三栏布局是常见的布局样式,要求是中间栏宽度自适应,左右两栏的宽度固定


一、浮动布局

将左右两栏和中间栏分别设置为浮动元素,并设置不同的宽度。

1. 浮动 float + calc()

  • 核心思想:先使用浮动将三栏水平排列,然后对中间栏使用 calc() 函数来计算去除左右两栏固定宽度后剩余的宽度。
  • 优点:逻辑简单,思路清晰。

HTML 结构:

1
2
3
4
5
6
7
<header>Header</header>
<div class="container">
<div class="left">Left</div>
<div class="middle">Middle</div>
<div class="right">Right</div>
</div>
<footer>Footer</footer>

CSS 样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
div {
height: 200px;
}
.left {
float: left;
width: 300px;
}
.middle {
float: left;
width: calc(100% - 500px);
}
.right {
float: right;
width: 200px;
}

2. 浮动 float + margin 负值

核心思想:利用浮动的方式,为左右两栏设置对应方向的浮动。中间一栏设置左右两个方向的 margin 负值。注意这种方式,中间一栏必须放到最后

HTML 结构:

1
2
3
4
5
6
7
<header>Header</header>
<div class="container">
<div class="left">Left</div>
<div class="right">Right</div>
<div class="middle">Middle</div>
</div>
<footer>Footer</footer>

CSS 样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
div {
height: 200px;
}
.left {
float: left;
width: 300px;
}
.right {
float: right;
width: 200px;
}
.middle {
margin-left: 300px;
margin-right: 200px;
}

3. 圣杯布局

核心思想:利用浮动外边距负值相对定位来实现。

  1. 父级容器设置左右 marginpadding 留出两边栏的位置,三列均设置向左浮动;
  2. 中间列放在文档流最前面,宽度设置为100%(父级元素宽度),因此后面两列都被挤到了下一行;
  3. 再通过设置 margin 负值将其移动到上一行;
  4. 再利用相对定位position: relative,分别配合rightleft属性定位到两边。

注意:圣杯布局中间列的宽度不能小于两边任意列的宽度,而双飞翼布局则不存在这个问题。

HTML 结构:

1
2
3
4
5
6
7
<header>Header</header>
<div class="container">
<div class="middle">Middle</div>
<div class="left">Left</div>
<div class="right">Right</div>
</div>
<footer>Footer</footer>

CSS 样式:

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
.container {
height: 200px;
padding-left: 300px;
padding-right: 200px;
}
.middle,
.left,
.right {
float: left;
height: 100%;
}
.middle {
width: 100%;
}
.left {
width: 300px;
margin-left: -100%;
position: relative;
left: -300px;
}
.right {
width: 200px;
margin-right: -200px;
position: relative;
}

4. 双飞翼布局

核心思想浮动 + 外边距负值

双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列paddingmargin 值来实现的,而不是通过父元素paddingmargin 来实现的。为了让中间 div 内容不被遮挡,需要在中间 div 内部创建子 div 用于放置内容,在该 div 里用 margin-leftmargin-right 为左右两栏留出位置。

HTML 结构:

1
2
3
4
5
6
7
8
9
<header>Header</header>
<div class="container">
<div class="middle">
<div class="inner">Middle</div>
</div>
<div class="left">Left</div>
<div class="right">Right</div>
</div>
<footer>Footer</footer>

CSS 样式:

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
.container {
height: 200px;
}
.middle,
.left,
.right {
float: left;
height: 100%;
}
.middle {
width: 100%;
}
.inner {
height: 100%;
padding-left: 300px;
padding-right: 200px;
}
.left {
width: 300px;
margin-left: -100%;
left: -300px;
}
.right {
width: 200px;
margin-left: -200px;
}
圣杯布局 双飞翼布局
由来 由一篇名为《In Search of the Holy Grail》的文章提出 由淘宝 UED 团队提出
实现方法 在父元素上设置 padding-left 和 padding-right,给左右两边的内容设置 position 为 relative,并通过左移和右移来使得左右两边的内容得以展现。 在中间一栏的外层再套一个 div 用于放置内容,在给这个中间的 div 设置 margin-left 和 margin-right 来为左右两栏留出位置。
优点 不需要添加多余的 Dom 节点 可以避免布局混乱的问题,更稳定
缺点 当浏览器窗口过窄时,可能会导致布局混乱 需要添加多余的 dom 节点,增加了 html 结构复杂度

二、定位布局

将左右两栏和中间栏分别设置为绝对定位元素,并设置不同的位置。

5. 绝对定位 position

