CSS 多种布局方式

268 阅读10分钟

​css布局是工作中最常碰到的,同时也是笔试 or 面试中会被问到的问题,故在本文整理了css多种布局方式,以供参考。

此篇较长四千五百字左右,读者可分三部分阅读,水平居中布局,垂直居中布局,水平居中对齐。

水平居中布局

水平居中布局,指当前元素在父级元素中的水平方向上是居中,如:

实现水平居中的方法有很多,我们一个一个来看。

1、inline-block + text-align

  • 设置子元素为一个 inline-block 元素
  • 设置父元素 text-align: center;  

代码如下:

<div id="parent">
    <div id="children"></div>
</div>
#parent {  
    width: 300px;  
    height: 200px;  
    background-color: aquamarine; /*海蓝色*/    
    text-align: center;}
    
#children {  
    width: 100px;  
    height: 100px;  
    background-color: pink; /*粉色*/    
    display: inline-block;
    }

解读:  

1、给父元素设置 text-align: center; 是何用意?

css 属性 text-align 的作用是定义行内内容(例如 文字)如何相对于它的块父元素对齐。

text-align 的值有很多,最常用的:

  • left 左对齐
  • right 右对齐
  • center 居中对齐

所以,通过text-align: center;,就可以让内部的行内子元素居中对齐了。

注意⚠️:text-align 并不控制块元素自己的对齐,而是只控制它的行内内容的对齐。

拓展阅读:text-align。

2、给子元素设置 display: inline-block; 是何用意?

通过第一步,我们了解了,要想子元素居中,该元素就需要是一个行内元素,但是子元素children 是一个div 块级元素,所以我们就需要把它变为行内元素,变为行内元素很简单,设置display: inline; 即可,但是从css中我们可以看到,该元素设置了width & height,inline 行内元素设置宽度和高度是不生效的,所以,我们就必须设置 display: inline-block; 将其变为行内块元素,结合行内元素和块级元素的特点,既能设置宽高,又为一个行内元素,此时居中效果就生效了。

拓展阅读:inline、block、inline-block。

优点: 

浏览器兼容性好。

由于text-align:center; 和 display: inline-block 都为css2中的内容,老版本的浏览器对于CSS2的支持是很友好的。

缺点: 

text-align 具有继承性,会导致子元素中的文本也是居中显示的。

如下,在子元素中添加文本:

<div id="parent">
    <div id="children">文本</div>
</div>

效果:

会看到,文本内容自动水平居中了。

如果不想要文本水平居中的效果该怎么办?如想要文本左对齐,那么就需要在子元素中设置text-align: left; 了。

2、margin + block

  • 设置子元素的margin margin: 0 auto;
  • 设置子元素为一个 block 元素

代码如下:

<div id="parent">  
    <div id="children"></div>
</div>
#parent {  
    width: 300px;  
    height: 200px;  
    background-color: aquamarine;
    }
    
#children {  
    width: 100px;  
    height: 100px;
    background-color: pink;
    
    margin: 0 auto;
    display: block;
    }

解读: 

1、给子元素设置 margin: 0 auto; 是何用意?

margin是一个简写属性,当给一个元素设置 margin: 0 auto; 时,设置的其实是:

  • margin-top 为 0
  • margin-right 为 auto
  • margin-bottom 为 0
  • margin-left 为 auto

如果两侧均为auto的话,则平分剩余空间,那么设置左右为auto后,元素自然而然就水平居中了。

2、为何需要给子元素设置 display: block; ?

阅读了第一条的解释后,有些同学可能会很迷惑,设置 margin: 0 auto; 就可以将元素设置为居中对齐了,为什么还要再次设置 diaplay: block; 呢?

是这样的,当元素的 display 为 inlineinline-blockinline-table 时,给元素的 margin 设置为 auto 时,最终设置的值,等价于 0。所以一旦要使用 margin: 0 auto; 进行水平居中布局,就避免让元素为以上三种 display ,直接设置为 block 就好了。当然,如果子元素本身就为块级元素,那么就不需要再单独设置 display 为 block 了。所以上面代码中的 display: block; 可以删除掉。

