
CSS 面试这件事表面看考的是“背没背过”实际考的是你有没有真正理解浏览器怎么摆放元素、怎么计算样式、怎么渲染页面。我在过去几年帮团队招过不少前端也陪很多候选人模拟过面试发现一个规律能顺利通过 CSS 环节的人靠的不是背题而是心里有一套完整的“渲染模型”。这套模型一旦建立起来不管面试官从哪个角度切入你都能从底层逻辑推导出答案。这篇内容我围绕 CSS 面试中最高频的几类问题展开覆盖布局、盒模型、层叠规则、单位、动画、现代特性、手写题等方向。每个问题都会拆解背后的原理再补上我实际使用和踩坑的经验。不管你是准备面试还是想系统补一补 CSS 基础应该都能在这篇内容里找到能直接用上的东西。1. 布局面试题flex、grid、定位的底层逻辑1.1 flex 布局三个核心属性的计算逻辑面试里 flex 相关的题几乎必出但很多人卡在flex-grow、flex-shrink、flex-basis这三个值的联动关系上。其实你只要记住一个核心flex 布局的本质是“先按基础尺寸摆好剩余空间再按比例分配”。flex-basis决定元素在主轴上的基础尺寸默认值是auto也就是看元素自身的宽高或者内容尺寸。flex-grow决定剩余空间怎么分配默认 0 表示不分配1 表示参与等分。flex-shrink决定空间不足时怎么压缩默认 1 表示按比例压缩。最常见的简写flex: 1实际上等于flex: 1 1 0%意思是基础尺寸为 0然后按 1 的比例平分剩余空间所以它经常被用来实现“三个子元素等宽”的效果。如果你写flex: 1 1 auto那么子元素的基础尺寸会参照内容宽度结果可能不是等宽而是“内容多的更宽”。我在实际项目里踩过一个坑给某个子元素设了flex: 1并且里面放了一串很长的英文单词结果这个元素被撑出了容器。原因是 flex 子项的min-width默认值是auto意味着“不能小于内容的最小尺寸”。解决办法是显式设置min-width: 0或者用overflow: hidden把溢出内容截断。这个点面试官经常拿来追问你主动说出来会显得理解更深。调试 flex 布局时最有效的工具是浏览器开发者工具里的“flex 编辑器”。选中设置了display: flex的容器后可以图形化调整这几个属性实时观察子项的尺寸变化。这个操作看起来简单但能帮你把flex-grow、flex-shrink、flex-basis的联动关系彻底“看”明白。1.2 grid 布局fr 单位和隐式网格的考点grid 这几年在面试里的出现频率越来越高尤其是fr单位的含义和它与%、auto的区别。fr是“剩余空间分配单位”它的计算方式类似 flex 的flex-grow。比如grid-template-columns: 1fr 2fr意思是把容器宽度分成 3 份两列分别占 1 份和 2 份。但如果你写成grid-template-columns: 30% 1fr那第一列固定是容器宽度的 30%剩下的 70% 再按 fr 分配。这个“先固定、再分配”的顺序理解后就不会写错。另一个高频考点是“隐式网格”。当你在网格容器里塞了比预设轨道更多的子元素时浏览器会悄悄创建额外的行或列这些自动生成的轨道就叫隐式网格。它们的尺寸默认是auto也就是根据内容撑开。如果你想让隐式网格也遵循特定的尺寸规则要用grid-auto-rows或grid-auto-columns来控制。有一次我在一个数据看板项目里用 grid 做卡片布局忘了设置grid-auto-rows结果卡片数量超过预设行数后新增行的行高完全由内容决定看起来高高低低特别不整齐。后来加了grid-auto-rows: minmax(120px, auto)问题立刻解决。minmax也是面试爱考的点它表示“最小这么大、最大这么大”灵活性远高于固定尺寸。grid 和 flex 的选型问题也经常被问到。我的习惯是一维布局单行或单列用 flex二维布局同时控制行和列用 grid。比如导航栏的排列用 flex 更自然而整个页面的区域划分、卡片网格、表单的标签和输入框对齐grid 的优势非常明显。1.3 定位体系relative、absolute、fixed、sticky定位相关的面试题核心是“包含块”这个概念。很多候选人知道absolute应该放在relative的父元素里但说不清为什么。position: absolute的定位基准是“最近的、非 static 定位的祖先元素”这个祖先元素就叫包含块。所以你把父元素设为relative子元素的absolute才会以父元素为参考。如果祖先里找不到非 static 定位的元素最终会一路找到最外层也就是视口严格说是初始包含块。很多“定位跑偏”的问题就是这么来的。fixed的包含块通常也是视口所以它表现为“相对于浏览器窗口固定”。但是如果某个祖先元素设置了transform、perspective或filter属性fixed的包含块就会变成这个祖先元素行为会改变。这一点非常容易踩坑面试也常以“给祖先加了 transform 后 fixed 失效”来考察。sticky是我特别推荐大家多用的一个定位方式。它像是relative和fixed的结合体元素在滚动范围内先相对定位等滚动到指定阈值后就“粘住”不走了。实现一个吸顶的表头、侧边栏几行代码就能搞定。但要注意几个限制父容器必须有足够的高度让sticky元素“滚动”否则它还没到阈值就结束定位了。祖先元素不能有overflow: hidden或overflow: auto之外的设置否则可能失效。实际上只要祖先有非visible的 overflowsticky的滚动容器就变了容易出现“不粘”的现象。sticky的生效范围只限于父容器内部超出后就不粘了。我在一个列表页里用sticky做分组标题结果发现标题滚到父容器底部就消失了而不是一直吸在屏幕顶部。排查了半天就是因为父容器的高度只到列表末尾。理解了“生效范围”之后这个行为其实是符合预期的。2. 盒模型与层叠规则面试必问的底层原理2.1 标准盒模型与怪异盒模型的差异盒模型是 CSS 里最基础但也最要命的概念。标准盒模型里width只表示内容区宽度不包含 padding 和 border。而怪异盒模型也叫 IE 盒模型里width包含内容、padding 和 border。面试里经常这么问“一个元素width: 200px、padding: 20px、border: 5px它的实际占位宽度是多少”如果默认标准盒模型答案是200 40 10 250px如果加了box-sizing: border-box实际占位宽度就是200px内部的内容宽度被压缩为200 - 40 - 10 150px。我个人的实践是全局都设置为border-box因为这样更符合“我设定的宽度就是最终占位宽度”的直觉。特别是做响应式布局时border-box能避免因为 padding 或被加边框导致布局溢出。你可以在全局样式中声明*, *::before, *::after { box-sizing: border-box; }这种“一切都用 border-box”的做法在很多大型项目里都很常见面试时主动提出来再解释为什么这样做会显得你很有工程经验。2.2 层叠上下文与优先级z-index 不是越大越好很多人以为z-index越大就越靠上层但面试题里经常会反问你“为什么 z-index 很高的元素被 z-index 很低的元素盖住了”这就是“层叠上下文”在作怪。理解了层叠上下文之后CSS 面试的深度就上了一个台阶。z-index只在同一个层叠上下文内部比较。以下几个条件都会触发一个元素产生层叠上下文position为relative、absolute或fixed且z-index不是auto。opacity小于 1。transform不是none。filter不是none。will-change指定了某个可能产生层叠上下文的属性。假设有两个子元素一个z-index: 999另一个z-index: 1如果它们的父元素形成了两个相互独立的层叠上下文那么层级比较发生在“父元素”之间而不是子元素之间。也就是说A 容器里即使子元素 z-index 很低也完全可能高于 B 容器里 z-index 很高的元素因为比较的是容器的层级。我做过一个管理后台项目弹窗和下拉框互相覆盖的问题反复出现。后来把弹层组件加上position: fixed和z-index再把遮罩层放同一个容器层级关系一下清爽了。核心原则是能用“额外创建层叠上下文”来隔离层级风险就不要靠堆叠超大的 z-index。CSS 优先级specificity的计算也是必考。不少人以为优先级是“数量比较”或者“类名会不会覆盖 id”。准确规则是按 4 个维度计算分别对应内联样式、id 选择器、类/属性/伪类选择器、元素/伪元素选择器。比如#app .btn的优先级是 1 个 id、1 个类会覆盖.content .btn2 个类。一个类加十个类也抵不过一个 id因为 id 维度的权重更高。面试技巧是别跟面试官扯“甲乙丙丁”直接说“id 选择器优先于类选择器类选择器优先于元素选择器优先级相同时后写的覆盖先写的内联样式最高!important最高优先级但要慎用”。讲清楚这几点再举一个“当你用!important时其实是给代码埋雷”的原因后续维护的人必须用同样带!important的声明才能覆盖你这会让级联规则失控。2.3 BFC为什么能解决这么多布局问题块级格式化上下文Block Formatting Context简称 BFC是 CSS 面试里的经典话题。你可以把 BFC 理解成一个“独立的渲染区域”里面的元素布局不会影响外面外面的布局也不会渗透进来。BFC 有很多触发条件常见的有float非none。overflow非visible。display为inline-block、flex、grid、table-cell等。position为absolute或fixed。BFC 的三个经典应用场景面试必考清除浮动带来的父容器高度塌陷把父元素触发成 BFC比如overflow: hidden它就能把浮动的子元素“包裹”住。防止外边距合并相邻兄弟元素之间上方元素设margin-bottom下方元素设margin-top实际间距取较大值而不是相加值。给其中一个元素包一层 BFC就能避免合并。实现两栏自适应布局左栏固定宽度并浮动右栏触发 BFC 后右边的区域就不会被左栏覆盖而是自动占据剩余空间。面试官如果问你“怎么创建一个 BFC”很多人只会背overflow: hidden。其实你还可以用display: flow-root这是一个专门为了创建 BFC 而设计的属性副作用最小。这个冷知识能让你在候选人里显得独特。我实际开发过程中很少刻意“创建 BFC”但理解这个概念对排查浮动、边距合并这类问题帮助极大。比如有一次排行榜列表的第一项上方出现了不可能存在的间距查过才知道是上一项margin-bottom和下一项margin-top合并了通过调整间距设置或包一层容器解决。3. 单位与数值CSS 的隐藏考点3.1 相对字体单位 em 与 rem 的纠葛关于em最常见的坑是“嵌套翻倍”。em是相对当前元素的字体大小但如果嵌套结构font-size也用了em就会层层放大或缩小。一个典型的例子.parent { font-size: 20px; } .child { font-size: 0.8em; /* 相当 16px */ } .grandchild { font-size: 0.8em; /* 相当 12.8px而不是 16px */ }因为.child的font-size: 0.8em是相对父元素的20px结果变成16px。而.grandchild的0.8em是相对父元素.child的16px结果变成12.8px。链式反应会让很多人困惑。rem只相对根元素html的字体大小不受中间层级影响。所以我通常用rem来设定全局字号、间距用em来设计某个局部组件内部的相对尺寸比如按钮里的图标大小跟随按钮字号。另一个面试考点是“移动端适配为什么常用 rem”思路是设置根元素html的font-size为视口宽度的一定比例比如 1/10这样页面上所有的rem单位都会随视口宽度等比缩放。这种方案在以前很流行但现在有了更多选择比如可以用vw、clamp()等 CSS 函数实现类似效果而无需依赖 JavaScript 去动态计算根字号。如果你在面试里提“我不会首选 rem 做适配而是优先考虑clampvw”很容易给面试官留下“技术紧跟时代”的印象。3.2 视口单位 vh、vw 与百分比的坑vh、vw在移动端有一个著名的坑地址栏收起和弹出时100vh会发生变化导致页面底部被遮挡或出现空白。移动浏览器的可视高度和vh定义并不完全一致这是历史遗留问题。解决方案有两种用100dvhdynamic viewport height适配动态视口。用100svhsmall viewport height作为保守最小值。如果两者都不放心最可靠的方案是直接用min-height: 100vh并保证内部内容能自然撑开或者给关键布局设置position: fixed并计算合适的top/bottom。%也有一个特别容易忽略的考点百分比margin和padding是按父元素宽度计算的不是高度。也就是说无论你是在竖向设置margin-top: 50%还是横向设置margin-left: 50%都是参考父元素宽度的 50%。这个行为在面试里经常被拿来当成“离谱但正确”的观察点。我做过一个移动端适配项目正方形的卡片需要固定宽高比。同事直接用width: 50%接着很自然地写height: 50%结果根本不成立因为高度百分比依赖父级高度。后来用aspect-ratio: 1 / 1一行解决。面试时提到这个场景能体现你跟现代 CSS 特性能接上。4. 颜色与文本容易被小视的细节4.1 色值表示与透明度机制面试里关于颜色问得最多的是rgba、hsl和opacity的区别。opacity影响元素自身及所有子元素的整体透明度而rgba或hsla只影响单个元素的背景色或者设置的具体颜色属性。这个差异在日常开发里经常导致“背景透明了但文字还是清晰的”和“背景透明了文字也跟着透明了”两种截然不同的效果。hsl是很有价值的一种颜色表示法它的三个参数分别是色相、饱和度、明度。用hsl调整明度来做“hover 变暗”效果非常直观不用去算 RGB 的变化值。现代 CSS 里还有很多新颜色函数比如lab()、lch()、oklch()它们在色域和感知均匀性上有更好的表现。面试时如果能讲出这些新函数的价值——比如用oklch做调色板更符合人眼感知——会有加分。4.2 字体、行高与文本溢出处理font-size、line-height、letter-spacing这些和文本渲染相关的属性看起来简单但有几个反认知的考点。比如line-height设置为无单位数值时是相对自身font-size的倍数也是推荐的做法因为完整继承了比例而不是绝对数值而设置为带单位的值如20px时一旦嵌套里字体大小变了行高不会跟着等比变化容易出现行间距不协调。文本溢出的“三件套”是一个超高频率的手写题.ellipsis { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }很多候选人会背这三行但面试官往往会追加一句“两行省略怎么做”答案是用-webkit-line-clamp.clamp2 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }它的原理是让容器变成一个垂直排列的弹性盒子并且限制行数。这个属性确实是非标准的 WebKit 扩展但几乎所有现代浏览器都支持可以放心使用。text-indent的百分比单位也是考点。它的百分比是相对父元素宽度的而不是自身宽度或行高。这在首行缩进时没问题但如果你用text-indent做“负文本隐藏 Logo 文字”之类的技巧时要确认父级宽度是否如预期。我自己做过一个电商项目要求所有产品名最多两行超出部分省略。在这个场景里除了写-webkit-line-clamp还要配合word-break: break-all防止因为长英文单词把容器撑破。这些小细节面试官问到的时候如果你主动说出来会让人觉得你不是“背答案”而是真正处理过生产环境的问题。5. 动画与过渡链路原理比关键帧更重要5.1 CSS 动画与合成器为什么 transform 和 opacity 更快面试里提到性能优化通常会问“CSS 动画为什么比 JS 动画更流畅或者什么时候其实一样卡”。这背后涉及浏览器渲染流水线样式计算、布局、绘制、合成。大多数 CSS 属性变化会触发布局或绘制比如改变width、left、top都会导致回流而只改变transform和opacity可以在合成阶段完成不需要重新布局和绘制因此性能最好。实际开发里做位移动画时推荐使用transform: translate(...)而不是直接改top/left。因为transform不会触发布局页面可以用 GPU 加速。GPU 合成会把该层作为纹理交给 GPU 处理动画看起来更流畅帧率更稳定。但是盲目“所有元素都开硬件加速”是大忌。如果你让过多元素启用 3D 变换或will-change: transform会占用 GPU 内存反而导致卡顿甚至黑屏。我的经验是只对真正需要动画的元素处理同时尽量让动画元素保持在独立的层上动画结束后撤掉不必要的属性。5.2 animation 的关键细节与常见陷阱animation-fill-mode是一个被低估但必考的参数。它的四个值none、forwards、backwards、both决定了动画开始前和结束后元素应用哪一帧的样式。举一个很常见的需求一个弹窗从透明变为不透明结束后要保持可见状态。如果你不设置forwards动画结束后元素就会回到原始状态出现“闪回来”的效果。但forwards会保留动画结束时的状态如果页面交互里跟正常样式冲突也可能埋雷所以我会优先考虑用animation-direction加alternate或者直接控制opacity本身的默认值来达到预期。还有一点是动画的infinite循环。面试官可能会问“如何让一个动画暂时停住”。常见做法是设置animation-play-state: paused并在 JS 里切换或者用animation-timeline这类新特性实现滚动驱动动画让动画进度与滚动位置绑定。滚动驱动是 CSS 里比较新的能力很多开发还没接触过聊出来能体现你的知识更新速度。我记得有一次做侧边栏收起动画最开始用 JS 改width动画很卡。后来改成 flex 布局在侧边栏内部宽度设为 0 并配合transform位移再用transition过渡整条动画才顺畅起来。这个案例在面试里特别适合作为“CSS 动画只能做简单位移”的反例。6. 现代 CSS 特性面试新宠6.1 CSS 自定义属性变量不只是变量CSS 自定义属性CSS Variables现在是很多团队的主题方案基础。比如你可以定义:root { --primary-color: #2a6df4; --spacing-base: 8px; }然后到处使用var(--primary-color)。它可以和层叠机制结合在不同作用域覆盖同一个变量从而实现主题切换。常见做法是给html或某个容器加一个>[data-themedark] { --primary-color: #79a8ff; --bg-color: #1a1a1a; }页面里凡是使用var(--bg-color)的地方都会自动跟随主题变化。这个方案我强烈推荐因为想做品牌改色、明暗主题切换时纯 CSS 变量能省下大量 BEM 修改样式的时间。但如果项目里支持特别老的浏览器比如非常旧的 WebView就要小心 CSS 变量不支持导致整块样式失效。这种情况下可以利用var()的默认值特性写回退color: #333; color: var(--text-color, #333);。第二行被支持时会覆盖第一行不支持时第二行失效保留第一行兜底。还有一个冷知识CSS 变量可以被 JS 动态读取和赋值所以可以做到“JS 驱动 CSS 变量的变化然后 CSS 变量驱动动画”比在 JS 里逐条改样式更高效。我自己在做图表可视化时经常用 JS 更新--chart-column-height这类变量让柱状图高度由 CSS 直接渲染代码简洁很多。6.2 容器查询、级联层与逻辑选择器容器查询Container Queries是响应式设计的一次升级。传统响应式通常只依赖视口宽度比如media (max-width: 768px)。但容器查询可以让组件根据自己所在容器的宽度来决定布局这样同一套卡片组件在窄侧栏里自动变成单列在主内容区里自动变成多列无需关心整体视口大小。用法示例.card { container-type: inline-size; } container (max-width: 320px) { .card-title { font-size: 14px; } }级联层layer是我觉得前景很好但国内面试还不太常见的特性。它的意义在于显式地声明样式优先级避免无休止地靠!important和选择器加权来压制样式。你可以在入口 CSS 里定义层级layer reset, base, components, utilities;之后分别写入对应层的代码。后声明的层优先级更高同一层内再按常规选择器比较。这样处理第三方库样式覆盖非常干净把第三方样式放进base层自己的业务样式放在components层通常不再需要!important。逻辑选择器方面:is()和:has()也值得掌握。:has()被称作“父选择器”因为它能根据子元素的状态来选中父元素比如.form-row:has(input:required) { border-left: 3px solid red; }这行代码选中了所有包含必填输入项的表单行。以前要实现这种效果只能给表单行手动加类名或依赖 JS 动态判断现在纯 CSS 就能完成极大地解放了手写逻辑的工作量。:has()在现代浏览器里已经得到比较广泛的支持了面试里聊到这个会是一个亮点。7. 手写代码题不能只靠背7.1 高频手写题三角形、加载动画、按钮状态手写题是 CSS 面试的另一种形式核心就一个字快。面试官不是考你会不会用工具而是考你在几秒钟内能不能写出稳妥的代码。画三角形最典型的方案是通过 border 组合.triangle { width: 0; height: 0; border: 20px solid transparent; border-top-color: #333; }这个方案的原理是元素宽高为 0四个边框会按 45 度拼接成一个矩形设置三条边透明剩一条边自然就成了三角形。随之旋转方向只需要改border-top-color为border-bottom-color、border-left-color或border-right-color。如果面试官问你“为什么 border 能画出三角形”你能把这个拼接原理讲清楚印象分会很高。加载动画也很常考。最经典的是旋转圆圈.spinner { width: 32px; height: 32px; border: 4px solid rgba(0, 0, 0, 0.1); border-top-color: #333; border-radius: 50%; animation: spin 0.8s linear infinite; } keyframes spin { to { transform: rotate(360deg); } }再进阶一点多段跳跃的加载动画考察animation-delay的使用。假如有 5 个圆点每个圆点错开0.1s开始动画就能形成波纹效果。你可以在面试时现场写出来并且补一句“这里用负延迟更高效因为负值的动画会从中间状态开始跑不需要等第一轮循环”。按钮的 hover 和 active 状态也是一个手写考点。很多人只知道:hover但忘了:focus-visible和:active的差异。hover是鼠标悬停focus-visible是键盘导航时聚焦出现的轮廓active是鼠标按下去的瞬间。无障碍规范很看重焦点样式面试时提一句“我给按钮写了:focus-visible的清晰轮廓确保键盘用户能用 Tab 操作”会让面试官觉得你有工程化意识。7.2 实用布局题水平垂直居中、粘性页脚、多栏自适应水平垂直居中是 CSS 面试的“必考题中的必考题”没有唯一的正确答案我觉得最靠谱的答案顺序是flex 方案父容器display: flexalign-items: centerjustify-content: center。grid 方案父容器display: gridplace-items: center代码更短。absolute transform子元素position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)常用于不改变父容器布局方式时。老式margin: autoposition: absolute 四边为 0 的技巧。选择哪个方案取决于你是否希望“父元素和子元素不互相干扰”。flex和grid是主流absolute方案在弹窗、浮层场景里仍然有效。粘性页脚Sticky Footer也是一个经典手写场景内容少时页脚要贴底内容多时页脚正常跟随。用 flex 最简单body { display: flex; flex-direction: column; min-height: 100vh; } main { flex: 1; }页面内容容器自适应占满剩余空间页脚自然被“推”到底部。这个写法比老式的“padding-bottom 占位法”和“margin-top 负值法”都干净很多面试时能写出这种方案会显得你对现代布局模式很熟练。多栏自适应布局常见的还有“左固定、右自适应”。用 grid 最直观.container { display: grid; grid-template-columns: 240px 1fr; }左栏 240px右栏占满剩余空间没有浮动和清理浮动的负担。如果你写的是两栏的常规内容页这个方案几乎是最佳的。7.3 面试心态别停在“知道”层面最后想说说心态层面的东西。CSS 面试题看着零散但其实有脉络可循。从渲染机制到盒模型从布局方式到层叠规则从响应式适配到动画性能你会发现每个知识点背后都指向同一个底层模型浏览器如何理解并渲染 CSS。所以我的准备方法是不背题而是针对每个知识点问自己“为什么会出现这个问题”“浏览器为什么要这么设计”“如果让我设计浏览器我会怎么做”。这样的思考方式不仅适合面试也有助于实际开发时做技术选型和问题排查。8. 复盘值得记住的通用排查技巧这里我分享几个在团队和项目中反复用到的、可以迁移到任何 CSS 问题里的排查思路样式不生效时先看选择器优先级是不是被更高的规则压住再看有没有父级创建了层叠上下文。元素位置不对时先在开发者工具里查看它的position、父级容器的尺寸和 overflow 设置。自适应布局异常时优先怀疑flex的min-width: auto或者 grid 轨道的1fr与其他单位的混用。动画卡顿先看是否在改动width/height/top/left等触发布局的属性换成transform优先。兼容性出问题时用“层层回退”的思路新旧属性一起写浏览器自己选择能用的那条。有一次我在一个移动端页面上排查一个“图片底部莫名多了几像素间距”的问题最后发现是图片下面的换行空白导致的给图片设置display: block后间隙消失。这种问题很常见底层原因是行内元素的基线对齐机制。这类“幽灵间隔”虽然是老问题但在面试里有机会的话拿出来聊能体现你对行内排版细节的理解。还有一次做多端登录页明明代码一样iOS 和 Android 的样式总有几像素差异。这些大多和系统默认字体、边框渲染参数、输入框的内阴影有关。处理方式是统一重置样式把input、button的appearance设为none再手动处理边框和阴影。遇到这类问题时只要脑子里的“渲染模型”是清晰的很快就能推理出原因在哪。CSS 是一门需要反复实操和踩坑的语言面试题只是检验你实践深度的方式。如果你平时真正在写页面、查过样式、优化过性能那么应付这些问题会是很自然的事。反过来如果只是背了一堆概念一旦面试官追问“为什么”就很容易露馅。我的建议是准备面试时多手写、多改造、多实验拿到一个布局需求先自己写一版再试试如果不用 flex 还能不能实现用一个新的单位时故意在移动端模拟器里看它的表现写动画时打开 Performance 面板看一下哪一步耗时最多。这样形成的经验很难被遗忘也远比背面试题更有价值。