三栏布局/圣杯布局是常见的布局方式,面试也经常问。
圣杯布局说的是左右的宽度固定,中间宽度自适应的布局。实现方式有很多,之前只是知道两三种。现在来总结一下。
总的来说,分为css3之前和css3之后的属性实现。
html结构都是这样:
css3之前的:
1.左右两栏绝对定位,父元素设置padding,中间自适应
父元素相对定位,设置padding,左右两侧绝对定位,中间的content利用块级元素的特点自动铺满.
.box { padding: 0 150px; height: 500px; position: relative; } .left { width: 150px; position: absolute; left: 0; height: 100%; background: red; } .right { width: 150px; position: absolute; right: 0; height: 100%; background: blue; } .content { height: 100%; background: blueviolet; }
2.左右两栏绝对定位,父元素设置border,中间自适应
这个和上一个很像,不同的是利用border来占据左右的空间,使中间自适应。有个小小的点就是,子元素的定位默认是以padding区域计算的,所以左右两栏的left和right要设置相应的负值。
.box { border-left: 150px solid transparent; border-right: 150px solid transparent; height: 500px; position: relative; } .left { width: 150px; position: absolute; left: -150px; height: 100%; background: red; } .right { width: 150px; position: absolute; right: -150px; height: 100%; background: blue; } .content { height: 100%; background: blueviolet; }
3.三栏都绝对定位,中间利用left和right实现自适应
.box { height: 500px; position: relative; } .left { width: 150px; position: absolute; left: 0; height: 100%; background: red; } .right { width: 150px; position: absolute; right: 0; height: 100%; background: blue; } .content { height: 100%; background: blueviolet; left: 150px; right: 150px; position: absolute; }
4.左右两栏绝对定位,中间设置margin自适应
.box { height: 500px; position: relative; } .left { width: 150px; position: absolute; left: 0; height: 100%; background: red; } .right { width: 150px; position: absolute; right: 0; height: 100%; background: blue; } .content { height: 100%; background: blueviolet; margin: 0 150px; }
5.左右两栏绝对定位,中间设置计算宽度实现自适应
.box { height: 500px; position: relative; } .left { width: 150px; position: absolute; left: 0; height: 100%; background: red; } .right { width: 150px; position: absolute; right: 0; height: 100%; background: blue; } .content { height: 100%; background: blueviolet; width: calc(100% - 300px); margin: 0 auto; }
6.左右两栏浮动,中间设置margin自适应
.box { height: 500px; } .left { width: 150px; float: left; height: 100%; background: red; } .right { width: 150px; float: right; height: 100%; background: blue; } .content { height: 100%; background: blueviolet; margin: 0 150px; }
7.左右两栏浮动,父元素设置padding实现中间自适应
和第二个方法类似,因为浮动的元素默认以content区域计算,所以左右两栏要设置margin方向的负值
.box { height: 500px; padding: 0 150px; } .left { width: 150px; float: left; height: 100%; background: red; margin-left: -150px; } .right { width: 150px; float: right; height: 100%; background: blue; margin-right: -150px; } .content { height: 100%; background: blueviolet; }
8.左右两栏浮动,父元素设置border实现中间自适应
.box { height: 500px; border-left: 150px solid transparent; border-right: 150px solid transparent; } .left { width: 150px; float: left; height: 100%; background: red; margin-left: -150px; } .right { width: 150px; float: right; height: 100%; background: blue; margin-right: -150px; } .content { height: 100%; background: blueviolet; }
9.左右两栏浮动,中间设置绝对定位实现自适应
.box { height: 500px; position: relative; } .left { width: 150px; float: left; height: 100%; background: red; } .right { width: 150px; float: right; height: 100%; background: blue; } .content { height: 100%; background: blueviolet; position: absolute; left: 150px; right: 150px; }
10.左右两栏浮动,中间使用计算宽度实现自适应
.box { height: 500px; } .left { width: 150px; float: left; height: 100%; background: red; } .right { width: 150px; float: right; height: 100%; background: blue; } .content { height: 100%; background: blueviolet; width: calc(100% - 300px); margin: 0 auto; }
先来个总结:
css3之前的方式,主要是左右两栏的布局方式结合中间宽度自适应的实现方式。左右两栏分为浮动和绝对定位,中间自适应的方式,分为:绝对定位的left和right,左右的margin+块级元素的特性,计算宽度,父元素的padding,父元素的border。这样两两结合,总共有10种方式
css3:
11.flex布局
.box { height: 500px; display: flex; } .left { width: 150px; background: red; } .right { width: 150px; background: blue; } .content { height: 100%; background: blueviolet; width: 0; flex: auto; }
为什么content要设置width:0呢?这是一个好的习惯,常规场景,不设置width:0也可以。但是如果在对应的主轴方向上,content需要有超出隐藏的功能,那么不设置width:0(如果主轴方向是column就是height:0)的话,子元素超出时content的宽度会被撑开。所以我习惯在flex:auto的元素上,在对应的主轴方向的尺寸属性设置为0.
12.grid
.box { height: 500px; display: grid; grid-template-columns: 150px auto 150px; grid-template-rows: auto; } .left { background: red; } .right { background: blue; } .content { background: blueviolet; }
可以看的出来,css3的flex布局十分简单,需要设置的属性也更少。
有个细节就是,css3下的实现,三栏的html元素的顺序不能改变,而css2的实现,三栏的html元素的顺序可以是任意的。比如content可以在最后或者最前面。当然一般来说html顺序可以自由控制,所以这个问题不大。