优点: 

只需要对子元素进行特殊设置,就可以实现水平居中布局。

缺点: 

如果子元素脱离文档流,那么会导致margin失效

在css中进行以下几个设置时,元素会脱离文档流:

  • float: left;
  • float: right;
  • position: absolute;
  • position: fixed;

3、position + 负margin

  • 设置父元素为相对定位
  • 设置子元素为绝对定位
  • 设置子元素 left 为 50%
  • 设置子元素 margin 为 -1/2*width (宽度一半的负值)

代码如下:

<div id="parent">
    <div id="children"></div>
</div>
parent {  
    width: 300px; 
    height: 200px; 
    background-color: aquamarine;​ 
    
    position: relative;
    }
    
#children {
    width: 100px;
    height: 100px;
    background-color: pink;
    
    position: absolute;
    left: 50%;
    margin-left: -50px;
    }

解读: 

1、为了让子元素相对于父元素进行定位,所以设置父元素相对定位、子元素绝对定位

2、为了让元素在中间,所以设置子元素的 left 为 50% 。让子元素距离父元素的左边的距离是 父元素宽度的一半,即 150px 。

3、由于 150px 过大,会导致子元素位置向右偏,如:

4、所以,要设置,让元素向左移动自己宽度的一半,回到正中间,所以设置了 margin-left 为 -50px 。

优点:

无论父元素是否脱离文档流,都不影响子元素水平居中的效果。

缺点: 

必须要明确子元素的宽度,否则没有办法设置 margin-left 的值。

4、position + translateX

  • 设置父元素为相对定位
  • 设置子元素为绝对定位
  • 设置子元素 left 为 50% 
  • 设置子元素 translateX 为 -50%

代码如下:

<div id="parent">
    <div id="children"></div>
</div>
#parent {
    width: 300px;
    height: 200px;
    background-color: aquamarine;
    
    position: relative;
    }

#children {  
    width: 100px; 
    height: 100px;  
    background-color: pink;​ 
    
    position: absolute; 
    left: 50%;
    transform: translateX(-50%);
    }

解读: 

和上一个的方法一样,需要让子元素向左移动自己的宽度的一半,除了用 margin 之外,也可以使用 translateX 让元素在水平方向上偏移,当给 translateX 的参数设置为 -50% 时,即为向左移动自己宽度的一半。

优点: 

无论父元素是否脱离文档流,都不影响子元素水平居中的效果。

缺点: 

transform 是 CSS3中新增的属性,所以不兼容部分老浏览器。

兼容性查询:www.caniuse.com/#search=tra…

5、flex + justify-content

  • 设置父元素的 dispaly 为 flex
  • 设置父元素的 justify-content 为 center

代码如下:

<div id="parent">
    <div id="children"></div>
</div>
#parent {
    width: 300px;
    height: 200px;
    background-color: aquamarine;​
    
    display: flex; 
    justify-content: center;
    }​
    
#children {  
    width: 100px; 
    height: 100px;
    background-color: pink;
    }

解读: 

设置 display 为 flex 的父元素其主轴上元素的排列方式为居中。

优点: 

无论父元素是否脱离文档流,都不影响子元素水平居中的效果。

缺点: 

1、flex 是 CSS3中新增的内容,所以不兼容部分老浏览器。

兼容性查询:www.caniuse.com/#search=fle…

2、使用此种方式,会让父元素内的其他子元素也全部水平居中,如下,在父元素中添加其他子元素:

<div id="parent">
    <div id="children"></div>
    <div id="other-item"></div>
</div>
#parent { 
    width: 300px;  
    height: 200px; 
    background-color: aquamarine;​
    
    display: flex;
    justify-content: center;
    }​

#children { 
    width: 100px; 
    height: 100px; 
    background-color: pink;
    }

#other-item {
    width: 100px;  
    height: 30px;  
    background-color: salmon;
    }

效果如下:

