2.CSS常用效果及实现

一、水平居中

(1)文本/行内元素/行内块级元素

#parent{
    text-align: center;
}

优缺点

  • 优点:简单快捷,容易理解,兼容性非常好
  • 缺点:只对行内内容有效;属性会继承影响到后代行内内容;如果子元素宽度大于父元素宽度则无效,只有后代行内内容中宽度小于设置text-align属性的元素宽度的时候,才会水平居中

(2)单个块级元素

#son{
    width: 100px; /*必须定宽*/
    margin: 0 auto;
}

优缺点

  • 优点:简单;兼容性好
  • 缺点:必须定宽,并且值不能为auto宽度要小于父元素,否则无效

(3)多个块级元素

#parent{
    text-align: center;
}
.son{
    display: inline-block; /*改为行内或者行内块级形式,以达到text-align对其生效*/
}

优缺点

  • 优点:简单,容易理解,兼容性非常好
  • 缺点:只对行内内容有效;属性会继承影响到后代行内内容;块级改为inline-block换行、空格会产生元素间隔

(4)使用绝对定位实现

#parent{
    height: 200px;
    width: 200px;  /*定宽*/
    position: relative;  /*父相*/
    background-color: #f00;
}
#son{
    position: absolute;  /*子绝*/
    left: 50%;  /*父元素宽度一半,这里等同于left:100px*/
    transform: translateX(-50%);  /*自身宽度一半,等同于margin-left: -50px;*/
    width: 100px;  /*定宽*/
    height: 100px;
    background-color: #00ff00;
}

优缺点

  • 优点:使用margin-left兼容性好;不管是块级还是行内元素都可以实现
  • 缺点:代码较多;脱离文档流;使用margin-left需要知道宽度值;使用transform兼容性不好(ie9+)

(5)任意个元素(flex)

#parent{
    display: flex;
    justify-content: center;
}

优缺点

  • 优点:功能强大;简单方便;容易理解
  • 缺点:PC端兼容性不好移动端(Android4.0+)

二、垂直居中

(1)单行文本/行内元素/行内块级元素

#parent{
    height: 150px;
    line-height: 150px;  /*与height等值*/
}

优缺点

  • 优点:简单;兼容性好
  • 缺点:只能用于单行行内内容;要知道高度的值

(2)多行文本/行内元素/行内块级元素

#parent{  /*或者用span把所有文字包裹起来,设置display:inline-block转换成图片的方式解决*/
    height: 150px;
    line-height: 30px;  /*元素在页面呈现为5行,则line-height的值为height/5*/
}

优缺点

  • 优点:简单;兼容性好
  • 缺点:只能用于行内内容;需要知道高度最终呈现多少行来计算出line-height的值,建议用span包裹多行文本

(3)图片

原理:vertical-align和line-height的基友关系

#parent{
    height: 150px;
    line-height: 150px;
    font-size: 0;
}
img#son{vertical-align: middle;} /*默认是基线对齐,改为middle*/

优缺点

  • 优点:简单;兼容性好
  • 缺点:需要添加font-size: 0; 才可以完全的垂直居中;不过需要主要,html#parent包裹img之间需要有换行或空格

(4)单个块级元素

//html代码:

<div id="parent">
    <div id="son"></div>
</div>

(4-1) 使用tabel-cell实现:

#parent{
    display: table-cell;
    vertical-align: middle;
}

优缺点

  • 优点:简单;宽高不定;兼容性好(ie8+)
  • 缺点:设置tabl-cell的元素,宽度和高度的值设置百分比无效,需要给它的父元素设置display: table; 才生效;table-cell不感知margin,在父元素上设置table-row等属性,也会使其不感知height;设置float或position会对默认布局造成破坏,可以考虑为之增加一个父div定义float等属性;内容溢出时会自动撑开父元素

(4-2) 使用绝对定位实现:

/*原理:子绝父相,top、right、bottom、left的值是相对于父元素尺寸的,然后margin或者transform是相对于自身尺寸的,组合使用达到水平居中的目的*/
#parent{
    height: 150px;
    position: relative;  /*父相*/
}
#son{
    position: absolute;  /*子绝*/
    top: 50%;  /*父元素高度一半,这里等同于top:75px;*/
    transform: translateY(-50%);  /*自身高度一半,这里等同于margin-top:-25px;*/
    height: 50px;
}

