本文节选自我的博客:实现三栏布局的十种方式
- 💖 作者简介:大家好,我是MilesChen,偏前端的全栈开发者。
- 📝 CSDN主页:爱吃糖的猫🔥
- 📣 我的博客:爱吃糖的猫
- 📚 Github主页: MilesChen
- 🎉 支持我:点赞👍+收藏⭐️+留言📝
- 💬介绍:The mixture of WEB+DeepLearning+Iot+anything🍁
前言
实现三栏布局也是一道经典的面试题,如果你能侃侃而谈这十种实现三栏布局的方式,一定会令面试官眼前一亮。三栏布局即左右固定中间伸缩,将三栏布局的方式按照中间栏的渲染顺序可以分为三种: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">/* 方法1 浮动+BFC 左右元素固定宽度,向左右浮动 中间元素不设置宽度,会自动撑满,重叠问题可使用构造BFC解决 *//* 注意HTML标签中需要将 中间元素放在最后显示,这会导致问题,中间内容后显示 */.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">/* 方法2 浮动+margin 和两栏比较法二很像,左右元素固定宽度,向左右浮动 中间元素不设置宽度,会自动撑满,重叠问题可使用margin解决 *//* 注意HTML标签中需要将 中间元素放在最后显示,这会导致问题,中间内容后显示 */.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">/* 方法3 浮动+calc() 先使用浮动将三栏水平排列,然后对中间栏使用calc()函数来计算去除左右两栏固定宽度后剩余的宽度。*/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">/* 方法4 flex 直接给中间设置flex 1 左右固定宽度 *//* 优点是特别简单 缺点是依赖flex的兼容性 */.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">/* 方法5 网格 利用grid布局的方式,左右两栏设置固定宽度,中间一栏设置为auto*//* 核心代码:grid-template-columns 左栏固定宽度 中间自适应宽度 右栏固定宽度*/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">/* 方法6 子绝父相:三栏全部绝对定位;中间栏left: 200px;right: 200px;保持伸缩居中 */.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">/* 方法7:使用flex实现圣杯、双飞翼的效果, 使用 order 调整flex顺序 使中间块最先加载*/.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栏添加padding,左右栏使用相对定位移上去。利用浮动,外边距负值和相对定位来实现。 */.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;/* float后的元素可以使用 margin-left: -100%; 切换到上一行起始位置*/margin-left: -100%;}.right {position: relative;width: 200px;background: pink;/* 第一种写法 */margin-left: -200px;left:200px;/* 第二中写法 *//* margin-right: -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;}/* 中间栏的子标签margin+左右负边距 */.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>/* 双飞翼与圣杯布局的结合写法,这一种直接在中间栏加padding,然后将左右栏 添加margin-left移动上去 *//* middle要使用内减模式 不然会多出一块区域 */.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+负数边距
。
感谢小伙伴们的耐心观看,本文为笔者个人学习记录,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!