若父元素内有其他子元素不需要水平居中处理,则可以考虑不使用这种方式。

垂直居中布局

垂直居中布局,指当前元素在父级元素中的垂直方向上时居中,如:

以下为实现垂直居中的方法

1、vertical-align+table-cell

  • 设置父元素的 vertical-align 为 middle 
  • 设置父元素的 display 为 table-cell

代码如下:

<div id="parent">
    <div id="children"></div>
</div>
#parent {
    width: 300px;  
    height: 200px;  
    background-color: aquamarine;​
    
    display: table-cell;
    vertical-align: middle;
    }​

#children {
    width: 100px;
    height: 100px; 
    background-color: pink;
    }

解读: 

1、属性 vertical-align 用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐方式,当给 table-cell 元素设置 vertical-align: middle; 时,表示让该单元格元素内部的盒模型在该行内居中对齐。

2、由1可知,元素需为 table-cell ,所以设置 display 为 table-cell

优点: 

浏览器兼容性好。

由于 vertical-align: middle; 和 display: table-cell; 都为css2中的内容,老版本的浏览器对于CSS2的支持是很友好的。

缺点: 

vertical-align 会导致父级元素中的全部元素都一起居中显示。

如下,在父元素中添加元素:

<div id="parent">
    文本 
    <div id="children"></div>
    <div id="other-item"></div>
</div>
#parent {
    width: 300px; 
    height: 200px; 
    background-color: aquamarine;​  
    
    display: table-cell;
    vertical-align: middle;
    }​
    
#children {  
    width: 100px;  
    height: 100px; 
    background-color: pink;
    }​

#other-item { 
    width: 100px; 
    height: 30px; 
    background-color: salmon;}

效果:

所以当父元素中拥有其他元素时,就不太适合使用这种方案实现垂直居中布局了。

2、position+负margin

  • 设置父元素为相对定位
  • 设置子元素为绝对定位
  • 设置子元素 left 为 50%
  • 设置子元素 top 为 -1/2*height (高度一半的负值)

代码如下:

<div id="parent">
    <div id="children"></div>
</div>
#parent {  
    width: 300px;  
    height: 200px;  
    background-color: aquamarine;​  
    
    position: relative;
    }​
    
#children { 
    width: 100px;
    height: 100px;  
    background-color: pink;​  
    
    position: absolute;  
    top: 50%;  
    margin-top: -50px;
    }

解读:

1、为了让子元素相对于父元素进行定位,所以设置父元素相对定位、子元素绝对定位

2、为了让元素在中间,所以设置子元素的 top 为 50% 。让子元素距离父元素的左边的距离是 父元素宽度的一半,即 100px

3、由于 100px 过大,会导致子元素位置向下偏,如:

4、所以,要设置,让元素向上移动自己高度的一半,回到正中间,所以设置了 margin-top 为 -50px 。

优点:

无论父元素是否脱离文档流,都不影响子元素水平居中的效果。

缺点:

必须要明确子元素的宽度,否则没有办法设置 margin-left 的值。

3、position+translateY

  • 设置父元素为相对定位
  • 设置子元素为绝对定位
  • 设置子元素 left 为 50%
  • 设置子元素 translateY 为 -50%

代码如下:

<div id="parent">
    <div id="children"></div>
</div>
#parent {  
    width: 300px; 
    height: 200px; 
    background-color: aquamarine;​  
    
    position: relative;
    }​
    
#children {  
    width: 100px; 
    height: 100px;
    background-color: pink;​
    
    position: absolute;  
    top: 50%;  
    transform: translateY(-50%);
    }

解读:

和上一个的方法一样,需要让子元素向上移动自己的高度的一半,除了用 margin 之外,也可以使用 translateY 让元素在垂直方向上偏移,当给 translateY 的参数设置为 -50% 时,即为向上移动自己高度的一半。

优点:

无论父元素是否脱离文档流,都不影响子元素水平居中的效果。

缺点:

transform 是 CSS3中新增的属性,所以不兼容部分老浏览器。

