3

页面布局解决方案

居中布局

水平居中

子元素相对于父元素居中且子元素宽度可变。

除了另外声明,HTML结构为以下内容:

<div class="parent">
    <div class="child">Demo</div>
</div>

inline-block + text-align

.parent {
    text-align: center;
}

.child {
    display: inline-block;
    width: 300px; /*宽度可变*/
    background: #ffff00;
}

优点

  • 兼容性好(甚至可以兼容 IE6IE7

table + margin

<div class="parent">
    <div class="child">Demo</div>
</div>

.parent {
    text-align: center;
}

.child {
    display: table;
    margin: 0 auto;
    width: 200px; /*宽度可变*/
    background: #ffff00;
}

NOTE: display: table 在表现上类似 block 元素,但是宽度为内容宽度。

优点

  • 不需要设置父元素样式 (支持 IE8 及其以上版本)

NOTE:兼容 IE8 以下版本需要调整为 <table> 的结果。

absolute + transform

.parent {
    position: relative;
    text-align: center;
}

.child {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    width: 200px; /*宽度可变*/
    background: #ffff00;
}

优点

  • 绝对定位脱离文档流,不会对后续元素的布局造成影响。
  • 子元素设置绝对定位 position: absolute;,父元素设置相对定位 position: relative; 是典型的定位方法,多用于为子元素设置定位的参考点。

缺点

  • transformCSS3 属性,有兼容性问题。

NOTE:transform属性的translateXtranslateY对元素进行旋转、缩放、移动或倾斜,其中移动功能可以用于定位。

flex + justify-content

.parent {
    display: flex;
    justify-content: center;
    text-align: center;
}

.child {
    width: 200px; /*宽度可变*/
    background: #ffff00;
}

/* 下面的方法,可以达到一样的效果 */
.parent {
    display: flex;
    text-align: center;
}

.child {
    margin: 0 auto;
    width: 200px; /*宽度可变*/
    background: #ffff00;
}

优点

  • 只需设置父元素属性,无需设置子元素。

优点

  • flex有兼容性问题。

垂直居中

子元素相对于父元素居中且子元素高度可变。

table-cell + vertical-align

.parent {
    display: table-cell;
    vertical-align: middle;
    height: 200px;
    background: #ffff00;
}

优点

  • 兼容性好(支持 IE8,以下版本需要调整页面结构至 table

absolute + transform

.parent {
    position: relative;
    width: 200px;
    height: 200px;
    background: #ffff00;
}

.child {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

优点

  • 绝对定位脱离文档流,不会对后续元素的布局造成影响。但如果绝对定位元素是唯一的元素则父元素也会失去高度。

缺点

  • transformCSS3 属性,有兼容性问题。

flex + align-items

.parent {
    display: flex;
    align-items: center; /*垂直居中*/
    justify-content: center; /*水平居中*/
    width: 200px;
    height: 200px;
    background: #ffff00;
}

优点

  • 只需设置父节点属性,无需设置子元素

缺点

  • 有兼容性问题

水平与垂直居中

水平与垂直居中的一般性布局在另一篇文章中有过总结,可以作为参考学习。

子元素相对于父元素水平垂直居中且其(子元素与父元素)高度宽度均可变。

inline-block + text-align + table-cell + vertical-align

.parent {
    text-align: center;
    display: table-cell;
    vertical-align: middle;
    width: 300px; /*宽度和高度均可变*/
    height: 300px;
    background: #ffff00;
}

.child {
    display: inline-block;
}

优点

  • 兼容性好

absolute + transform

.parent {
    position: relative;
    width: 300px; /*宽度和高度均可变*/
    height: 300px;
    background: #ffff00;
}

.child {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);

}

优点

  • 绝对定位脱离文档流,不会对后续元素的布局造成影响。

缺点

  • transformCSS3 属性,有兼容性问题。

flex + justify-content + align-items

.parent {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 300px; /*宽度和高度均可变*/
    height: 300px;
    background: #ffff00;
}

优点

  • 只需设置父节点属性,无需设置子元素

多列布局

多列布局在网页中很常见(例如两列布局),多列布局可以是两列定宽,一列自适应, 或者多列不定宽一列自适应,还有等分布局等。

一列定宽,一列自适应

除了另外声明,HTML结构为以下内容:

<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>

float + margin

p {
    margin: 0; /*清掉 p 标签的默认margin*/
}

.left {
    float: left;
    width: 100px;
    background: #ffff00;
}

.right {
    margin-left: 100px;
    background: #c7254e;
}

float + margin + (fix) 改造版

<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right-fix">
        <div class="right">
            <p>right</p>
            <p>right</p>
        </div>
    </div>
</div>

p {
    margin: 0; /*清掉 p 标签的默认margin*/
}

.left {
    float: left;
    width: 100px;
    background: #ffff00;
    position: relative;
}

.right-fix {
    float: right;
    width: 100%;
    margin-left: -100px;
}

.right {
    margin-left: 100px;
    background: #c7254e;
}

NOTE:此方法不会存在 IE63像素的 BUG,但 .left 不可选择, 需要设置 .left {position: relative} 来提高层级。 此方法可以适用于多版本浏览器(包括 IE6)。缺点是多余的 HTML 文本结构。

float + overflow

p {
    margin: 0; /*清掉 p 标签的默认margin*/
}

.left {
    float: left;
    width: 100px;
    background: #ffff00;
}

.right {
    overflow: hidden;
    background: #c7254e;
}

设置 overflow: hidden 会触发 BFC 模式(Block Formatting Context)块级格式化文本。 BFC 中的内容与外界的元素是隔离的。

overflow: hidden; 除了隐藏溢出内容外,还具有清除浮动的功能,具体实现是触发 BFC 或者 IFC,而这也是很常用的方法。overflow: hidden;对与父元素显示区域重叠部分进行切割,只在 BFC 区域显示,从而实现浮动的清除。

clear: both; 是经典的清除浮动方法,但它与 overflow: hidden;有很大的区别。clear: both;是清除父元素同一侧的浮动元素,即同一侧不允许存在其他浮动内容,子元素需换行显示。如果布局目标是同侧有其他浮动元素,可以选择 overflow: hidden;。这个特性称为浮动元素闭合。如果有对这个特性感兴趣或者研究透彻的朋友请多多指教,这个在解决高度坍塌、触发BFC等方面应用广泛,且非常实用。

table

.parent {
    display: table;
    width: 100%;
    table-layout: fixed;
}

.left {
    display: table-cell;
    width: 100px;
    background: #ffff00;
}

.right {
    display: table-cell;
    /*宽度为剩余宽度*/
    background: #c7254e;
}

table 的显示特性为每列的单元格宽度和一定等于表格宽度。 table-layout: fixed; 可加速渲染,也是设定布局优先。

NOTE:table-cell 中不可以设置 margin 但是可以通过 padding 来设置间距。

flex

.parent {
    display: flex;
}

.left {
    width: 100px;
    background: #ffff00;
}

.right {
    flex: 1;
    background: #c7254e;
}

NOTE:flex-item 默认为内容宽度。

缺点

  • 低版本浏览器兼容问题。
  • 性能问题,只适合小范围布局。

两列定宽,一列自适应

除了另外声明,HTML结构为以下内容:

<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="center">
        <p>center</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>
p {
    margin: 0; /*清掉 p 标签的默认margin*/
}

.left, .center {
    float: left;
    width: 100px;
    background: #ffff00;
}

.right {
    overflow: hidden;
    /*等价于*/
    /*flex: 1 1 0;*/
    background: #c7254e;
}

多列定宽的实现可以根据单列定宽的例子进行修改与实现。

一列不定宽 + 一列自适应

不定宽的宽度为内容决定,下面为可以实现此效果的方法:

  • float + overflow,此方法在 IE6 中有兼容性问题
  • table,此方法在 IE6 中有兼容性问题
  • flex,此方法在 IE9及其以下版本中有兼容性问题

多列不定宽 + 一列自适应

其解决方案同一列不定宽加一列自适应相仿。

多列等分布局

除了另外声明,HTML结构为以下内容:

<div class="parent">
    <div class="column">
        <p>1</p>
    </div>
    <div class="column">
        <p>2</p>
    </div>
    <div class="column">
        <p>3</p>
    </div>
    <div class="column">
        <p>4</p>
    </div>
</div>

float

.parent {
    /*margin-left: -20px;*/
}

.column {
    float: left;
    width: 25%;
    box-sizing: border-box;
    /*padding-left: 20px;*/
    background: #c7254e;
}

NOTE:此方法可以完美兼容 IE8 以上版本。 NOTE+:此方法结构和样式具有耦合性。

table

<div class='parent-fix'>
    <div class="parent">
        <div class="column">
            <p>1</p>
        </div>
        <div class="column">
            <p>2</p>
        </div>
        <div class="column">
            <p>3</p>
        </div>
        <div class="column">
            <p>4</p>
        </div>
    </div>
</div>

.parent-fix {
    /*margin-left: -20px;*/
}

.parent {
    display: table;
    width: 100%;
    /*可以布局优先,也可以单元格宽度平分在没有设置的情况下*/
    table-layout: fixed;
}

.column {
    display: table-cell;
    /*padding-left: 20px;*/
    background: #c7254e;
}

NOTE:缺点是多了文本结果

flex

.parent {
    display: flex;
}

.column {
    flex: 1;
    background: #c7254e;
}

NOTE:flex 的特性为分配剩余空间。 NOTE+:兼容性有问题。

两列等高布局

除了另外声明,HTML结构为以下内容:

<div class="parent">
    <div class="left">
        <p>left</p>
    </div>
    <div class="right">
        <p>right</p>
        <p>right</p>
    </div>
</div>

table

table 的特性为每列等宽,每行等高可以用于解决此需求。

.parent {
    display: table;
    width: 100%;
    table-layout: fixed;
}

.left {
    display: table-cell;
    background: #ffff00;
}

.right {
    display: table-cell;
    background: #c7254e;
}

flex

两列布局,一列定宽,一列自适应

.parent {
    display: flex;
}

.left {
    width: 100px;
    background: #ffff00;
}

.right {
    flex: 1;
    background: #c7254e;
}

float

.parent {
    overflow: hidden;
}

.left, .right {
    padding-bottom: 99px; 
    /*此处设置 9999px 很大的值,实际满足一定大小即可*/
    margin-bottom: -99px;
}

.left {
    float: left;
    width: 100px;
    background: #ffff00;
}

.right {
    overflow: hidden;
    background: #c7254e;
}

NOTE:此方法为伪等高(只有背景显示高度相等),左右真实的高度其实不相等。 NOTE+:此方法兼容性较好。

全屏布局

除了另外声明,HTML结构为以下内容:

<div class="parent">
    <div class="top"></div>
    <div class="middle">
        <div class="left"></div>
        <div class="right"></div>
    </div>
    <div class="bottom"></div>
</div>

定宽需求

图片描述

实现方案

  • position 常规方案
  • flex CSS3 新实现

position

<div class="parent">
    <div class="top"></div>
    <div class="left"></div>
    <div class="right"></div>
    <div class="bottom"></div>
</div>

html, body, .parent {
    height: 100%;
    /*用于隐藏滚动条*/
    overflow: hidden;
}

.top {
    /*相对于 body 定位*/
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 100px;
    background: #ffff00;
}

.left {
    position: absolute;
    top: 100px;
    left: 0;
    bottom: 50px;
    width: 200px;
    background: #c7254e;
}

.right {
    position: absolute;
    left: 200px;
    top: 100px;
    right: 0;
    bottom: 50px;
    overflow: auto;
    background: #5cb85c;
}

.bottom {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 50px;
    background: #2a6496;
}

Flex

html, body, .parent {
    height: 100%;
    /*用于隐藏滚动条*/
    overflow: hidden;
    margin: 0;
    padding: 0;
}

.parent {
    display: flex;
    flex-direction: column;
}

.top {
    height: 100px;
    background: #ffff00;
}

.bottom {
    height: 50px;
    background: #2a6496;
}

.middle {
    /*居中自适应*/
    display: flex;
    flex: 1;
    /*flex-direction: row 为默认值*/
}

.left {
    width: 200px;
    background: #c7254e;
}

.right {
    flex: 1;
    overflow: auto;
    background: #5cb85c;
}

百分比宽度需求

图片描述

只需把定宽高(px 为单位的值)的实现改成百分比(%)既可。

内容自适应

图片描述

只有右侧栏占据剩余位置,其余空间均需根据内容改变。 所以 postion 的定位方法不适合实现此方案。下面列出了两种布局方案:

  • flex
  • gridW3C 草案并不稳定,浏览器支持也并不理想。

flex

只有不给宽和高进行限制,即可对其中的内容做出自适应的布局。把定宽实现方案中设置了宽度和高度的部分去掉。


寒青
10.4k 声望3.8k 粉丝

« 上一篇
React 组件