核心思想:利用绝对定位的方式。

优点:这种实现方式的三栏 HTML 结构可以任意摆放,不用考虑先后次序。

HTML 结构:

1
2
3
4
5
6
7
<header>Header</header>
<div class="container">
<div class="left">Left</div>
<div class="right">Right</div>
<div class="middle">Middle</div>
</div>
<footer>Footer</footer>

CSS 样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
div {
height: 200px;
}
.container {
position: relative;
}
.left {
position: absolute;
left: 0;
width: 300px;
}
.middle {
position: absolute;
left: 300px;
right: 200px;
}
.right {
position: absolute;
right: 0;
width: 200px;
}

三、表格布局

将父元素设置为表格显示,并在子元素中设置不同的单元格宽度。

6. 表格 table

实现方法:将整个页面用一个 table 标签包裹,然后在 table 中创建一行三列的单元格,将左右两栏的宽度设置为固定值,中间一栏的宽度设置为 100%,这样就可以实现两边固定,中间自适应的效果。

优点:兼容性好,代码简单。

缺点:不符合语义化的原则,不利于 SEO 优化,不方便维护和修改。

HTML 结构:

1
2
3
4
5
6
7
<table>
<tr>
<td class="left">左侧栏</td>
<td class="middle">中间栏</td>
<td class="right">右侧栏</td>
</tr>
</table>

CSS 样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
table {
width: 100%;
height: 300px;
border-collapse: collapse;
}
td {
border: 1px solid black;
}
.left {
width: 200px;
background-color: lightblue;
}
.middle {
background-color: rgb(214, 214, 214);
}
.right {
width: 200px;
background-color: lightgreen;
}

四、弹性布局

将父元素设置为 Flex 布局,并在子元素中设置不同的 flex-grow 值。

7. 弹性布局 flex

核心思想:利用 flex 布局的方式,左右两栏设置固定宽度,中间一栏设置为 flex: 1;

其中 flex: 1; 等同于 flex: 1 1 auto;,等同于 flex-grow: 1; flex-shrink: 1; flex-basis: auto;

优点:这种实现方式代码非常简洁。

HTML 结构:

1
2
3
4
5
6
7
<header>Header</header>
<div class="container">
<div class="left">Left</div>
<div class="middle">Middle</div>
<div class="right">Right</div>
</div>
<footer>Footer</footer>

CSS 样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
div {
height: 200px;
}
.container {
display: flex;
}
.left {
width: 300px;
}
.middle {
flex: 1;
}
.right {
width: 200px;
}

8. 弹性布局 flex 实现圣杯布局

核心思想:中间列放在文档流最前面,从而实现优先渲染。然后利用 flex 布局的方式,将左栏设置 order: -1; 属性放到最前面。

优点:代码简洁,中间栏优先渲染。

HTML 结构:

1
2
3
4
5
6
7
<header>Header</header>
<div class="container">
<div class="middle">Middle</div>
<div class="left">Left</div>
<div class="right">Right</div>
</div>
<footer>Footer</footer>

CSS 样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
div {
height: 200px;
}
.container {
display: flex;
}
.middle {
flex: 1;
}
.left {
width: 300px;
order: -1;
}
.right {
width: 200px;
}

五、网格布局

将父元素设置为 Grid 布局,并在子元素中设置不同的 grid-column 和 grid-row 值。

9. 网格布局 grid

核心思想:利用 grid 布局的方式,左右两栏设置固定宽度,中间一栏设置为 auto。

优点:这种实现方式代码也非常简洁。

缺点:Grid 布局的兼容性不如 Flex 布局。

HTML 结构:

1
2
3
4
5
6
7
<header>Header</header>
<div class="container">
<div class="left">Left</div>
<div class="middle">Middle</div>
<div class="right">Right</div>
</div>
<footer>Footer</footer>

CSS 样式:

1
2
3
4
5
6
7
8
div {
height: 200px;
}
.container {
display: grid;
/* 核心代码:左右两栏固定宽度,中间自适应宽度 */
grid-template-columns: 200px auto 200px;
}

总结思考

  • 如果页面过窄导致出现错位,可以通过为容器或页面设置 min-width

  • 圣杯布局和双飞翼布局的共同优点是,使中间一栏处于文档流最前面,从而实现优先渲染。

  • 调整三栏布局中适当元素的高度,可以实现占满全屏。


【参考内容】:

[1] 实现三栏布局的 7 种方法

[2] 圣杯布局和双飞翼布局的理解和区别

[3] 圣杯布局三种方式

[4] 经典圣杯布局和双飞翼布局