兼容性查询:www.caniuse.com/#search=tra…

4、flex + align-items

  • 设置父元素的 dispaly 为 flex
  • 设置父元素的 align-items 为 center

代码如下:

<div id="parent"> 
    <div id="children"></div>
</div>
#parent { 
    width: 300px;  
    height: 200px;
    background-color: aquamarine;​
    
    display: flex;  
    align-items: center;
    }​
    
#children {  
    width: 100px;
    height: 100px;  
    background-color: pink;
    }

解读:

设置 display 为 flex 的父元素其交叉轴上元素的排列方式为居中。

优点:

无论父元素是否脱离文档流,都不影响子元素水平居中的效果。

缺点:

1、flex 是 CSS3中新增的内容,所以不兼容部分老浏览器。

兼容性查询:www.caniuse.com/#search=fle…

2、使用此种方式,会让父元素内的其他子元素也全部垂直居中,如下,在父元素中添加其他子元素:

<div id="parent">
    <div id="children"></div>
    <div id="other-item"></div>
</div>
#parent {
    width: 300px;  
    height: 200px; 
    background-color: aquamarine;​ 
    
    display: flex; 
    justify-content: center;
    }​
    
#children {  
    width: 100px; 
    height: 100px;  
    background-color: pink;
    }​
    
#other-item {
    width: 100px;  
    height: 30px;
    background-color: salmon;
    }

效果如下:

若父元素内有其他子元素不需要垂直居中处理,则可以考虑不使用这种方式。

居中 (水平+垂直) 布局

居中布局,即为元素在父元素的水平方向上和居中方向都对齐,效果如下:

想要实现居中对齐,整合上面的水平布局方法和垂直居中即可,故不再对解读、优点、缺点进行书写。

1、table+margin+table-cell+vertical-align

代码如下:

<div id="parent"> 
    <div id="children"></div>
</div>
#parent {
    width: 300px;  
    height: 200px; 
    background-color: aquamarine;​  
    
    display: table-cell; 
    vertical-align: middle;
    text-align: center;
    }​
    
#children { 
    width: 100px; 
    height: 100px;
    background-color: pink;​  
    
    display: inline-block;
    }

2、position+负margin

代码如下:

<div id="parent">  
    <div id="children"></div>
</div>
#parent {
    width: 300px;  
    height: 200px; 
    background-color: aquamarine;​ 
    
    position: relative;
    }​
    
#children {
    width: 100px;
    height: 100px;  
    background-color: pink;​ 
    
    position: absolute;  
    left: 50%; 
    top: 50%;  
    margin-top: -50px;
    margin-left: -50px;
    }

3、position+translateX+translateY

代码如下:

<div id="parent">
    <div id="children"></div>
</div>
#parent {
    width: 300px;  
    height: 200px;
    background-color: aquamarine;​ 
    
    position: relative;
    }​
    
#children { 
    width: 100px;  
    height: 100px; 
    background-color: pink;​ 
    
    position: absolute;
    left: 50%;  
    top: 50%;  
    transform: translateX(-50%) translateY(-50%);
    }

4、flex+justify-content+align-items

代码如下:

<div id="parent"> 
    <div id="children"></div>
</div>
#parent {
    width: 300px;  
    height: 200px;
    background-color: aquamarine;​  
    
    display: flex;
    justify-content: center;  
    align-items: center;
    }​
    
#children {
    width: 100px; 
    height: 100px; 
    background-color: pink;
    }

5、position+margin

<div id="parent">
    <div id="children"></div>
</div>
#parent {
    width: 300px;  
    height: 200px;
    background-color: aquamarine;​  
    
    position: relative;
    }​

#children { 
    width: 100px;
    height: 100px;  
    background-color: pink;​ 
    position: absolute;  
    top: 0;  
    right: 0;  
    bottom: 0;
    left: 0;  
    margin: auto;
    }

最后听一首悦耳的歌放松放松,回忆学到的东西。

点击下面​播放音乐

New Boy (Live片段).mp3 00:00 00:13#让生活多一点生机