Skip to content

圣杯布局和双飞翼布局

我们希望有一种简单高效的三栏布局方式可以实现以下要求:

  • 两边固定宽度,中间自适应
  • 先加载中间的内容(因为两边是导航栏和广告栏,中间是内容区)

2006 年,圣杯布局在 Matthew Levine 的文章 In Search of the Holy Grail 中被提出。也许是因为当时该模板有效的解决了以上需求(“圣杯”象征“渴求之物”),又或者是因为将左右两栏定位到两侧的过程十分像杯把(圣杯有杯把吗?),它被命名为“圣杯”。

圣杯布局

通过为父元素设置左右padding,然后利用浮动和负边距将左右两栏移动到适当位置,并使用相对定位调整左右两栏的位置。

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .container {
        padding: 0px 100px;
        min-width: 300px;
        overflow: hidden;
      }
      .left {
        float: left;
        position: relative;
        left: -100px;
        margin-left: -100%;
        width: 100px;
        height: 100px;
        background-color: red;
      }
      .center {
        float: left;
        width: 100%;
        height: 100px;
        background-color: green;
      }
      .right {
        float: left;
        position: relative;
        left: 100px;
        margin-left: -100px;
        width: 100px;
        height: 100px;
        background-color: blue;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="center"></div>
      <div class="left"></div>
      <div class="right"></div>
    </div>
  </body>
</html>

缺点

  • 某一列内容溢出时,三栏不是等高的。(进行等高布局解决)
  • 中间栏的最小宽度不能小于左右两栏的宽度,否则左右两栏会掉到下一行。(设置 min-width 解决)

双飞翼布局

通过在中间栏内部添加一个内部容器,并为这个内部容器设置左右margin来保留左右两栏的位置,同样利用浮动和负边距来实现三栏布局。

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      *{
        margin: 0;
        padding: 0;
      }
      body{
        width: 100vw;
        height: 100vh;
      }
      .container > div{
        float: left;
      }

      /* 左 */
      .left {
        margin-left: -100%;

        width: 100px;
        height: 100vh;
        background: red;
      }

      /* 中 */
      .center {
        width: 100%; /* 自适应 */
        height: 100vh;
        background: green;
      }
      .inner {
        /* 防止中间的内容被覆盖 */
        padding: 0 100px;
      }

      /* 右 */
      .right {
        margin-left: -100px;

        width: 100px;
        height: 100vh;
        background: blue;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="center">
        <div class="inner">中</div>
      </div>
      <div class="left">左</div>
      <div class="right">右</div>
    </div>
  </body>
</html>

优点

  • 双飞翼布局省去了很多 css,由于不使用定位,中间栏的最小宽度不再受限于左右两栏宽度。

缺点

  • 双飞翼布局多加一层 dom 树节点,增加渲染树生成的计算量, dom 结构不如圣杯布局简单直观。
  • 三列等高问题仍然要单独解决。

Released under the MIT License.