/*优缺点
- 优点:使用margin-top兼容性好;不管是块级还是行内元素都可以实现
- 缺点:代码较多;脱离文档流;使用margin-top需要知道高度值;使用transform兼容性不好(ie9+)*/

或

/*原理:当top、bottom为0时,margin-top&bottom会无限延伸占满空间并且平分*/
#parent{position: relative;}
#son{
    position: absolute;
    margin: auto 0;
    top: 0;
    bottom: 0;
    height: 50px;
}

/*优缺点
- 优点:简单;兼容性较好(ie8+)
- 缺点:脱离文档流*/

(4-3) 使用flex实现:

#parent{
    display: flex;
    align-items: center;
}

或

#parent{display: flex;}
#son{align-self: center;}

或
/*原理:这个尚未搞清楚,应该是flex使margin上下边界无限延伸至剩余空间并平分了*/
#parent{display: flex;}
#son{margin: auto 0;}

优缺点

  • 优点:简单灵活;功能强大
  • 缺点:PC端兼容性不好,移动端(Android4.0+)

(5)任意个元素(flex)

#parent{
    display: flex;
    align-items: center;
}

或

#parent{
    display: flex;
}
.son{
    align-self: center;
}

或 

#parent{
    display: flex;
    flex-direction: column;
    justify-content: center;
}

优缺点

  • 优点:简单灵活;功能强大
  • 缺点:PC端兼容性不好移动端(Android4.0+)

三、水平垂直居中

(1)行内/行内块级/图片

#parent{
    height: 150px;
    line-height: 150px;  /*行高的值与height相等*/
    text-align: center;
    font-size: 0;   /*消除幽灵空白节点的bug*/
}
#son{
    /*display: inline-block;*/  /*如果是块级元素需改为行内或行内块级才生效*/
    vertical-align: middle;
}

优缺点

  • 优点:代码简单;兼容性好(ie8+)
  • 缺点:只对行内内容有效;需要添加font-size: 0; 才可以完全的垂直居中;不过需要注意html中#parent包裹#son之间需要有换行或空格;熟悉line-height和vertical-align的基友关系较难

(2)table-cell

#parent{
    height: 150px;
    width: 200px;
    display: table-cell;
    vertical-align: middle;
    /*text-align: center;*/   /*如果是行内元素就添加这个*/
}
#son{
    /*margin: 0 auto;*/    /*如果是块级元素就添加这个*/
    width: 100px;
    height: 50px;
}

优缺点

优点:简单;适用于宽度高度未知情况;兼容性好(ie8+)
缺点:设置tabl-cell的元素,宽度和高度的值设置百分比无效,需要给它的父元素设置display: table; 才生效;table-cell不感知margin,在父元素上设置table-row等属性,也会使其不感知height;设置float或position会对默认布局造成破坏,可以考虑为之增加一个父div定义float等属性;内容溢出时会自动撑开父元素

(3)button作为父元素

//原理:button的默认样式,再把需要居中的元素表现形式改为行内或行内块级

button#parent{  /*改掉button默认样式就好了,不需要居中处理*/
    height: 150px;
    width: 200px;
    outline: none;  
    border: none;
}
#son{
    display: inline-block; /*button自带text-align: center,改为行内水平居中生效*/
}

优缺点

  • 优点:简单方便,充分利用默认样式
  • 缺点:只适用于行内内容;需要清除部分默认样式;水平垂直居中兼容性很好,但是ie下点击会有凹陷效果

(4)绝对定位

#parent{
    position: relative;
}
#son{
    position: absolute;
    top: 50%;
    left: 50%;
    /*定宽高时等同于margin-left:负自身宽度一半;margin-top:负自身高度一半;*/
    transform: translate(-50%,-50%); 
}

优缺点

  • 优点:使用margin兼容性好;不管是块级还是行内元素都可以实现
  • 缺点:代码较多;脱离文档流;使用margin需要知道宽高;使用transform兼容性不好(ie9+)

(5)绝对居中

#parent{
    position: relative;
}
#son{
    position: absolute;
    margin: auto;
    width: 100px;
    height: 50px;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

优缺点

  • 优点:无需关注宽高;兼容性较好(ie8+)
  • 缺点:代码较多;脱离文档流

(6)flex

#parent{
    display: flex;
}
#son{
    margin: auto;
}

或

#parent{
    display: flex;
    justify-content: center;
    align-items: center;
}

或

#parent{
    display: flex;
    justify-content: center;
}
#son{
    align-self: center;
}

