CSS 三栏布局的几种方式
前言
很多网页的整体布局呈现为 “两栏” 或者 “三栏”,比如下图中 echarts 的布局就是最典型的左右两栏:
此外,另一种常用布局就是 “左-中-右” 三栏布局,比如下图中 pytorch 的官方文档:
当然,还有很多网页都采用的这种布局方式,这里我也就不一一举例。回归到问题本质,那么该如何实现这种布局?又或者说有哪些方法可以满足我们的布局需求呢?
因为两栏布局比较简单,故本文将主要围绕三栏布局,思想大同小异,读者也可以灵活变通,从而解决两栏布局的问题。
这里我把本文的核心问题再提出来详细描述一番,以免有读者没有完全理解,即:将网页分为左中右三栏布局,左右部分定宽,中间部分宽度自适应。
常用方法及原理
基于我自己开发的经验并借鉴其他的参考资料,本文根据布局的方法分为四种主体类型,其中基于 float 布局的方式下还包括经典的圣杯布局和双飞翼布局。如下所示:
- 基于 absolute 定位
- 基于 float 布局
- 圣杯布局
- 双飞翼布局
- 基于 flex 布局
- 基于 grid 布局
首先我们先定义三个元素,即:left
、main
、right
三个部分。其 html 形式如下所示,后续也将不再重复赘述这一部分。
1 | <div class='left'>Left</div> |
基于 absolute 定位
absolute
定位提供了 top
、left
、bottom
、right
等定位属性,并且绝对定位的元素脱离文档流,相对于最近的已经定位的祖先元素进行定位。因此,该方法的思路如下:
- 分别将左、右两个部分基于 absolute 的相关属性定位到左右两边。
- 中间的部分直接占据宽度的 100%,并基于
margin
留出 left 和 right 部分的宽度。
代码如下:
1 | .container { /*容器*/ |
1 | <div class='container'> |
上面就是基于 absolute 定位实现的三栏布局效果图。然而这种方法一旦出现中间栏含有最小宽度的限制,且当浏览器宽度小到一定程度的时候,就会发生层重叠的情况。因此,该方法并不是最优选择 ❌,且不够优雅!
基于 float 布局
float
布局是一个众所周知被常用于三栏布局的方法。我们可以分别将左部分设置为 float: left
,将右部分设置为 float: right
,最后中间部分自适应即可。
然而这种方法存在一个问题:由于中间部分的自适应是依赖于左右部分的,因此在 html 的节点中,一定是要先加载 left
和 right
,才能再加载 main
。如果顺序出现问题,则 main
不能正确的获取位置。然而,很多网页中,中间部分的重要程度往往更大,需要最先加载,那么这种方法就无法满足需求了。
为了解决上述问题,实现中间部分先加载,我提供了两种经典方法:圣杯布局和双飞翼布局。
圣杯布局 ✅
圣杯布局是一个经典的基于 float 的布局方法,在很多页面中被使用到,包括下一小节的双飞翼布局也是在圣杯布局上进行的优化。因此,我也将详细介绍圣杯布局的原理。
首先,我们还是设置三个部分:left
、main
、right
,并将其设置为 float: left
,代码如下:
1 | .container { |
1 | <div class='container'> |
从上面的结果可以看出,由于 main
设置的 width: 100%
,因此占据了整个页面的宽度,因此 left
和 right
的内容都因为空间不足而被迫移到了下一行。但是这里有一个重要的知识点:虽然 left
和 right
被在视觉上被移到了下一行,实际上它们和 main
还是在一行中(不理解 float 的读者建议去先学习一下)。
那么该怎么在这个基础上来实现三栏布局呢?我们可以先给 container
元素添加上 padding
效果,从而让整体预留出 left
和 right
的视觉空间。代码如下:
1 | .container { |
由上图可以看出,main
的左右都变成了空白,为 left
right
预留出了它们理所应当在的位置空间。后续的调整也很显而易见了:将 left
和 right
移动到 main
的左右两边。
那么如何移动呢?使用 relative
定位的相关属性和负值 margin
。再次提醒,main
、left
、right
实际位置是在同一行中的。如果忽略了这一点,可能会不理解下面代码中的 margin-left: -100%
的含义。代码如下:
1 | /* 圣杯布局 */ |
此处 html 的代码和上述组织形式相同。从上图可以看出,我们已经实现了三栏布局。至此,上述的 CSS 代码就是圣杯布局的全部内容。
双飞翼布局 ✅
在上一节的开头,本文提到双飞翼布局是对圣杯布局的优化。其实理解了圣杯布局的逻辑会发现,很多内容存在冗余,从而导致了一定的复杂度。那么下面就来看看双飞翼布局是如何优化的。
双飞翼布局的思路就是:首先不需要对整个 container
进行 padding
设置,取而代之的是再用一个容器 wrapper
包裹着 main
,并对 main
进行相关设置。代码如下:
1 | .left, .right { |
1 | <div class='container'> |
上图达到了三栏布局的效果。有几个比较重要的点,本文对此再做一定的解释:
- 利用
wrapper
包裹,wrapper
的宽度还是占据整个页面的宽度。- 只对
main
设置 margin 属性,达到内容不被left
和right
遮盖。margin-left
的负值理解,重点是移动的参考线在哪,移动的距离多长。
我相信,当你理解了上述三点,就能够彻底理解双飞翼布局的原理啦!
基于 flex 布局
之前我在一篇文章中说了一句flex yyds!那既然都这么说了,那么flex
布局也可以灵活且简洁地实现三栏布局的需求。
flex
弹性布局实现三栏布局十分简单,这里我也不详细赘述,直接上代码,想了解的也可以去学一学 flex
。
1 | .container { /* 关键部分 */ |
1 | <div class='container'> |
上图的效果也是满足我们的需求,并且代码量是否少。整个实现原理如下所示:
- 将容器设置为
display:flex
,盒内元素排布方式为space-between
。- 设置左右元素宽度,再将中间元素设置为
width: 100%
,或者设为flex: 1
,即可填充空白部分。
由此可见,flex
布局用于实现三栏布局是一个简便且优雅的方法 ✅!
基于 grid 布局
我之前阅读的时候看到过有一个大佬说 grid 布局是最强大的布局,这次我特地去找到了这篇文章:《最强大的 CSS 布局 —— Grid 布局》,感兴趣的可以阅读并学习一下 grid 布局。本人觉得 grid 布局如果不考虑浏览器的兼容性问题的话,确实是一个十分优秀的选择,建议读者了解并学习。
因为 grid 布局和 flex 布局实现三栏布局都十分简单,因此这里我也直接放代码,想要学习细节的可以参考提供的学习链接。
1 | .container { |
1 | <div class='container'> |
效果如上图所示,我也不多说什么,只能说大佬没说错,grid 也是 yyds ✅!
总结
以上就是所有内容啦,我总结了四种实现三栏布局的方法供大家参考。第一张方法使用较少,缺点也比较明显,我也是建议大家多多学习并理解后面三种方法,尤其是认真学习圣杯布局和双飞翼布局,这有助于提升你对 CSS 的理解。
很感谢你能看到这里!谢谢~
参考资料: (衷心感谢各参考资料提供的帮助)