前端一面:盒模型、BFC 与经典布局题
CSS 相关的一面题里,盒模型和 BFC 几乎是高频中的高频,这一篇把“盒子长啥样”“BFC 能解决什么问题”和几道经典布局题放在一起梳理一下。
盒模型:内容、内边距、边框和外边距
标准盒模型下,一个元素的可视区域可以拆成几层:
- content:内容区域;
- padding:内边距;
- border:边框;
- margin:外边距。
默认情况下,元素的 width/height 只包含 content,不包含 padding 和 border:
1/* content-box(默认) */
2.box {
3 box-sizing: content-box;
4 width: 100px; /* 只算内容宽度 */
5 padding: 10px; /* 实际渲染宽度是 100 + 10*2 + border */
6 border: 2px solid;
7}
在实际项目中,更常用的是:
1/* border-box:width 包含 padding + border */
2*,
3*::before,
4*::after {
5 box-sizing: border-box;
6}
这样可以避免在布局时不断手工相加减 padding/border。
BFC(块级格式化上下文):一个“独立的小布局世界”
BFC 听起来很玄乎,本质上可以先记住两点:
- 它是一个独立的布局区域,内部盒子如何排列不会影响到外部;
- 一些与浮动、清除浮动、margin 折叠相关的问题,可以通过制造一个新的 BFC 来解决。
常见的触发 BFC 的方式包括:
float不为none;overflow为hidden/auto/scroll;display: inline-block/table-cell/flex/grid等;position: absolute/fixed。
典型应用场景:
- 清除浮动:给父元素加
overflow: hidden,让它形成 BFC,将内部浮动元素包含起来; - 避免兄弟块级元素之间的 margin 折叠:让其中一个元素形成 BFC。
经典布局题:水平居中、垂直居中、两栏/三栏布局
一面里 CSS 布局经常以“实现某种布局”为题出现,常见的有:
行内/块级元素的水平居中:
- 行内:
text-align: center; - 块级、固定宽度:
margin: 0 auto。
- 行内:
容器内单个元素的水平垂直居中(flex 方案):
1.container {
2 display: flex;
3 justify-content: center; /* 水平居中 */
4 align-items: center; /* 垂直居中 */
5}
经典两栏布局:左侧固定宽度,右侧自适应:
- Flex 方案:左列
width: 200px,右列flex: 1; - 旧方案(float + margin)可以略提一下,表明知道历史方案即可。
- Flex 方案:左列
圣杯/双飞翼布局(可以简单知道有这么回事,不必细写代码)。
在一面答这种布局题时,重点是:
- 能给出一套现代、可维护的方案(Flex/Grid),
- 如果顺带提一句 IE 老方案,算加分项,不是硬性要求。
常见面试题与参考答案
题 1:标准盒模型和 IE 盒模型有什么区别?如何切换?
参考答案要点:
- 标准盒模型(
content-box):width/height只包含内容区域,不包含 padding 和 border; - IE 盒模型(
border-box):width/height包含内容 + padding + border; - 可以通过
box-sizing切换:
1.box {
2 box-sizing: border-box; /* 切到“IE 盒模型”行为 */
3}
可以顺带提一下“在实际项目里通常会全局设置 border-box,更符合直觉”。
题 2:什么是 BFC?它能解决哪些问题?
参考答案要点:
- BFC 是块级格式化上下文,可以理解为一个独立的布局上下文,内部元素的布局不会影响外部;
- 触发方式有很多,比如
float、overflow非visible、display: flex/grid、position: absolute/fixed等; - 常见用途:
- 包裹浮动元素,让父元素撑开高度(清除浮动);
- 避免兄弟块级元素之间的 margin 折叠,通过让其中一个元素单独形成 BFC。
如果面试官继续追问 margin 折叠,可以简要描述“相邻块级元素的上下 margin 会合并成一个”,通过 BFC 把它们“隔开”。
题 3:用 Flex 实现一个左右布局,左边固定 200px,右边自适应
参考实现:
1.layout {
2 display: flex;
3}
4
5.layout-left {
6 width: 200px;
7 flex-shrink: 0; /* 防止过窄时被压缩 */
8}
9
10.layout-right {
11 flex: 1;
12 min-width: 0; /* 避免内容过长撑爆布局 */
13}
参考讲法:
- 左边通过固定
width+flex-shrink: 0保证宽度不被压缩; - 右边设置
flex: 1占据剩余空间; - 如果提到
min-width: 0,可以说明是为了解决某些浏览器中长内容撑爆的问题。
这一题主要是考你对 Flex 的基本属性是否熟悉,回答时可以顺带提一句“实际项目中基本都用 Flex 来解决这类布局问题”。