前言
实现三栏布局也是一道经典的面试题,如果你能侃侃而谈这十种实现三栏布局的方式,一定会令面试官眼前一亮。三栏布局即左右固定中间伸缩,将三栏布局的方式按照中间栏的渲染顺序可以分为三种:float实现的三种(中间栏最后渲染),flex、grid、绝对定位实现的三种(中间栏中间渲染),双飞翼圣杯实现的四种(中间栏最后渲染)
float实现的三种
float实现的方式优点是兼容性好;缺点是需要将中间栏放在最后渲染,网速慢的情况下可能会影响用户体验。
float+BFC
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>CSS实现三栏布局</title> <style type="text/css"> .left{ float: left; width: 100px; background-color: aqua; } .middle{ overflow: hidden; height: 200px; background-color: green; } .right{ float: right; width: 100px; background-color: aqua; } </style> </head> <body> <div class="container"> <div class="left">左栏</div> <div class="right">右栏</div> <div class="middle">中间栏</div> </div> </body> </html>
|
float+margin
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>CSS实现三栏布局</title> <style type="text/css"> .left{ float: left; width: 100px; background-color: aqua; } .middle{ margin:0 100px; height: 200px; background-color: green; } .right{ float: right; width: 100px; background-color: aqua; } </style> </head> <body> <div class="container"> <div class="left">左栏</div> <div class="right">右栏</div> <div class="middle">中间栏</div> </div> </body> </html>
|
float+calc()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>CSS实现三栏布局</title> <style type="text/css"> div { height: 100px; } .left { float: left; width: 200px; background-color: red; } .middle { float: left; width: calc(100% - 400px); background-color: green; } .right { float: right; width: 200px; background-color: blue; } </style> </head> <body> <div class="container"> <div class="left">左栏</div> <div class="right">右栏</div> <div class="middle">中间栏</div> </div> </body> </html>
|
flex、grid、绝对定位实现的三种
这三种方式都是将中间栏放在中间渲染。
flex
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>CSS实现三栏布局</title> <style type="text/css"> .container { display: flex; } .left { width: 200px; height: 200px; background: red; } .middle { height: 200px; background: yellow; flex: 1; } .right { width: 200px; height: 200px; background: blue; } </style> </head> <body> <div class="container"> <div class="left">左栏</div> <div class="middle">中间栏</div> <div class="right">右栏</div> </div> </body> </html>
|
grid
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>CSS实现三栏布局</title> <style type="text/css"> div { height: 100px; } .container { display: grid; grid-template-columns: 200px auto 200px; } .left { background: red; } .middle { background: green; } .right { background: blue; } </style> </head> <body> <div class="container"> <div class="left">左栏</div> <div class="middle">中间栏</div> <div class="right">右栏</div> </div> </body> </html>
|
绝对定位
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>CSS实现三栏布局</title> <style type="text/css"> .container { position: relative; } .left { position: absolute; left: 0; width: 200px; background-color: red; } .middle { position: absolute; left: 200px; right: 200px; background-color: green; } .right { position: absolute; right: 0; width: 200px; background-color: blue; } </style> </head> <body> <div class="container"> <div class="left">左栏</div> <div class="middle">中间栏</div> <div class="right">右栏</div> </div> </body> </html>
|
双飞翼圣杯实现的四种
这四种方式都是将中间栏放在最前面渲染,保证中间栏最先渲染。
felx实现圣杯双飞翼效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>CSS实现三栏布局</title> <style type="text/css"> .container { display: flex; } .middle { flex: 1; background-color: red; } .left { width: 200px; order: -1; background-color: aqua; } .right { width: 200px; order: 1; background-color: bisque; } </style> </head> <body> <div class="container"> <div class="left">左栏</div> <div class="right">右栏</div> <div class="middle">中间栏</div> </div> </body> </html>
|
圣杯布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS实现三栏布局</title> <style> * { margin: 0; padding: 0; } .container { height: 100px; padding: 0 200px; } .middle,.left,.right{ float: left; height: 100%; } .middle { width: 100%; background: rgb(100, 105, 100); } .left { position: relative; width: 200px; background: pink; left: -200px; margin-left: -100%; } .right { position: relative; width: 200px; background: pink; margin-left: -200px; left:200px; } </style> </head> <body> <div class="container"> <div class="middle">middle</div> <div class="left">left</div> <div class="right">right</div> </div> </body> </html>
|
注意:圣杯布局中间列的宽度不能小于两边任意列的宽度,而双飞翼布局则不存在这个问题。
父级padding+子绝父相+负边距:三栏都使用float:left;
父级标签padding: 0 200px;
,结合下面这张图理解

将left和right使用子绝父相,再调整定位的方式弄上去
左边:margin-left: -100%;
(切换到上一行起始位置)left: -200px;
(相对定位,向左移动200px)
右边:margin-left: -200px;
(向左移动一个身位,移动到middle的右侧)left:200px;
(向右移动200px)
还有种方法也能挤上去:margin-right: -200px;
双飞翼布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS实现三栏布局</title> <style> .container { overflow: hidden; height: 200px; } .middle,.left,.right { float: left; height: 100px; } .middle { width: 100%; background-color: aqua; } .inner { margin: 0 200px; height: 100px; background-color: green; } .left { width: 200px; margin-left: -100%; background-color: red; } .right { width: 200px; margin-left: -200px; background-color: blue; } </style> </head> <body> <div class="container"> <div class="middle"> <div class="inner">中间</div> </div> <div class="left">左边</div> <div class="right">右边</div> </div> </body> </html>
|
中间栏的子标签margin+左右负边距:三栏都使用float:left;
中间栏子标签margin: 0 200px;
HTML中将中间栏放前面;结合下面这张图去理解

双飞翼圣杯复合写法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CSS实现三栏布局</title> <style> .container { height: 100px; } .middle,.left,.right{ float: left; height: 100%; } .middle { box-sizing: border-box; width: 100%; background: rgb(100, 105, 100); padding: 0 200px; } .left { width: 200px; background: pink; margin-left: -100%; } .right { width: 200px; background: pink; margin-left: -200px; } </style> </head> <body> <div class="container"> <div class="middle">middle</div> <div class="left">left</div> <div class="right">right</div> </div> </body> </html>
|
中间标签内减模式padding+负数边距:三栏都使用float:left
;中间栏标签padding: 0 200px;
且要设置box-sizing: border-box;
左边:margin-left: -100%
;右边:margin-left: -200px
;

总结
- float+BFC:左右两栏float到左右;中间
overflow: hidden;
清除浮动显示第二栏 ;注意:HTML需要将中间块放在right之后;
- float+margin:左右两栏float到左右;中间设置
margin-left
和margin-right
;注意:HTML需要将中间块放在right之后;
- float+calc() :先使用浮动将三栏水平排列,然后对中间栏使用
calc(100% - 400px);
来计算去除左右两栏宽度后剩余的宽度;
- flex;将中间设定值为1,最简单的方式;
- grid:
display: grid;grid-template-columns: 200px auto 200px;
左右两栏固定宽度,中间自适应宽度;
- 子绝父相:三栏全部绝对定位;中间栏left: 200px;right: 200px;保持伸缩居中
- felx实现圣杯双飞翼效果:
left {order: -1;} right{order: 1;}
中间块默认为0;所以显示顺序了-1、0、1;
- 圣杯布局:
父级padding+子绝父相+负边距
;
- 双飞翼布局:
中间栏的子标签margin+左右负边距
;
- 双飞翼圣杯复合写法:
中间标签内减模式padding+负数边距
。
感谢小伙伴们的耐心观看,本文为笔者个人学习记录,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!