(7)视窗居中

//原理:vh为视口单位,视口即文档可视的部分,50vh就是视口高度的50/100,设置50vh上边距再transform变换
#son{
    /*0如果去掉,则会多出滚动条并且上下都是50vh的margin。如果去掉就给body加上overflow:hidden;*/
    margin: 50vh auto 0;  
    transform: translateY(-50%);
}

优缺点

  • 优点:简单;容易理解;两句代码达到屏幕水平垂直居中
  • 缺点:兼容性不好(ie9+,Android4.4+)

四、两列布局

4.1 左列定宽,右列自适应

效果图.png

(1)利用float+margin实现

//html代码:
<body>
<div id="left">左列定宽</div>
<div id="right">右列自适应</div>
</body>

//css代码:
#left {
    background-color: #f00;
    float: left;
    width: 100px;
    height: 500px;
}
#right {
    background-color: #0f0;
    height: 500px;
    margin-left: 100px; /*大于等于#left的宽度*/
}

(2)利用float+margin(fix)实现

//html代码:
<body>
<div id="left">左列定宽</div>
<div id="right-fix">
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#left {
    background-color: #f00;
    float: left;
    width: 100px;
    height: 500px;
}
#right-fix {
    float: right;
    width: 100%;
    margin-left: -100px; /*正值大于或等于#left的宽度,才能显示在同一行*/
}
#right{
    margin-left: 100px; /*大于或等于#left的宽度*/
    background-color: #0f0;
    height: 500px;
}

(3)使用float+overflow实现

//html代码:
<body>
<div id="left">左列定宽</div>
<div id="right">右列自适应</div>
</body>

//css代码:
#left {
    background-color: #f00;
    float: left;
    width: 100px;
    height: 500px;
}
#right {
    background-color: #0f0;
    height: 500px;
    overflow: hidden; /*触发bfc达到自适应*/
}

优缺点:

  • 优点:代码简单,容易理解,无需关注定宽的宽度,利用bfc达到自适应效果
  • 缺点:浮动脱离文档流,需要手动清除浮动,否则会产生高度塌陷;不支持ie6
    (4)使用table实现
//html代码:
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="right">右列自适应</div>
</div>

//css代码:
#parent{
    width: 100%;
    display: table;
    height: 500px;
}
#left {
    width: 100px;
    background-color: #f00;
}
#right {
    background-color: #0f0;
}
#left,#right{
    display: table-cell;  /*利用单元格自动分配宽度*/
}

优缺点:

  • 优点:代码简单,容易理解,无需关注定宽的宽度,利用单元格自动分配达到自适应效果
  • 缺点:margin失效设置间隔比较麻烦不支持ie8-
    (5)使用绝对定位实现
//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent{
    position: relative;  /*子绝父相*/
}
#left {
    position: absolute;
    top: 0;
    left: 0;
    background-color: #f00;
    width: 100px;
    height: 500px;
}
#right {
    position: absolute;
    top: 0;
    left: 100px;  /*值大于等于#left的宽度*/
    right: 0;
    background-color: #0f0;
    height: 500px;
}

(6)使用flex实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent{
    width: 100%;
    height: 500px;
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;
}
#left {
    width: 100px;
    background-color: #f00;
}
#right {
    -webkit-box-flex: 1;
    -webkit-flex: 1;
    -ms-flex: 1;
    flex: 1; /*均分了父元素剩余空间*/
    background-color: #0f0;
}

(7)使用Grid实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent {
    width: 100%;
    height: 500px;
    display: grid;
    grid-template-columns: 100px auto;  /*设定2列就ok了,auto换成1fr也行*/
}
#left {
    background-color: #f00;
}
#right {
    background-color: #0f0;
}

4.3 一列不定,一列自适应

(盒子宽度随着内容增加或减少发生变化,另一个盒子自适应)

效果图:

效果图.png

变化后:

变化后.png

(1)使用float+overflow实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列不定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#left {
    margin-right: 10px;
    float: left;  /*只设置浮动,不设宽度*/
    height: 500px;
    background-color: #f00;
}
#right {
    overflow: hidden;  /*触发bfc*/
    height: 500px;
    background-color: #0f0;
}

优缺点:

  • 优点:代码简单,容易理解,无需关注宽度利用bfc达到自适应效果
  • 缺点:浮动脱离文档流,需要手动清除浮动,否则会产生高度塌陷不支持ie6
    (2)使用flex实现
