# 前言

圣杯布局来源于文章 In Search of the Holy Grail,而双飞翼布局来源于淘宝 UED。

虽然两者的实现方法略有差异,不过都遵循了以下要点:

  • 两侧宽度固定,中间宽度自适应
  • 中间部分在 DOM 结构上优先,以便先行渲染
  • 允许三列中的任意一列成为最高列
  • 只需要使用一个额外的 div 标签

直接上布局效果图。

圣杯布局1.gif

区别:

1. 圣杯布局:

  • 布局结构清晰,一目了然
  • 为了让中间 div 内容不被遮挡,将中间 div 设置了左右 padding-left 和 padding-right 后,将左右两个 div 用相对布局 position: relative 并分别配合 right 和 left 属性,以便左右两栏 div 移动后不遮挡中间 div。

2. 双飞翼布局:

  • 布局结构不太直观
  • 为了让中间 div 内容不被遮挡,直接在中间 div 内部创建子 div 用于放置内容,在该 div 里用 margin-left 和 margin-right 为左右两栏 div 留出位置。

# 圣杯布局:

用 float 实现圣杯布局

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>圣杯布局</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        font-size: 25px;
        text-align: center;
      }

      header,
      footer {
        height: 40px;
        width: 100%;
        background: skyblue;
      }

      footer {
        clear: both;
      }

      .wrapper {
        padding: 0 300px 0 150px;
        height: 100px;
      }

      .center {
        float: left;
        width: 100%;
        height: 500px;
        background: plum;
      }

      .left {
        float: left;
        width: 150px;
        height: 500px;
        margin-left: -100%;
        position: relative;
        left: -150px;
        background: pink;
      }

      .right {
        float: left;
        width: 300px;
        height: 500px;
        margin-left: -300px;
        position: relative;
        right: -300px;
        background: hotpink;
      }
    </style>
  </head>
  <body>
    <header>header</header>
    <div class="wrapper">
      <div class="center">center</div>
      <div class="left">left</div>
      <div class="right">right</div>
    </div>
    <footer>footer</footer>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

其中:

左右栏通过添加负的 margin 放到正确的位置了,此段代码是为了摆正中间栏的位置

.wrapper {
  padding: 0 300px 0 150px;
  height: 100px;
}
1
2
3
4

中间栏的位置摆正之后,左栏的位置也相应右移,通过相对定位的 left 恢复到正确位置

.left {
  float: left;
  width: 150px;
  margin-left: -100%;
  position: relative;
  left: -150px;
}
1
2
3
4
5
6
7

中间栏的位置摆正之后,右栏的位置也相应左移,通过相对定位的 right 恢复到正确位置

.right {
  float: left;
  width: 300px;
  margin-left: -300px;
  position: relative;
  right: -300px;
}
1
2
3
4
5
6
7

优点:不需要添加 dom 节点

# 双飞翼布局

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>双飞翼布局</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        font-size: 25px;
        text-align: center;
      }

      header,
      footer {
        height: 40px;
        width: 100%;
        background: skyblue;
      }

      footer {
        clear: both;
      }

      .center {
        float: left;
        width: 100%;
        /*左栏上去到第一行*/
        height: 500px;
        background: plum;
      }

      /*给内部 div 添加 margin,把内容放到中间栏,其实整个背景还是 100%*/
      #inside {
        margin: 0 300px 0 150px;
        height: 500px;
      }

      .left {
        float: left;
        width: 150px;
        height: 500px;
        margin-left: -100%;
        background: pink;
      }

      .right {
        float: left;
        width: 300px;
        height: 500px;
        margin-left: -300px;
        background: hotpink;
      }
    </style>
  </head>
  <body>
    <header>header</header>
    <div class="center">
      <div class="inside">center</div>
    </div>
    <div class="left">left</div>
    <div class="right">right</div>
    <footer>footer</footer>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

优点:不会像圣杯布局那样变形; 缺点是:多加了一层 dom 节点

# 普通三栏布局,其中左右两栏宽度固定,中间自适应。

通过实践,发现 flex 布局和 grid 布局真香。传统的借助浮动和定位的方式,跟上述类似,这里不再赘述,另外也可以参考笔者的另一篇笔记面试常考题 1-页面布局 (opens new window)

# 利用 flex 布局

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>圣杯布局</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        font-size: 25px;
        text-align: center;
      }

      header,
      footer {
        height: 40px;
        width: 100%;
        background: skyblue;
      }

      .wrapper {
        display: flex;
      }

      .left {
        width: 150px;
        height: 500px;
        background: pink;
      }

      .center {
        flex: 1;
        height: 500px;
        background: plum;
      }

      .right {
        width: 300px;
        height: 500px;
        background: hotpink;
      }
    </style>
  </head>
  <body>
    <header>header</header>
    <div class="wrapper">
      <div class="left">left</div>
      <div class="center">center</div>
      <div class="right">right</div>
    </div>
    <footer>footer</footer>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# grid 布局

相关知识点请参照:阮一峰-CSS Grid 网格布局教程 (opens new window)

实现效果图

圣杯布局-grid.png
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>圣杯布局</title>
    <style>
      body {
        display: grid;
        grid-template-areas:
          "header header header"
          "left center right"
          "footer footer footer";
        min-height: 100vh;
        grid-template-rows: 40px 1fr 40px;
        grid-template-columns: 150px 1fr 300px;
        font-size: 25px;
        text-align: center;
      }

      header {
        grid-area: header;
        background: skyblue;
      }

      footer {
        grid-area: footer;
        background: skyblue;
      }

      .left {
        grid-area: left;
        background: pink;
      }

      .center {
        grid-area: center;
        background: plum;
      }

      .right {
        grid-area: right;
        background: hotpink;
      }
    </style>
  </head>
  <body>
    <header>header</header>
    <div class="left">left</div>
    <div class="center">center</div>
    <div class="right">right</div>
    <footer>footer</footer>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

grid 布局非常灵活,对于这种布局的实现有很多种方式。笔者这里先给出最直观的一种,足以体现 grid 的强大。

上次更新: 2021年12月31日星期五下午3点10分