# 三栏布局

题目:假设高度已知,请写出三栏布局,其中左栏、右栏宽度各为 300px,中间自适应。

# 分析

1. 题目真的像我们想得这么简单吗?

其实不然,这道题可以有多种方案,面试官想要通过这个题目考察面试者对 CSS 的掌握程度,是否善于思考、总结

比较容易想到的两种方法是:

  • 浮动
  • 绝对定位

但如果只给出这两个答案,还没到及格线。

2. 进阶

  • flex
  • table cell
  • 网格布局---grid

【下文第二部分,有相应的代码及实现效果演示】

3. 延伸。面试官极有可能就这个题目延伸出若干问题。

  • 这五种方案各自有什么优点和缺点?这几种方案的兼容性如何,如果在做业务的时候,应该选择哪一种方案,哪个是最实用的?
  • 如果把【假设高度已知】去掉,这五种方案的效果?怎么解决出现的问题?

【下文第三部分,有关于这几个问题的参考答案】

# 五种方法的代码实现

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style>
      html * {
        padding: 0;
        margin: 0;
      }
      .layout {
        margin-top: 20px;
      }
      .layout article div {
        min-height: 100px;
      }
    </style>
  </head>
  <body>
    <!-- 浮动解决方案 -->
    <section class="layout float">
      <style media="screen">
        .layout.float .left {
          float: left;
          width: 300px;
          background: #ffcccc;
        }
        .layout.float .right {
          float: right;
          width: 300px;
          background: #ff6666;
        }
        .layout.float .center {
          background: #ffffcc;
        }
      </style>
      <article class="left-right-center">
        <div class="left"></div>
        <div class="right"></div>
        <div class="center">
          <h1>浮动解决方案</h1>
          1.这是三栏布局中间部分 2.这是三栏布局中间部分
        </div>
      </article>
    </section>

    <!-- 绝对定位解决方案 -->
    <section class="layout absolute">
      <style>
        .layout.absolute .left {
          position: absolute;
          width: 300px;
          left: 0;
          background: red;
        }
        .layout.absolute .center {
          position: absolute;
          left: 300px;
          right: 300px;
          background: pink;
        }
        .layout.absolute .right {
          position: absolute;
          width: 300px;
          right: 0;
          background: blue;
        }
      </style>
      <article class="left-center-right">
        <div class="left"></div>
        <div class="center">
          <h1>绝对定位解决方案</h1>
          1.这是三栏布局绝对定位中间部分 2.这是三栏布局绝对定位中间部分
        </div>
        <div class="right"></div>
      </article>
    </section>

    <!-- flexbox 解决方案 -->
    <section class="layout flexbox">
      <style>
        .layout.flexbox {
          margin-top: 150px;
        }
        .layout.flexbox .left-center-right {
          display: flex;
        }
        .layout.flexbox .left {
          width: 300px;
          background: #0000ff;
        }
        .layout.flexbox .center {
          flex: 1;
          background: greenyellow;
        }
        .layout.flexbox .right {
          width: 300px;
          background: blueviolet;
        }
      </style>
      <article class="left-center-right">
        <div class="left"></div>
        <div class="center">
          <h1>flexbox 解决方案</h1>
          1.这是三栏布局flexbox中间部分 2.这是三栏布局flexbox中间部分
        </div>
        <div class="right"></div>
      </article>
    </section>

    <!-- 表格布局 -->
    <section class="layout table">
      <style>
        .layout.table .left-center-right {
          width: 100%;
          display: table;
          height: 100px;
        }
        .layout.table .left-center-right > div {
          display: table-cell;
        }
        .layout.table .left {
          width: 300px;
          background: #0000ff;
        }
        .layout.table .center {
          background: #adff2f;
        }
        .layout.table .right {
          width: 300px;
          background: #008b8b;
        }
      </style>
      <article class="left-center-right">
        <div class="left"></div>
        <div class="center">
          <h1>表格布局 解决方案</h1>
          1.这是三栏布局 表格布局 中间部分 2.这是三栏布局 表格布局 中间部分
        </div>
        <div class="right"></div>
      </article>
    </section>

    <!-- 网格布局 -->
    <section class="layout grid">
      <style>
        .layout.grid .left-center-right {
          display: grid;
          width: 100%;
          grid-template-rows: 100%;
          grid-template-columns: 300px auto 300px;
        }
        .layout.grid .left {
          background: #0000ff;
        }
        .layout.grid .center {
          background: #adff2f;
        }
        .layout.grid .right {
          background: #008b8b;
        }
      </style>
      <article class="left-center-right">
        <div class="left"></div>
        <div class="center">
          <h1>网格布局 解决方案</h1>
          1.这是三栏布局 网格布局 中间部分 2.这是三栏布局 网格布局 中间部分
        </div>
        <div class="right"></div>
      </article>
    </section>
  </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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

页面布局演示,没有???

# 题目的延伸问题

1. 这五种方案各自有什么优点和缺点?这五种方案的兼容性如何,如果在做业务的时候,应该选择哪一种方案,哪个是最实用的?

  • 【浮动】

优点 :兼容性比较好。

缺点 :浮动是脱离文档流的,如果处理不好,会带来很多问题。有些时候需要清除浮动,需要很好的处理浮动周边元素的关系。

  • 【绝对定位】

优点:快捷。

缺点:布局脱离文档流,意味着下面的子元素也要脱离文档流,导致这个方案的有效性是比较差的。

  • 【flex】

