前端面试100问系列 | 第2章:CSS 核心考点,布局与视觉的修罗场!
一、盒模型box-sizing到底救了多少人 标准答案CSS盒模型分为两种标准盒模型W3Cwidth 内容区宽度contentpadding 和 border 在外部扩展。IE盒模型怪异width content padding borderpadding和border向内挤压。box-sizing属性控制使用哪种盒模型box-sizing: content-box默认标准盒模型。box-sizing: border-box推荐IE盒模型固定宽高后padding/border不会撑大盒子。 代码演示/* 标准盒模型默认 */ .box-standard { box-sizing: content-box; width: 200px; padding: 20px; border: 2px solid red; /* 实际宽度 200 40 4 244px ❌ 容易撑破布局 */ } /* IE盒模型推荐 */ .box-border { box-sizing: border-box; width: 200px; padding: 20px; border: 2px solid red; /* 实际宽度 200px ✅ 内容区压缩为 200-40-4156px */ }!-- 实际项目中全局重置Ant Design / Element Plus 都这么干 -- style * { margin: 0; padding: 0; box-sizing: border-box; /* 一劳永逸 */ } /style 面试官追问Q父元素宽度500px子元素左右padding各20pxborder各1px想让子元素占满父元素宽度宽高怎么设置A子元素width: 100%; box-sizing: border-box;即可。如果是content-box100% 40 2 542px直接溢出。二、BFC块级格式化上下文——CSS最核心的结界 标准答案BFCBlock Formatting Context是页面中一个独立的渲染区域内部元素的布局不会影响外部元素。触发BFC的条件高频考点触发方式示例根元素html本身就是BFCfloat不为nonefloat: left/rightposition为absolute/fixed脱离文档流display为inline-block / flex / grid / table-cell等overflow不为visibleoverflow: hidden/auto/scrollcontain: layout / paint现代浏览器BFC的核心特性面试必背内部box垂直排列margin会折叠塌陷。BFC内部不会与浮动元素重叠经典两栏自适应。BFC内部浮动元素也会参与高度计算清除浮动。 代码演示清除内部浮动!-- ❌ 父元素高度塌陷子元素浮动父元素高度为0 -- div classparent styleborder:2px solid blue; div stylefloat:left; width:100px; height:100px; background:red;浮动/div /div !-- 父元素border紧贴着没有高度 -- !-- ✅ 触发BFC父元素高度被浮动撑开 -- div classparent styleborder:2px solid blue; overflow:hidden; div stylefloat:left; width:100px; height:100px; background:red;浮动/div /div !-- 父元素高度 100px border -- 代码演示防止外边距塌陷!-- ❌ 两个兄弟div的margin会合并取最大值 -- div stylemargin-bottom: 30px; background:red; height:50px;A/div div stylemargin-top: 50px; background:blue; height:50px;B/div !-- 实际间距 50px不是 305080px -- !-- ✅ 用父容器包裹其中一个并触发BFC -- div div stylemargin-bottom:30px; background:red; height:50px;A/div /div div stylemargin-top:50px; background:blue; height:50px;B/div !-- 或者给div加 overflow:hidden 触发BFC阻止合并 -- 代码演示两栏自适应布局经典!-- 左侧固定宽度右侧自适应BFC不与浮动重叠 -- div styleborder:1px solid #ccc; overflow:hidden; div stylefloat:left; width:200px; background:red; height:300px;左侧固定/div !-- 右侧触发BFC不会与左侧浮动重叠 -- div styleoverflow:hidden; background:blue; height:300px; 右侧自适应内容区域BFC /div /div 面试官追问Qdisplay: flow-root和overflow: hidden触发BFC有什么区别Adisplay: flow-root是专门用来触发BFC的不会产生任何副作用overflow:hidden会裁剪溢出的内容。兼容性上flow-root需Chrome 58、Firefox 53现代项目大胆用。三、Flex布局flex: 1究竟代表什么 标准答案flex是flex-grow、flex-shrink、flex-basis三个属性的缩写。flex-grow剩余空间的分配比例默认0不放大。flex-shrink空间不足时的收缩比例默认1允许缩小。flex-basis在分配空间之前的初始主轴尺寸默认auto即元素自身宽高。flex: 1等价于flex-grow: 1; flex-shrink: 1; flex-basis: 0%。核心理解flex:1表示元素在主轴方向上平分剩余空间把flex-basis设为0所有元素从同一起跑线开始瓜分。 Flex核心属性速查属性作用可选值flex-direction主轴方向row默认/column/row-reversejustify-content主轴对齐flex-start/center/space-between/space-around/space-evenlyalign-items交叉轴对齐单行stretch默认/center/flex-start/flex-endalign-content交叉轴对齐多行flex-start/center/space-betweenflex-wrap是否换行nowrap默认/wrap/wrap-reverse 代码演示经典导航栏style .nav { display: flex; justify-content: space-between; /* 两端对齐 */ align-items: center; /* 垂直居中 */ background: #1a1a2e; padding: 0 20px; height: 60px; } .nav-links { display: flex; gap: 20px; /* 子项间距替代margin */ } .nav-links a { color: white; text-decoration: none; } .nav-user { display: flex; align-items: center; gap: 10px; color: white; } /* 圣杯布局中间自适应 */ .container { display: flex; height: 500px; } .left { width: 200px; background: red; } .center { flex: 1; background: blue; } /* ✅ 占满剩余空间 */ .right { width: 150px; background: green; } /style div classnav div classnav-links a href#首页/a a href#产品/a a href#关于/a /div div classnav-user span 张三/span button退出/button /div /div 面试官追问Qflex: 0 0 auto和flex: auto有什么区别Aflex: 0 0 auto 不放大、不缩小、保持原始尺寸固定宽度。flex: autoflex: 1 1 auto放大且缩小初始尺寸为自身大小会尽量占满但不会压缩内容。flex: noneflex: 0 0 auto完全固定。Qalign-items和align-content的区别Aalign-items控制单行内每个元素在交叉轴上的对齐方式align-content控制多行换行后整个行组在交叉轴上的对齐方式。如果flex-wrap: nowrap单行align-content无效。四、Grid布局与Flex的本质区别是什么 标准答案Flex一维布局。控制主轴行或列上的元素排列适合导航栏、列表、组件内对齐。Grid二维布局。同时控制行和列适合复杂页面整体结构如后台面板、图片墙、瀑布流。 代码演示经典网格.grid-container { display: grid; /* 三列第一列200px第二列1fr剩余空间第三列100px */ grid-template-columns: 200px 1fr 100px; /* 两行第一行100px第二行auto根据内容撑开 */ grid-template-rows: 100px auto; /* 行/列间距 */ gap: 16px 24px; /* 行间距16px列间距24px */ /* 区域命名高阶 */ grid-template-areas: header header header sidebar main ads footer footer footer; min-height: 100vh; } .header { grid-area: header; background: #f1f1f1; } .sidebar { grid-area: sidebar; background: #ddd; } .main { grid-area: main; background: #eee; } .ads { grid-area: ads; background: #ccc; } .footer { grid-area: footer; background: #bbb; } /* 跨列/跨行 */ .grid-item { grid-column: 1 / 3; /* 从第1条网格线到第3条网格线占2列 */ grid-row: 1 / 2; /* 占1行 */ }!-- 等宽响应式卡片经典场景 -- style .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* ↑ 每列最少250px不足则换行自动填充 */ gap: 20px; } .card { background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } /style div classcard-grid div classcard卡片1/div div classcard卡片2/div div classcard卡片3/div !-- 自动换行自适应 -- /div 面试官追问Qgrid-template-columns: repeat(auto-fill, minmax(250px, 1fr))怎么理解Aauto-fill让容器尽可能多地填充列minmax(250px, 1fr)每列最小250px最大占满剩余空间。这是实现纯CSS响应式卡片布局的最佳实践无需媒体查询。五、层叠上下文为什么z-index死活不生效 标准答案z-index只在同一个层叠上下文Stacking Context中比较才有意义。如果元素不在同一个层叠上下文中z-index再高也没用。触发层叠上下文的条件高频触发方式示例根元素html根层叠上下文position: relative/absolute/fixedz-index不为autoposition: relative; z-index: 1opacity小于 1opacity: 0.9transform / filter / perspective不为nonetransform: scale(1)will-change值为上述任意属性will-change: transformdisplay: flex/gridz-index不为auto子元素产生新上下文层叠顺序从底到顶背景和边框background/border负z-indexz-index: -1block块级盒子正常流float浮动盒子inline/inline-block内联盒子定位元素positionz-index: auto正z-indexz-index: 1及以上 代码演示常见Bug!-- ❌ z-index 不生效场景 -- style .parent { position: relative; z-index: 1; /* ⚠️ parent触发了层叠上下文 */ } .child-1 { position: absolute; z-index: 999; /* 在parent内部只跟parent内的兄弟比较 */ background: red; } .sibling { position: relative; z-index: 2; /* 与parent同层级z-index:2 parent的1 */ background: blue; } /* child-1 永远无法盖住 sibling因为child-1在parent内部 */ /style!-- ✅ 解决方案提升parent的z-index或调整结构 -- style .parent { position: relative; z-index: 3; /* 大于sibling的2即可 */ } .child-1 { position: absolute; z-index: 999; } .sibling { position: relative; z-index: 2; } /style 面试官追问Qopacity: 0.99和opacity: 1哪个触发层叠上下文Aopacity: 0.99小于1触发opacity: 1不触发。这是一个常见面试坑。六、CSS选择器权重计算一道题摸清你的底子 标准答案权重从高到低排列!important 最强但严禁滥用等级权重值选择器示例!important∞最高color: red !important;内联样式1000stylecolor: red;ID选择器0100#header类/伪类/属性0010.nav、:hover、[typetext]标签/伪元素0001div、::before通配符/组合器0000*、、、~计算规则把三个数字组合a-b-c从左到右比较不进位即11个标签选择器0-0-11权重仍小于1个类选择器0-1-0。 代码演示/* 计算以下选择器权重 */ #nav .list a:hover /* [1 ID] [1 类] [1 伪类] [1 标签] 0-2-1 → 权重 21 */ body .container div /* [1 标签] [1 类] [1 标签] 0-1-2 → 权重 12 */ #header .menu li a /* [1 ID] [1 类] [2 标签] 1-1-2 → 权重 112 */ .style /* [1 类] 0-1-0 → 权重 10 */!-- 面试经典题型 -- style #id .class { color: red; } /* 权重: 1-1-0 110 */ .class .child { color: blue; } /* 权重: 0-2-0 20 */ div .child { color: green; } /* 权重: 0-1-1 11 */ /* red 胜出 ✅ */ /style div idid div classclass span classchild这是什么颜色/span !-- 红色 -- /div /div/* ❌ 史上最蠢面试坑!important 泛滥 */ .button { color: blue !important; } .btn-primary { color: red !important; /* 后来者居上红色 */ } /* 正确做法提升特异性不用 !important */ 面试官追问Q11个标签选择器div div div...和 1个类选择器.cls谁权重高A.cls权重0-1-0 10高于 11个标签0-0-11 11因为权重是三位独立比较不进位。这也是为什么(0-1-0) (0-0-11)。Q!important能互相覆盖吗A能。如果有多个!important则按选择器权重再次比较内联ID类标签如果再相同则按后声明覆盖。七、伪类 vs 伪元素:和::你真的分清楚了吗 标准答案伪类Pseudo-classes单冒号:。表示元素的状态如:hover、:focus、:nth-child不创建新元素。伪元素Pseudo-elements双冒号::CSS3规范CSS2用单冒号兼容。表示元素的特定部分如::before、::after、::first-line创建了一个虚拟DOM节点在文档树中不存在。 代码演示/* ✅ 伪类状态变化 */ a:hover { color: red; } input:focus { border-color: blue; } li:nth-child(2n) { background: #f5f5f5; } /* 偶数行 */ /* ✅ 伪元素生成内容必须有 content */ .clearfix::after { content: ; display: block; clear: both; } .quote::before { content: 「; color: #999; font-size: 24px; } .quote::after { content: 」; color: #999; font-size: 24px; } /* 首字母下沉 */ p::first-letter { font-size: 300%; float: left; color: #d32f2f; } 面试官追问Q::before和::after创建的伪元素可以点击吗A默认情况下不可以因为伪元素是渲染层而非真实DOM不响应鼠标事件。但可以设置pointer-events: auto让其响应或者将事件绑定到父元素上。Q为什么清除浮动用::after而不是::beforeA因为浮动元素在文档流中脱离了常规流::after在元素内容的末尾生成一个块级空元素并clear: both相当于在最后加了一个撑开父元素的“清洁工”。::before在开头生成无法清除后面浮动元素的影响。八、移动端适配rem、vw、flexible 方案全解析 标准答案移动端适配的核心是让页面在不同屏幕尺寸下都能正常显示。方案原理优缺点rem相对根元素html字体大小需JS动态计算根字体兼容性好vw/vh相对视口宽度/高度1vw1%视口宽纯CSS无需JS但单位换算麻烦百分比相对父元素只能解决宽高无法处理字体flexible手淘方案rem viewport缩放完美还原设计稿需引入阿里lib-flexible已过时容器查询新相对父容器尺寸2023新特性兼容性逐步完善 代码演示rem 适配方案主流// 方案根据设计稿宽度动态设置根字体大小设计稿以750px为例 (function flexible() { const baseWidth 750; // 设计稿宽度 const baseFontSize 100; // 1rem 100px方便换算 function setRem() { const clientWidth document.documentElement.clientWidth || window.innerWidth; // 限制最大宽度防止PC端过大 const width Math.min(clientWidth, 750); const fontSize (width / baseWidth) * baseFontSize; document.documentElement.style.fontSize fontSize px; } setRem(); window.addEventListener(resize, setRem); window.addEventListener(pageshow, (e) { if (e.persisted) setRem(); }); })();/* CSS中使用rem */ /* 设计稿中一个按钮宽200px高80px字体28px */ .btn { width: 2rem; /* 200/100 2rem */ height: 0.8rem; /* 80/100 0.8rem */ font-size: 0.28rem; /* 28/100 0.28rem */ border-radius: 0.08rem; }/* ✅ 纯CSS vw方案无需JS强烈推荐 */ html { font-size: calc(100vw / 7.5); /* 设计稿750px下1rem 100vw/7.5 100px */ /* 实际屏幕375px下1rem 50px */ } /* 如果设计稿是375px则用 calc(100vw / 3.75) *//* ✅ 现代方案clamp() 限制最大最小值 */ html { font-size: clamp(12px, calc(100vw / 7.5), 24px); /* 最小12px最大24px中间弹性变化 */ } 面试官追问Q1px边框在移动端变粗的问题怎么解决A使用transform: scale(0.5)缩放或使用border-image。推荐::aftertransform方式css复制下载.border-1px::after { content: ; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background: #ccc; transform: scaleY(0.5); transform-origin: 0 0; }九、CSS动画性能优化为什么动画总是掉帧 标准答案浏览器渲染流水线JS Style Layout Paint Composite。触发Layout回流改变宽高、位置、字体等 →代价最高16ms内完不成就掉帧。触发Paint重绘改变颜色、背景、阴影等 →代价中等。触发Composite合成改变transform、opacity→代价最低GPU加速不触发Layout/Paint。性能优化核心原则优先使用transformopacity做动画。 代码演示/* ❌ 性能杀手改变width/height/left/top触发回流 */ .box-bad { transition: width 0.3s, top 0.3s; } .box-bad:hover { width: 300px; top: 50px; /* 每次变化都会触发布局计算 → 掉帧卡顿 */ } /* ✅ 性能王者transform opacity走合成器 */ .box-good { transition: transform 0.3s, opacity 0.3s; will-change: transform; /* 提前告知浏览器创建独立图层 */ } .box-good:hover { transform: translateY(50px) scale(1.05); opacity: 0.8; }/* 纯CSS实现平滑呼吸灯动画 */ keyframes breathe { 0%, 100% { transform: scale(1); opacity: 0.8; } 50% { transform: scale(1.15); opacity: 1; } } .breath { animation: breathe 2s ease-in-out infinite; will-change: transform, opacity; } 面试官追问Qwill-change是不是越多越好A大错特错will-change会让浏览器为元素创建独立合成层占用GPU内存。滥用会导致内存飙升反而更卡。只在动画即将发生前设置动画结束后移除。Q如何用 Chrome DevTools 查看动画性能APerformance面板录制动画过程看FPS 曲线是否掉到60以下Layers面板查看合成层数量过多需优化。十、经典布局手写水平垂直居中的N种姿势 标准答案水平垂直居中是面试手写代码最高频题没有之一。以下给出5种方案面试时说出3种即可碾压。 方案一Flex最推荐一行搞定.parent { display: flex; justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */ width: 400px; height: 300px; background: #f0f0f0; } .child { width: 100px; height: 80px; background: #d32f2f; } 方案二Grid同样简洁.parent { display: grid; place-items: center; /* 水平和垂直同时居中 */ width: 400px; height: 300px; background: #f0f0f0; } .child { width: 100px; height: 80px; background: #1976d2; } 方案三绝对定位 Transform万能兼容.parent { position: relative; width: 400px; height: 300px; background: #f0f0f0; } .child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100px; height: 80px; background: #2e7d32; } 方案四绝对定位 margin: auto经典.parent { position: relative; width: 400px; height: 300px; background: #f0f0f0; } .child { position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto; width: 100px; height: 80px; background: #ed6c02; } 方案五table-cell兼容IE8移动端少用.parent { display: table-cell; vertical-align: middle; /* 垂直居中 */ text-align: center; /* 水平居中 */ width: 400px; height: 300px; background: #f0f0f0; } .child { display: inline-block; width: 100px; height: 80px; background: #9c27b0; } 面试官追问Q如果子元素宽高不确定由内容撑开哪种方案最合适A方案一Flex和方案三absolute transform都完美支持。方案四margin:auto需要明确宽高不适合。Q父元素宽高也不确定时怎么办A直接上 Flex 或 Gridplace-items: center无需知道任何尺寸。 总结与记忆口诀题号核心考点一句话记忆1盒模型border-box防撑大全局重置最省心2BFCoverflow/float/flex触发清除浮动防塌陷3Flexflex:1 放大缩小基点0主轴交叉轴要分清4Grid二维布局repeat(auto-fill, minmax())响应式神器5层叠上下文z-index失效看父级opacity/transform会新建6权重!important 内联 ID 类 标签不进位7伪类/伪元素:状态::虚拟content必须有8适配rem算根字体vw纯CSSclamp限制边界9动画性能优先 transform/opacitywill-change慎用10居中Flex/Grid一骑绝尘transform兜底万能面试前5分钟速记盒模型 → BFC结界 → Flex/Grid布局 → 层叠上下文 → 权重计算 → 居中方案。 下篇预告《第3章JavaScript 基础核心考点闭包原型必杀技》涵盖闭包、原型链、this指向、深浅拷贝、垃圾回收、事件循环与浏览器篇联动等10道JS硬核原题。觉得有用点赞 收藏 关注系列持续更新不迷路有任何题目想补充评论区告诉我下篇安排