Ryan Shang

生死看淡,不服就干

0%

三栏布局

这几天看到一个面试题:

已知高度,完成一个三栏布局,左侧200px,右侧200px,中间自适应。

题目看起来不难,第一时间能想起来三种方案:Float、Absolute和Flex,后来发现还有两种:Table和Grid,所以来记录下。

首先写下公共的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
html * {
margin: 0;
padding: 0;
}
.left {
background: red;
width: 200px;
}
.center {
background: yellow;
}
.right {
background: blue;
width: 200px;
}
.container {
min-height: 100px;
margin: 20px;
width: 100%;
}
.left-center-right {
min-height: 100px;
}
.left-center-right>div {
min-height: 100px;
}

下面来写下五种写法:

1. Float

兼容性好,但是会影响文档流

1
2
3
4
5
6
7
8
9
10
11
12
<section class="container float">
<div class="left-center-right">
<div class="left"></div>
<div class="right"></div>
<div class="center">
<h2>Float</h2>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
</div>
</div>
</section>
1
2
3
4
5
6
.container.float .left {
float: left;
}
.container.float .right {
float: right;
}

2. Absolute

兼容性好,但是会影响文档流

1
2
3
4
5
6
7
8
9
10
11
12
<section class="container absolute">
<div class="left-center-right">
<div class="left"></div>
<div class="right"></div>
<div class="center">
<h2>Absolute</h2>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
</div>
</div>
</section>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.container.absolute {
position: relative;
}
.container.absolute .left {
position: absolute;
left: 0;
}
.container.absolute .center {
position: absolute;
left: 200px;
right: 200px;
}
.container.absolute .right {
position: absolute;
right: 0;
}

3. Table

兼容性好,但是比较老旧,布局比较麻烦,已经很少见

1
2
3
4
5
6
7
8
9
10
11
12
<section class="container table">
<div class="left-center-right">
<div class="left"></div>
<div class="center">
<h2>Table</h2>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
</div>
<div class="right"></div>
</div>
</section>
1
2
3
4
5
6
7
8
9
10
11
12
13
.container.table .left-center-right {
display: table;
width: 100%;
}
.container.table .left {
display: table-cell;
}
.container.table .center {
display: table-cell;
}
.container.table .right {
display: table-cell;
}

4. Flex

兼容性较好,在移动端很常用,写法简单。

1
2
3
4
5
6
7
8
9
10
11
12
<section class="container flex">
<div class="left-center-right">
<div class="left"></div>
<div class="center">
<h2>Flex</h2>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
</div>
<div class="right"></div>
</div>
</section>
1
2
3
4
5
6
.container.flex .left-center-right {
display: flex;
}
.container.flex .center {
flex: 1;
}

5. Grid

兼容性不是很好,但是写法最为简单。

1
2
3
4
5
6
7
8
9
10
11
12
<section class="container grid">
<div class="left-center-right">
<div class="left"></div>
<div class="center">
<h2>Grid</h2>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
</div>
<div class="right"></div>
</div>
</section>
1
2
3
4
5
.container.grid .left-center-right {
display: grid;
grid-template-rows: 100px;
grid-template-columns: 200px 1fr 200px;
}

最后,如果题目修改,高度未定的时候,这五种布局还都能成功么?

经过测试,增加中间div的内容使之超出div的高度

1
2
3
4
5
6
7
8
9
<div class="center">
<h2>Grid</h2>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
<p>中间部分</p>
</div>

对比下结果:

正常情况:

1-1

添加内容后:

1-2

可以看出:

  • Table和Flex布局能正常撑开容器高度,未知高度情况下可以考虑这两个方案
  • Float布局中间div高度变高,超出部分被宽度会和left-center-right一样,文字从最左边开始
  • Absolute布局会只撑开中间div的高度
  • Grid容器和div高度不会改变,但是因为grid-template-rows的设定,文字会超出容器