//html代码:
<body>
<div id="parent">
    <div id="left">左列不定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent{
    display: flex;//未写兼容代码
}
#left { /*不设宽度*/
    margin-right: 10px;
    height: 500px;
    background-color: #f00;
}
#right {
    height: 500px;
    background-color: #0f0;
    flex: 1;  /*均分#parent剩余的部分*/
}

(3)使用Grid实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列不定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent{
    display: grid;
    grid-template-columns: auto 1fr;  /*auto和1fr换一下顺序就是左列自适应,右列不定宽了*/
}
#left {
    margin-right: 10px;
    height: 500px;
    background-color: #f00;
}
#right {
    height: 500px;
    background-color: #0f0;
}

五、三列布局

5.1 两列定宽,一列自适应

效果图:


效果图.png

(1)使用float+margin实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="center">中间定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent{
    min-width: 310px; /*100+10+200,防止宽度不够,子元素换行*/
}
#left {
    margin-right: 10px;  /*#left和#center间隔*/
    float: left;
    width: 100px;
    height: 500px;
    background-color: #f00;
}
#center{
    float: left;
    width: 200px;
    height: 500px;
    background-color: #eeff2b;
}
#right {
    margin-left: 320px;  /*等于#left和#center的宽度之和加上间隔,多出来的就是#right和#center的间隔*/
    height: 500px;
    background-color: #0f0;
}

(2)使用float+overflow实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="center">中间定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

css代码:
#parent{
    min-width: 320px; /*100+10+200+20,防止宽度不够,子元素换行*/
}
#left {
    margin-right: 10px; /*间隔*/
    float: left;
    width: 100px;
    height: 500px;
    background-color: #f00;
}
#center{
    margin-right: 10px; /*在此定义和#right的间隔*/
    float: left;
    width: 200px;
    height: 500px;
    background-color: #eeff2b;
}
#right {
    overflow: hidden;  /*触发bfc*/
    height: 500px;
    background-color: #0f0;
}

优缺点:

  • 优点:代码简单,容易理解,无需关注定宽的宽度利用bfc达到自适应效果
  • 缺点:浮动脱离文档流,需要手动清除浮动,否则会产生高度塌陷不支持ie6

(3)使用table实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="center">中间定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent {
    width: 100%; 
    height: 520px; /*抵消上下间距10*2的高度影响*/
    margin: -10px 0;  /*抵消上下边间距10的位置影响*/
    display: table;
    /*左右两边间距大了一点,子元素改用padding设置盒子间距就没有这个问题*/
    border-spacing: 10px;  /*关键!!!设置间距*/
}
#left {
    display: table-cell;
    width: 100px;
    background-color: #f00;
}
#center {
    display: table-cell;
    width: 200px;
    background-color: #eeff2b;
}
#right {
    display: table-cell;
    background-color: #0f0;
}

优缺点:

  • 优点:代码简单,容易理解,无需关注定宽的宽度,利用单元格自动分配达到自适应效果
  • 缺点:margin失效设置间隔比较麻烦不支持ie8-

(4)使用flex实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="center">中间定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent {
    height: 500px;
    display: flex;
}
#left {
    margin-right: 10px;  /*间距*/
    width: 100px;
    background-color: #f00;
}
#center {
    margin-right: 10px;  /*间距*/
    width: 200px;
    background-color: #eeff2b;
}
#right {
    flex: 1;  /*均分#parent剩余的部分达到自适应*/
    background-color: #0f0;
}

(5)使用Grid实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="center">中间定宽</div>
    <div id="right">右列自适应</div>
</div>
</body>

//css代码:
#parent {
    height: 500px;
    display: grid;
    grid-template-columns: 100px 200px auto; /*设置3列,固定第一第二列的宽度,第三列auto或者1fr*/
}
#left {
    margin-right: 10px;  /*间距*/
    background-color: #f00;
}
#center {
    margin-right: 10px;  /*间距*/
    background-color: #eeff2b;
}
#right {
    background-color: #0f0;
}

5.2 两侧定宽,中间自适应

效果图:


效果图.png

5.2.1 双飞翼布局方法

//html代码:
<body>
<div id="header"></div>
<!--中间栏需要放在前面-->
<div id="parent">
    <div id="center">
        <div id="center_inbox">中间自适应</div>
        <hr>  <!--方便观察原理-->
    </div>
    <div id="left">左列定宽</div>
    <div id="right">右列定宽</div>
