zoukankan      html  css  js  c++  java
  • 用五种方法来聊一聊传说中的三栏布局

    引言

      三栏布局是目前网站建设的主流布局,同时也是面试中必考的一个点,无论是PC端还是移动端三栏布局都是非常重要的一个CSS知识点,关于三栏布局的方案说的最烂的莫过于圣杯布局了,其主要的核心思想其实就只有一条:实现两栏固定,中间自适应,保证页面的布局不受窗口大小的变化而紊乱。本文总结了五种实现三栏布局的方法,包括主流的圣杯布局、双飞翼布局,也包含了一些个人遐想的非主流布局,供同学们学习和参考。

    一、圣杯布局

      圣杯布局的思想是将页面纵向分为三个部分,即 header、container、footer,然后又将 container 定为三栏布局。在这里主要讲解其中的 container 布局。

      首先在 container 里面有三栏,分别是 left、middle、right,注意这里 middle 需要放在最前面,保证可以得到优先渲染:

     1 <div class="grail-container">
     2     <div class="grail-middle">
     3         Grail main
     4     </div>
     5     <div class="grail-left">
     6         Grail left
     7     </div>
     8     <div class="grail-right">
     9         Grail right
    10     </div>
    11 </div>

      对于 container ,设置一个属性 overflow: hidden; 让其形成一个 BFC ,然后使其三栏浮动,并使用相对定位:

    1 .grail-container {
    2     overflow: hidden;
    3 }
    4 .grail-container>div {
    5     position: relative;
    6     float: left;
    7     height: 100%;
    8 }

      这时执行以下的步骤:

      ① 置 middle 的 100%,给 left 和 right 定宽度,这里假设都是 200px;

      ② 这时 left 被挤到下面去了,所以我们要把它拉回来,设置 margin-left: -100%;

      ③ 还有一个 right 没有拉回来,同样,设置 margin-left: 200px;,这里的长度等于 right 自身的长度

      ④ 这时 middle 的两边被 left 和 right 给覆盖了,于是我们要把两边怼回来,设置 container padding: 0 200px 0 200px;

      ⑤ middle 怼回来了,可是 left 和 right 也跟着回来,所以现在我们要把 left 和 right 给怼回去,分别设置 left left: -200px;,right right: -200px;(这就是之前为什么要用相对定位)

     1 .grail-container {
     2     overflow: hidden;
     3     padding: 0 200px;
     4 }
     5 .grail-container>div {
     6     position: relative;
     7     float: left;
     8     height: 100%;
     9 }
    10 .grail-middle {
    11     width: 100%;
    12     background-color: blue;
    13 }
    14 .grail-left {
    15     width: 200px;
    16     background-color: green;
    17     margin-left: -100%;
    18     left: -200px;
    19 }
    20 .grail-right {
    21     width: 200px;
    22     background-color: brown;
    23     margin-left: -200px;
    24     right: -200px;
    25 }

      圣杯布局就完成了,不信拖拖看,是不是中间就自适应了?不过它有一个弊端,就是当拖到很小的时候,布局会乱,于是我们有了下面的布局:双飞翼布局。

     二、双飞翼布局

      双飞翼布局使于淘宝,是淘宝团队提出来的一种实现三栏布局的方案,其和圣杯布局是同门兄弟,同样将页面分为 header、container、footer ,不过在 container 里面有所区别。圣杯布局的缺陷在于内容区被 container 的 padding 夹在里面,使得页面宽度过小时会出现布局紊乱,这时候双飞翼布局就不使用 padding 来将内容区夹在里面,而是给内容区添加一个 main ,设置 margin 将页面主动的撑开,其 DOM 结构与圣杯类似,区别在于在 middle 中多了一个 main:

     1 <div class="double-wing-container">
     2     <div class="double-wing-middle">
     3         <div class="double-wing-main">
     4             Double wing main.  
     5         </div>
     6     </div>
     7     <div class="double-wing-left">
     8         Double wing left.  
     9     </div>
    10     <div class="double-wing-right">
    11         Double wing right
    12     </div>
    13 </div>
    1 .double-wing-container {
    2     overflow: hidden;
    3 }
    4 .double-wing-container>div {
    5     position: relative;
    6     float: left;
    7     height: 100%;
    8 }

      这时执行与圣杯布局类似的步骤:

      ① 置 middle 的  100%,给 left 和 right 定宽度,这里假设都是  200px;

      ② 这时 left 被挤到下面去了,所以我们要把它拉回来,设置 margin-left: -100%;

      ③ 还有一个 right 没有拉回来,同样,设置 margin-left: 200px;,这里的长度等于 right 自身的长度

      注意这里开始就有区别了:

      ④ 使用 main 把内容区撑开,设置 margin: 0 200px 0 200px;,同时设置 overflow: hidden; 使其形成一个 BFC

     1 .double-wing-container {
     2     overflow: hidden;
     3 }
     4 .double-wing-container>div {
     5     position: relative;
     6     float: left;
     7     height: 100%;
     8 }
     9 .double-wing-middle {
    10     width: 100%;
    11     background-color: gray;
    12 }
    13 .double-wing-left {
    14     width: 200px;
    15     background-color: orange;
    16     margin-left: -100%;
    17 }
    18 .double-wing-right {
    19     width: 200px;
    20     background-color: red;
    21     margin-left: -200px;
    22 }
    23 .double-wing-main {
    24     height: 100%;
    25     margin: 0 200px;
    26     background-color: pink;
    27     overflow: hidden;
    28 }

      现在再试试,是不是比圣杯布局稍微好一点,在窗口宽度过小时不会出现排版混乱?其核心就是把内容部分从 middle 迁移到了 main。

      以上两种布局方案已经适用于绝大部分场景,如果你只是想找一个三栏布局的解决方案,那么到此就够了。不过,如果你想要的不只是这些,if you wanna more,那么就一起来聊一聊下面的布局方案。

      首先呢,我们的两大三栏布局都有一个固定的模式,那就是两栏固定,中间自适应,可是你有没有想过,我们来实现一个三栏自适应的布局?那么大名鼎鼎的 Flex 布局就登场了,Flex 布局不光可以实现两栏固定,中间自适应,也可以实现三栏自适应,甚至随意固定,随意自适应。

    三、Flex 布局

      Flex 布局可谓 CSS3 提供一个布局神奇,将 CSS2 中的许多难点一网打尽。关于 Flex 布局的语法,这里就不做讨论了,如果有不熟悉的同学可以先看看阮老师的文章:Flex 布局教程:语法篇 这篇文章讲解的十分通俗易懂。在这里我们先照样子实现一个三栏布局, 两栏固定,中间自适应。

      首先,DOM 结构也是一样的:

     1 <div class="flex-container">
     2     <div class="flex-middle">
     3         Flex main
     4     </div>
     5     <div class="flex-left">
     6         Flex left
     7     </div>
     8     <div class="flex-right">
     9         Flex right
    10     </div>
    11 </div>

      然后执行以下步骤:

      ① 设置 container 布局方式 display: flex; 

      ② 这时候设置 middle 100%; ,同时给两栏定宽,这里假设都是 200px;

      ③ 既然是两栏固定,那么就不让两栏收缩,给 left 和 right 设置 flex-shrink: 0;

      ④ 由于 DOM 结构和我们实际的顺序不一样,这时我们来排个序 left order: 1;,middle order: 2;,right order: 3;

     1 .flex-container {
     2     display: flex;
     3 }
     4 .flex-container>div {
     5     height: 100%;
     6 }
     7 .flex-left {
     8     width: 200px;
     9     background-color: yellow;
    10     order: 1;
    11     flex-shrink: 0;
    12 }
    13 .flex-middle {
    14     width: 100%;
    15     background-color: gray;
    16     order: 2;
    17 }
    18 .flex-right {
    19     width: 200px;
    20     background-color: red;
    21     order: 3;
    22     flex-shrink: 0;
    23 }

      OK啦,现在拖动试一试。可以看出 flex 布局具有更强的适应性,在窗口宽度过小的时候不会造成页面布局混乱。通过设置内容的伸缩,可以实现任意栏的固定和自适应,同时也可以实现三栏自适应,通过设置 flex 内容的 flex-shrinkflex-grow 可以实现自定义的适应性布局。接下来,咱们聊一聊一些个人的遐想,偏非主流的三栏布局。

    四、绝对定位布局

      绝对定位其强大之处在于它的定位性能非常的优秀,这里我们就可以用绝对定位的自动伸缩性来实现一个三栏布局。

      DOM 结构依然不变:

     1 <div class="absolute-container">
     2     <div class="absolute-middle">
     3         Absolute main
     4     </div>
     5     <div class="absolute-left">
     6         Absolute left
     7     </div>
     8     <div class="absolute-right">
     9         Absolute right
    10     </div>
    11 </div>

      注意我们需要将 container 的 postion: relative; ,因为绝对定位元素的参照物为第一个 postion 不为 static 的祖先元素,同时需要使 left 向左浮动,right 向右浮动,同时使 middle 绝对定位,并把左右两边撑开:

     1 .absolute-container {
     2     position: relative;
     3     overflow: hidden;
     4 }
     5 .absolute-container>div {
     6     height: 100%;
     7 }
     8 .absolute-left {
     9     float: left;
    10     width: 200px;
    11     background-color: blue;
    12 }
    13 .absolute-middle {
    14     position: absolute;
    15     left: 200px;
    16     right: 200px;
    17     top: 0;
    18     bottom: 0;
    19     background-color: pink;
    20 }
    21 .absolute-right {
    22     float: right;
    23     width: 200px;
    24     background-color: brown;
    25 }

      注意绝对定位元素的高度需要设 top: 0 bottom: 0 来使其高度撑开。现在试一试是不是同样也实现了三栏布局,不过这种布局方案有一个致命的缺点,就是中间的内容区完全依赖于两栏的高度,如果两栏的高度不够,那么中间内容区的高度也会随着压缩,所以这种方案在很多场景下并不适合。下面我们来聊一个较强一点的非主流三栏布局。

    五、table-cell 三栏布局

       在前三种三栏布局方案中,我们三栏的高度取决于各自的内容区,也就是说如果中间内容多,两边内容少的情况下,页面的高度取决于内容区,同时两栏的高度不会增加,这是当今绝大多数的网站所采用的主流布局。第四种方案中的致命缺陷为中间内容区的高度取决于两栏的最高点。现在我们讨论一种非主流的三栏布局方案,表格布局,使其三栏高度统一,这种布局方案主要是利用了表格布局的伸缩性。首先 DOM 结构有所改变,middle 不能放在最前面了:

     1 <div class="table-cell-container">
     2     <div class="table-cell-left">
     3          Table cell left
     4     </div>
     5     <div class="table-cell-middle">
     6          Table cell main
     7     </div>
     8     <div class="table-cell-right">
     9          Table cell right
    10     </div>
    11 </div>

      这时执行以下步骤:

      ① 将 left、middle、right 都设置为表格单元 display: table-cell;

      ② 给 left 和 right 定宽,这里假设 200px;,同时设置 middle 100%; 

      ③ 这时候由于 middle 把两栏都给挤到两边去了,所以这时候我们要把两栏给挤回来,设置 min- 200px;

     1 .table-cell-container {
     2     position: relative;
     3     overflow: hidden;
     4 }
     5 .table-cell-container>div {
     6     height: 100%;
     7     display: table-cell;
     8 }
     9 .table-cell-left {
    10     width: 200px;
    11     min-width: 200px;
    12     background-color: red;
    13 }
    14 .table-cell-middle {
    15     margin: 0 200px;
    16     width: 100%;
    17     background-color: brown;
    18 }
    19 .table-cell-right {
    20     min-width: 200px;
    21     width: 200px;
    22     background-color: yellow;
    23 }

      OK ,现在试一试是不是同样的是一个三栏布局,而且这种布局方案中的三栏高度是统一的,但是其缺陷就是 middle 不能够像其他三栏布局那样放在最前面得到最先渲染。

    总结

      三栏布局的方式其实有很多,不过只要掌握了其核心思想就可以实现自定义的三栏布局。圣杯布局运用的很广泛,不过其致命的缺点就是 middle 区域占用空间过宽时会把两栏给挤下去,也就是当窗口 size 过小时,而双飞翼布局正是弥补了这一缺点。如果项目不考虑低版本 IE 的兼容性的话,建议还是使用 Flex  布局,simple and powerful,如果你想试试新鲜,也可以尝尝表格布局,你可以在下面随意拖动观察不同布局方案的区别:

    References:

      [1] 张鑫旭 . CSS深入理解流体特征和BFC特性下多栏自适应布局

      [2] 阮一峰 . Flex 布局教程:语法篇

      [3] 张鑫旭 . 我熟知的三种三栏网页宽度自适应布局方法

  • 相关阅读:
    使用Fiddler和雷电模拟器抓取安卓https请求
    Robot Framework -- 安装接口测试库
    Robot Framework --为了进行Web测试,安装SeleniumLibrary外部库
    robotframework+python3+eclipse+RED自动化测试框架初学笔记
    LeetCode Weekly Contest 27
    LeetCode Weekly Contest 26
    京东4.7实习笔试题
    牛客网模拟笔试 2
    4.1几道最近的题目
    网易3.25实习笔试
  • 原文地址:https://www.cnblogs.com/dong-xu/p/7360015.html
Copyright © 2011-2022 走看看