优点 :比较完美的解决了浮动和绝对定位的问题。在移动端比较常用。

缺点 :兼容性比较差,不兼容 IE8 及以下的版本。因为这个是 CSS3 中新增的 display 的属性值。

  • 【表格布局】

优点:兼容性比较好。

缺点:操作繁琐,对 SEO 不友好;当某个单元格高度变化时,所在行的其它单元格也会变化。

  • 【网格布局】

优点:代码比较简单。

缺点:兼容性比较差。

因为是较新的技术,如果在面试时回答出这种方法,可以一定程度上体现出面试者对新技术的学习和渴望。

2. 如果把【假设高度已知】去掉,这五种方案的效果?怎么解决出现的问题?

浮动

<!-- 浮动解决方案 -->
<section class="layout float">
  <style media="screen">
    .layout.float .left {
      float: left;
      width: 300px;
      background: #ffcccc;
    }
    .layout.float .right {
      float: right;
      width: 300px;
      background: #ff6666;
    }
    .layout.float .center {
      background: #ffffcc;
    }
  </style>
  <article class="left-right-center">
    <div class="left"></div>
    <div class="right"></div>
    <div class="center">
      <h1>浮动解决方案</h1>
      1.这是三栏布局中间部分 2.这是三栏布局中间部分
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
    </div>
  </article>
</section>
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

浮动的问题

问题的原因

因为浮动的基本原理,中间的内容向左浮动的时候,被左边的块挡住,所以在中间部分排,当文案超出以后,左侧没有遮挡物,就会溢出。

问题的解决

可以通过创建 BFC 的方式解决。

.layout.float .center {
  background: #ffffcc;
  overflow: hidden;
}
1
2
3
4

绝对定位

<!-- 绝对定位解决方案 -->
<section class="layout absolute">
  <style>
    .layout.absolute .left {
      position: absolute;
      width: 300px;
      left: 0;
      background: red;
    }
    .layout.absolute .center {
      position: absolute;
      left: 300px;
      right: 300px;
      background: pink;
    }
    .layout.absolute .right {
      position: absolute;
      width: 300px;
      right: 0;
      background: blue;
    }
  </style>
  <article class="left-center-right">
    <div class="left"></div>
    <div class="center">
      <h1>绝对定位解决方案</h1>
      1.这是三栏布局绝对定位中间部分 2.这是三栏布局绝对定位中间部分
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
    </div>
    <div class="right"></div>
  </article>
</section>
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

绝对定位的问题

flex、表格布局、网格布局

<!-- flexbox 解决方案 -->
<section class="layout flexbox">
  <style>
    .layout.flexbox {
      margin-top: 280px;
    }
    .layout.flexbox .left-center-right {
      display: flex;
    }
    .layout.flexbox .left {
      width: 300px;
      background: #0000ff;
    }
    .layout.flexbox .center {
      flex: 1;
      background: greenyellow;
    }
    .layout.flexbox .right {
      width: 300px;
      background: blueviolet;
    }
  </style>
  <article class="left-center-right">
    <div class="left"></div>
    <div class="center">
      <h1>flexbox 解决方案</h1>
      1.这是三栏布局flexbox中间部分 2.这是三栏布局flexbox中间部分
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
    </div>
    <div class="right"></div>
  </article>
</section>

<!-- 表格布局 -->
<section class="layout table">
  <style>
    .layout.table .left-center-right {
      width: 100%;
      display: table;
      height: 100px;
    }
    .layout.table .left-center-right > div {
      display: table-cell;
    }
    .layout.table .left {
      width: 300px;
      background: #0000ff;
    }
    .layout.table .center {
      background: #adff2f;
    }
    .layout.table .right {
      width: 300px;
      background: #008b8b;
    }
  </style>
  <article class="left-center-right">
    <div class="left"></div>
    <div class="center">
      <h1>表格布局 解决方案</h1>
      1.这是三栏布局 表格布局 中间部分 2.这是三栏布局 表格布局 中间部分
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
    </div>
    <div class="right"></div>
  </article>
</section>

<!-- 网格布局 -->
<section class="layout grid">
  <style>
    .layout.grid .left-center-right {
      display: grid;
      width: 100%;
      grid-template-rows: 100%;
      grid-template-columns: 300px auto 300px;
    }
    .layout.grid .left {
      background: #0000ff;
    }
    .layout.grid .center {
      background: #adff2f;
    }
    .layout.grid .right {
      background: #008b8b;
    }
  </style>
  <article class="left-center-right">
    <div class="left"></div>
    <div class="center">
      <h1>网格布局 解决方案</h1>
      1.这是三栏布局 网格布局 中间部分 2.这是三栏布局 网格布局 中间部分
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
      <p>增加高度</p>
    </div>
    <div class="right"></div>
  </article>
</section>
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

剩下三种方案

# 小结

答题要点

  1. 语义化掌握到位
  2. 页面布局理解深刻
  3. CSS 基础知识扎实
  4. 思维灵活且积极上进
  5. 代码书写规范

题目的扩展

三栏布局

  • 左右宽度固定,中间自适应
  • 上下高度固定,中间自适应

两栏布局

  • 左宽度固定,右自适应
  • 右宽度固定,左自适应
  • 上宽度固定,下自适应
  • 下宽度固定,上自适应

文章首发于我的博客园前端一面/面试常考题 1-页面布局 (opens new window)

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