</div>
<div id="footer"></div>
</body>

//css代码:
#header {
    height: 60px;
    background-color: #ccc;
}
#left {
    float: left;
    width: 100px;
    height: 500px;
    margin-left: -100%; /*调整#left的位置,值等于自身宽度*/
    background-color: #f00;
    opacity: 0.5;
}
#center {
    height: 500px;
    float: left;
    width: 100%;
    background-color: #eeff2b;
}
#center_inbox{
    height: 480px;
    border: 1px solid #000;
    margin: 0 220px 0 120px;  /*关键!!!左右边界等于左右盒子的宽度,多出来的为盒子间隔*/
}
#right {
    float: left;
    width: 200px;
    height: 500px;
    margin-left: -200px;  /*使right到指定的位置,值等于自身宽度*/
    background-color: #0f0;
    opacity: 0.5;
}
#footer {
    clear: both;  /*注意清除浮动!!*/
    height: 60px;
    background-color: #ccc;
}

5.2.2 圣杯布局方法

效果图:


效果图.png
//html代码:
<body>
<div id="header"></div>
<div id="parent">
    <!--#center需要放在前面-->
    <div id="center">中间自适应
        <hr>
    </div>
    <div id="left">左列定宽</div>
    <div id="right">右列定宽</div>
</div>
<div id="footer"></div>
</body>

//css代码:
#header{
    height: 60px;
    background-color: #ccc;
}
#parent {
    box-sizing: border-box;
    height: 500px;
    padding: 0 215px 0 115px;  /*为了使#center摆正,左右padding分别等于左右盒子的宽,可以结合左右盒子相对定位的left调整间距*/
}
#left {
    margin-left: -100%;  /*使#left上去一行*/
    position: relative;
    left: -115px;  /*相对定位调整#left的位置,正值大于或等于自身宽度*/
    float: left;
    width: 100px;
    height: 500px;
    background-color: #f00;
    opacity: 0.5;
}
#center {
    float: left;
    width: 100%;  /*由于#parent的padding,达到自适应的目的*/
    height: 500px;
    box-sizing: border-box;
    border: 1px solid #000;
    background-color: #eeff2b;
}
#right {
    position: relative;
    left: 215px; /*相对定位调整#right的位置,大于或等于自身宽度*/
    width: 200px;
    height: 500px;
    margin-left: -200px;  /*使#right上去一行*/
    float: left;
    background-color: #0f0;
    opacity: 0.5;
}
#footer{
    height: 60px;
    background-color: #ccc;
}

5.2.3 使用Grid实现

效果图:

html代码:
<body>
<div id="parent">
    <div id="header"></div>
    <!--#center需要放在前面-->
    <div id="center">中间自适应
        <hr>
    </div>
    <div id="left">左列定宽</div>
    <div id="right">右列定宽</div>
    <div id="footer"></div>
</div>
</body>

css代码:
#parent {
    height: 500px;
    display: grid;
    grid-template-columns: 100px auto 200px; /*设定3列*/
    grid-template-rows: 60px auto 60px; /*设定3行*/
    /*设置网格区域分布*/
    grid-template-areas: 
        "header header header" 
        "leftside main rightside" 
        "footer footer footer";
}
#header {
    grid-area: header; /*指定在哪个网格区域*/
    background-color: #ccc;
}
#left {
    grid-area: leftside;
    background-color: #f00;
    opacity: 0.5;
}
#center {
    grid-area: main; /*指定在哪个网格区域*/
    margin: 0 15px; /*设置间隔*/
    border: 1px solid #000;
    background-color: #eeff2b;
}
#right {
    grid-area: rightside; /*指定在哪个网格区域*/
    background-color: #0f0;
    opacity: 0.5;
}
#footer {
    grid-area: footer; /*指定在哪个网格区域*/
    background-color: #ccc;
}

5.2.4 其他方法

(1)使用table实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="center">中间自适应</div>
    <div id="right">右列定宽</div>
</div>
</body>

//css代码:
#parent {
    width: 100%;
    height: 500px;
    display: table;
}
#left {
    display: table-cell;
    width: 100px;
    background-color: #f00;
}
#center {
    display: table-cell;
    background-color: #eeff2b;
}
#right {
    display: table-cell;
    width: 200px;
    background-color: #0f0;
}

