三栏式布局(所谓的圣杯和双飞翼)

前面的话
常常听说圣杯布局和双飞翼布局,以为是两个很高级的语汇。但实际上,他们只是三栏式布局的两种布局方法而已。本文将介绍三栏式布局的4种思路
float
【1】圣杯布局
圣杯布局使用float、负margin和relative,不需要添加额外标签。.main元素设置padding,为两侧定宽元素留出位置。内容元素设置100%宽度,占据中间位置。而两侧定宽元素通过设置负margin和relative的偏移属性配合,到达相应位置
缺点: 并没有实现等高布局;使用了相对定位,扩展性不好
<style> body,p{margin: 0;} .top,.bottom{ height: 30px; } .middle{ padding: 0 120px; overflow: hidden; } .main{ width: 100%; float: left; } .left,.right{ float: left; width: 100px; position: relative; } .left{ margin-left: -100%; left: -120px; } .right{ margin-left: -100px; right: -120px; } </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" style="background-color: orange;"> <p>left</p> </div> <div class="right" style="background-color: lightsalmon;"> <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
【2】双飞翼布局
双飞翼布局在圣杯布局的基础上,通过为.main元素外添加一层div结构,不使用相对定位。在.main元素上设置margin。两侧的定宽列通过负margin来占据.main元素的margin区域
缺点: 并没有实现等高布局,增加了html结构
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{overflow: hidden;} .mainWrap{ width: 100%; float: left; } .main{margin: 0 120px;} .left,.right{ float: left; width: 100px; } .left{margin-left: -100%;} .right{margin-left: -100px;} </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="mainWrap"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> </div> <div class="left" style="background-color: orange;"> <p>left</p> </div> <div class="right" style="background-color: lightsalmon;"> <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
【3】float + box-sizing + background-clip
.main元素的border区域为两侧定宽列的所在区域,实现伪等高效果;设置.main的padding和background-clip来实现元素间隔。两侧元素通过负margin调整到.main元素的border区域
缺点: 兼容性不好
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{overflow: hidden;} .main{ float: left; width: 100%; border-left: 100px solid lightgrey; border-right: 100px solid lightgrey; padding: 0 20px; background-clip: content-box; box-sizing: border-box; } .left,.right{ float: left; width: 100px; } .left{margin-left: -100%;} .right{margin-left: -100px;} </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" > <p>left</p> </div> <div class="right" > <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
absolute
设置子元素的top:0;bottom:0;使得所有子元素的高度都和父元素的高度相同,实现等高效果
缺点: 需要为.middle元素设置高度,扩展性较差
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{ position: relative; height: 40px; } .left,.right,.main{ position: absolute; top: 0; bottom: 0; } .left{width: 100px;} .right{ width: 100px; right: 0; } .main{ left: 120px; right: 120px; } </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" style="background-color: lightseagreen;" > <p>left</p> </div> <div class="right" style="background-color: lightcyan;" > <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
flex
flex中的伸缩项目默认都拉伸为父元素的高度,可实现等高效果。通过改变伸缩项目的order,可以实现元素顺序调换的效果
缺点: 兼容性不高
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{display: flex;} .left,.right{width: 100px;} .right{order: 2;} .main{ order: 1; flex: 1; margin: 0 20px; } </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" style="background-color: lightseagreen;" > <p>left</p> </div> <div class="right" style="background-color: lightcyan;" > <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
grid
<style> body,p{margin: 0;} .top,.bottom{height: 30px;} .middle{display:grid;grid-template-columns:100px 1fr 100px;grid-gap:20px;} .main{grid-area:1/2/2/3;} </style>
<div class="parent" id="parent" style="background-color: lightgrey;"> <div class="top" style="background-color: lightblue;"> <p>top</p> </div> <div class="middle" style="background-color: pink;"> <div class="main" style="background-color: lightcoral;"> <p>main</p> <p>main</p> </div> <div class="left" style="background-color: lightseagreen;" > <p>left</p> </div> <div class="right" style="background-color: lightcyan;" > <p>right</p> </div> </div> <div class="bottom" style="background-color: lightgreen;"> <p>bottom</p> </div> </div>
总结
由于限定了主要内容元素在html结构中位于前面,通过css样式改变将其位置调换到中间的前提,所以思路并不是很多。float浮动流的元素可以通过负margin调换位置;absolute绝对定位流的元素可以通过偏移属性调换位置;flex弹性盒模型可以通过order属性调换位置;grid通过grid-area调换位置。而处于正常流中的元素除了使用relative外,使用负margin是无法调换位置的,所以table、inline-block等布局方式在此前提下不是很实用。
好的代码像粥一样,都是用时间熬出来的

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?