优缺点:

  • 优点:代码简洁,容易理解;
  • 缺点:margin失效,采用border-spacing表格两边的间隔无法消除不支持ie8-

(2)使用flex实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="center">中间自适应</div>
    <div id="right">右列定宽</div>
</div>
</body>

//css代码:
#parent {
    height: 500px;
    display: flex;
}
#left {
    width: 100px;
    background-color: #f00;
}
#center {
    flex: 1;  /*均分#parent剩余的部分*/
    background-color: #eeff2b;
}
#right {
    width: 200px;
    background-color: #0f0;
}

(3)使用position实现

//html代码:
<body>
<div id="parent">
    <div id="left">左列定宽</div>
    <div id="center">中间自适应</div>
    <div id="right">右列定宽</div>
</div>
</body>

//css代码:
#parent {
    position: relative; /*子绝父相*/
}
#left {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 500px;
    background-color: #f00;
}
#center {
    height: 500px;
    margin-left: 100px; /*大于等于#left的宽度,或者给#parent添加同样大小的padding-left*/
    margin-right: 200px;  /*大于等于#right的宽度,或者给#parent添加同样大小的padding-right*/
    background-color: #eeff2b;
}
#right {
    position: absolute;
    top: 0;
    right: 0;
    width: 200px;
    height: 500px;
    background-color: #0f0;
}

优缺点:

  • 优点:容易理解,兼容性比较好
  • 缺点:需手动计算宽度确定边距脱离文档流代码繁多

六、多列布局

6.1多列等宽

效果图:

效果图.png

(1)使用float实现

//html代码:
<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">5 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">6 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

//css代码:
#parent {
    height: 500px;
}
.column{
    float: left;  /*添加浮动*/
    width: 16.66666666666667%;  /*100÷列数,得出百分比*/
    height: 500px;
}
.column:nth-child(odd){
    background-color: #f00;
}
.column:nth-child(even){
    background-color: #0f0;
}

优缺点:

  • 优点:代码简单,容易理解;兼容性较好
  • 缺点:需要手动清除浮动,否则会产生高度塌陷

(2)使用table实现

//html代码
<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">5 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">6 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

//css代码:
#parent {
    width: 100%;
    height: 500px;
    display: table;
}
.column{
    display: table-cell; /*无需关注列数,单元格自动平分*/
}
.column:nth-child(odd){
    background-color: #f00;
}
.column:nth-child(even){
    background-color: #0f0;
}

优缺点:

  • 优点:代码简单,容易理解;无需关注宽度。单元格自动等分
  • 缺点:margin失效;设置间隔比较麻烦;不兼容ie8-

(3)使用flex实现

//html代码:
<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">5 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">6 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

//css代码:
#parent {
    height: 500px;
    display: flex;
}
.column{
    flex: 1;  /*无需关注列数,一起平分#parent*/
}
.column:nth-child(odd){
    background-color: #f00;
}
.column:nth-child(even){
    background-color: #0f0;
}

(4)使用Grid实现

//html代码:
<body>
<div id="parent">
    <div class="column">1 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">2 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">3 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">4 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">5 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
    <div class="column">6 <p>我是文字我是文字我输文字我是文字我是文字</p></div>
</div>
</body>

//css代码:
#parent {
    height: 500px;
    display: grid;
    grid-template-columns: repeat(6,1fr);  /*6就是列数*/
}
.column{}
.column:nth-child(odd){
    background-color: #f00;
}
.column:nth-child(even){
    background-color: #0f0;
}

6.2 九宫格布局

效果图:


效果图.png

(1)使用table实现

//html代码:
<body>
<div id="parent">
    <div class="row">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
    </div>
    <div class="row">
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
    </div>
    <div class="row">
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
    </div>
</div>
</body>

//css代码:
#parent {
    width: 1200px;
    height: 500px;
    margin: 0 auto;
    display: table;
}
.row {
    display: table-row;
}
.item {
    border: 1px solid #000;
    display: table-cell;
}

优缺点:

优点:代码简洁,容易理解;
缺点:margin失效,采用border-spacing表格两边的间隔无法消除不支持ie8-

(2)使用flex实现

//html代码:
<body>
<div id="parent">
    <div class="row">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
    </div>
    <div class="row">
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
    </div>
    <div class="row">
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
    </div>
</div>
</body>

//css代码:
#parent {
    width: 1200px;
    height: 500px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
}
.row {
    display: flex;
    flex: 1;
}
.item {
    flex: 1;
    border: 1px solid #000;
}

(3)使用Grid实现

//html代码:
<body>
<div id="parent">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
</div>
</body>

//css代码:
#parent {
    width: 1200px;
    height: 500px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: repeat(3, 1fr); /*等同于1fr 1fr 1fr,此为重复的合并写法*/
    grid-template-rows: repeat(3, 1fr);  /*等同于1fr 1fr 1fr,此为重复的合并写法*/
}
.item {
    border: 1px solid #000;
}

七、全屏布局

效果图:


效果图.png

(1)使用绝对定位实现

//html代码:
<body>
<div id="parent">
    <div id="top">top</div>
    <div id="left">left</div>
    <div id="right">right</div>
    <div id="bottom">bottom</div>
</div>
</body>

//css代码:
html, body, #parent {height: 100%;overflow: hidden;}
#parent > div {
    border: 1px solid #000;
}
#top {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 100px;
}
#left {
    position: absolute;
    top: 100px;  /*值大于等于#top的高度*/
    left: 0;
    bottom: 50px;  /*值大于等于#bottom的高度*/
    width: 200px;
}
#right {
    position: absolute;
    overflow: auto;
    left: 200px;  /*值大于等于#left的宽度*/
    right: 0;
    top: 100px;  /*值大于等于#top的高度*/
    bottom: 50px;  /*值大于等于#bottom的高度*/
}
#bottom {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 50px;
}

优缺点:

  • 优点:容易理解
  • 缺点:代码繁多;需要计算好各个盒子的宽高

(2)使用flex实现

//html代码:
<body>
<div id="parent">
    <div id="top">top</div>
    <div id="middle">
        <div id="left">left</div>
        <div id="right">right</div>
    </div>
    <div id="bottom">bottom</div>
</div>
</body>

//css代码:
*{
    margin: 0;
    padding: 0;
}
html,body,#parent{
    height:100%;
}
#parent {
    display: flex;
    flex-direction: column;
}
#top {
    height: 100px;
}
#bottom {
    height: 50px;
}
#middle {
    flex: 1;
    display: flex;
}
#left {
    width: 200px;
}
#right {
    flex: 1;
    overflow: auto;
}

(3)使用Grid实现

//html代码:
<body>
<div id="parent">
    <div id="top">top</div>
    <div id="left">left</div>
    <div id="right">right</div>
    <div id="bottom">bottom</div>
</div>
</body>

//css代码:
*{
    margin: 0;
    padding: 0;
}
html, body, #parent {
    height: 100%;
}
#parent {
    width: 100%;
    height: 100%;
    display: grid;
    /*分成2列,第一列宽度200px,第二列1fr平分剩余的部分,此处换成auto也行*/
    grid-template-columns: 200px 1fr;  
    /*分成3行,第一行高度100px,第二行auto为自适应,此处换成1fr也行,第3行高度为50px*/
    grid-template-rows: 100px auto 50px; 
    /*定义网格区域分布*/
    grid-template-areas:
        "header header"
        "aside main"
        "footer footer";
}
#parent>div{
    border: 1px solid #000;
}
#top{
    grid-area: header;  /*指定在哪个网格区域*/
}
#left{
    grid-area: aside;  /*指定在哪个网格区域*/
}
#right{
    grid-area: main;  /*指定在哪个网格区域*/
}
#bottom{
    grid-area: footer;  /*指定在哪个网格区域*/
}

九、其他补充:

9.1 移动端viewport

设置viewport:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

阅读推荐:
《解读 viewport—网页自适应移动 app 神器》

9.2 媒体查询

@media (max-width: 767px) { ...css代码... }
@media (min-width: 768px) and (max-width: 991px) { ...css代码... }
@media (min-width: 992px) and (max-width: 1199px) { ...css代码... }
@media (min-width: 1200px) { ...css代码... }

阅读推荐:
《MDN文档介绍》
《随方逐圆 -- 全面理解 CSS 媒体查询》

9.3 REM

阅读推荐:
《Rem布局的原理解析》
《rem是如何实现自适应布局的?》

9.4 Flexbox

阅读推荐:
《理解Flexbox:你需要知道的一切》
《深入理解 flex 布局以及计算》

9.5 CSS Grid

阅读推荐:
《grid布局学习指南》
《grid规范草稿》


参考资料:
《干货!各种常见布局实现+知名网站实例分析》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351