定位:不仅能回答"是什么",还能讲清楚"为什么、怎么落地、踩过哪些坑"。
目录
- [1. HTML 篇](#1. HTML 篇 "#1-html-%E7%AF%87")
- [1.1 语义化(Semantic HTML)](#1.1 语义化(Semantic HTML) "#11-%E8%AF%AD%E4%B9%89%E5%8C%96semantic-html")
- [1.2 块级/行内/行内块](#1.2 块级/行内/行内块 "#12-%E5%9D%97%E7%BA%A7%E8%A1%8C%E5%86%85%E8%A1%8C%E5%86%85%E5%9D%97")
- [1.3
script的async/defer区别](#1.3 script 的 async / defer 区别 "#13-script-%E7%9A%84-async--defer-%E5%8C%BA%E5%88%AB") - [1.4
meta viewport](#1.4 meta viewport "#14-meta-viewport") - [1.5
img的alt、懒加载与图片性能](#1.5 img 的 alt、懒加载与图片性能 "#15-img-%E7%9A%84-alt%E6%87%92%E5%8A%A0%E8%BD%BD%E4%B8%8E%E5%9B%BE%E7%89%87%E6%80%A7%E8%83%BD") - [1.6 表单与可访问性(A11y)](#1.6 表单与可访问性(A11y) "#16-%E8%A1%A8%E5%8D%95%E4%B8%8E%E5%8F%AF%E8%AE%BF%E9%97%AE%E6%80%A7a11y")
- [2. CSS 基础与原理篇](#2. CSS 基础与原理篇 "#2-css-%E5%9F%BA%E7%A1%80%E4%B8%8E%E5%8E%9F%E7%90%86%E7%AF%87")
- [2.1 选择器优先级(Specificity)](#2.1 选择器优先级(Specificity) "#21-%E9%80%89%E6%8B%A9%E5%99%A8%E4%BC%98%E5%85%88%E7%BA%A7specificity")
- [2.2 盒模型与
box-sizing](#2.2 盒模型与 box-sizing "#22-%E7%9B%92%E6%A8%A1%E5%9E%8B%E4%B8%8E-box-sizing") - [2.3 BFC(块级格式化上下文)](#2.3 BFC(块级格式化上下文) "#23-bfc%E5%9D%97%E7%BA%A7%E6%A0%BC%E5%BC%8F%E5%8C%96%E4%B8%8A%E4%B8%8B%E6%96%87")
- [2.4 浮动与清除浮动](#2.4 浮动与清除浮动 "#24-%E6%B5%AE%E5%8A%A8%E4%B8%8E%E6%B8%85%E9%99%A4%E6%B5%AE%E5%8A%A8")
- [2.5
position:relative/absolute/fixed/sticky](#2.5 position:relative/absolute/fixed/sticky "#25-positionrelativeabsolutefixedsticky") - [2.6 Flex:
flex: 1、压缩、溢出与min-width: 0](#2.6 Flex:flex: 1、压缩、溢出与 min-width: 0 "#26-flexflex-1%E5%8E%8B%E7%BC%A9%E6%BA%A2%E5%87%BA%E4%B8%8E-min-width-0") - [2.7 Grid:二维布局加分项](#2.7 Grid:二维布局加分项 "#27-grid%E4%BA%8C%E7%BB%B4%E5%B8%83%E5%B1%80%E5%8A%A0%E5%88%86%E9%A1%B9")
- [2.8 常见居中方案](#2.8 常见居中方案 "#28-%E5%B8%B8%E8%A7%81%E5%B1%85%E4%B8%AD%E6%96%B9%E6%A1%88")
- [2.9
z-index与层叠上下文(Stacking Context)](#2.9 z-index 与层叠上下文(Stacking Context) "#29-z-index-%E4%B8%8E%E5%B1%82%E5%8F%A0%E4%B8%8A%E4%B8%8B%E6%96%87stacking-context") - [2.10 继承、层叠、计算值(CSS 三板斧)](#2.10 继承、层叠、计算值(CSS 三板斧) "#210-%E7%BB%A7%E6%89%BF%E5%B1%82%E5%8F%A0%E8%AE%A1%E7%AE%97%E5%80%BCcss-%E4%B8%89%E6%9D%BF%E6%96%A7")
- [2.11 响应式单位与媒体查询](#2.11 响应式单位与媒体查询 "#211-%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8D%95%E4%BD%8D%E4%B8%8E%E5%AA%92%E4%BD%93%E6%9F%A5%E8%AF%A2")
- [2.12
transitionvsanimation与性能要点](#2.12 transition vs animation 与性能要点 "#212-transition-vs-animation-%E4%B8%8E%E6%80%A7%E8%83%BD%E8%A6%81%E7%82%B9")
- [3. 工程化与落地(公司最常用)](#3. 工程化与落地(公司最常用) "#3-%E5%B7%A5%E7%A8%8B%E5%8C%96%E4%B8%8E%E8%90%BD%E5%9C%B0%E5%85%AC%E5%8F%B8%E6%9C%80%E5%B8%B8%E7%94%A8")
- [3.1 移动端适配选型:
rem/vw/rpx/scale](#3.1 移动端适配选型:rem / vw / rpx / scale "#31-%E7%A7%BB%E5%8A%A8%E7%AB%AF%E9%80%82%E9%85%8D%E9%80%89%E5%9E%8Brem--vw--rpx--scale") - [3.2 H5(Vue/React)方案:PostCSS 自动转换(推荐写
px)](#3.2 H5(Vue/React)方案:PostCSS 自动转换(推荐写 px) "#32-h5vuereact-%E6%96%B9%E6%A1%88postcss-%E8%87%AA%E5%8A%A8%E8%BD%AC%E6%8D%A2%E6%8E%A8%E8%8D%90%E5%86%99-px") - [3.3 uni-app / 小程序:
rpx与安全区](#3.3 uni-app / 小程序:rpx 与安全区 "#33-uni-app--%E5%B0%8F%E7%A8%8B%E5%BA%8Frpx-%E4%B8%8E%E5%AE%89%E5%85%A8%E5%8C%BA") - [3.4 PC 响应式(B 端/官网):版心 + 断点 + Flex/Grid](#3.4 PC 响应式(B 端/官网):版心 + 断点 + Flex/Grid "#34-pc-%E5%93%8D%E5%BA%94%E5%BC%8Fb-%E7%AB%AF%E5%AE%98%E7%BD%91%E7%89%88%E5%BF%83--%E6%96%AD%E7%82%B9--flexgrid")
- [3.5 大屏可视化:容器等比缩放(
transform: scale)](#3.5 大屏可视化:容器等比缩放(transform: scale) "#35-%E5%A4%A7%E5%B1%8F%E5%8F%AF%E8%A7%86%E5%8C%96%E5%AE%B9%E5%99%A8%E7%AD%89%E6%AF%94%E7%BC%A9%E6%94%BEtransform-scale") - [3.6 移动端 1px 问题(Retina)](#3.6 移动端 1px 问题(Retina) "#36-%E7%A7%BB%E5%8A%A8%E7%AB%AF-1px-%E9%97%AE%E9%A2%98retina")
- [3.7 隐藏元素:
display:none/visibility:hidden/opacity:0](#3.7 隐藏元素:display:none / visibility:hidden / opacity:0 "#37-%E9%9A%90%E8%97%8F%E5%85%83%E7%B4%A0displaynone--visibilityhidden--opacity0") - [3.8 响应式布局 SOP(步骤 + 不同场景方案)](#3.8 响应式布局 SOP(步骤 + 不同场景方案) "#38-%E5%93%8D%E5%BA%94%E5%BC%8F%E5%B8%83%E5%B1%80-sop%E6%AD%A5%E9%AA%A4--%E4%B8%8D%E5%90%8C%E5%9C%BA%E6%99%AF%E6%96%B9%E6%A1%88")
- [3.1 移动端适配选型:
- [4. 高频场景题(面试直接用)](#4. 高频场景题(面试直接用) "#4-%E9%AB%98%E9%A2%91%E5%9C%BA%E6%99%AF%E9%A2%98%E9%9D%A2%E8%AF%95%E7%9B%B4%E6%8E%A5%E7%94%A8")
1. HTML 篇
1.1 语义化(Semantic HTML)
- 是什么
- 使用符合内容含义的标签(
header/nav/main/article/section/aside/footer、h1-h6、p、ul/li、figure/figcaption等)描述结构,而不是全用div/span。
- 使用符合内容含义的标签(
- 为什么(收益)
- SEO:搜索引擎更容易理解页面结构与权重。
- 可访问性(A11y):读屏软件更好解析;键盘导航更顺。
- 可维护性:结构清晰,样式/脚本更容易定位。
- 默认行为 :例如
button天然可聚焦、可键盘触发。
- 常见追问
sectionvsdiv:section表示主题分区(通常应该有标题),div是无语义容器。em/strongvsi/b:前者强调语义,后者偏展示。
- 常见坑
div冒充按钮但缺少role="button"、tabindex="0"、键盘事件。
1.2 块级/行内/行内块
- 块级(block) :独占一行;可设置
width/height/margin/padding。 - 行内(inline) :不独占一行;
width/height通常不生效;margin-top/bottom通常不生效。 - 行内块(inline-block) :不独占一行,但可设置
width/height。 - 追问:
inline-block空白间隙怎么解决- 删除标签间空白/换行;父元素
font-size:0;或者直接改用flex/grid。
- 删除标签间空白/换行;父元素
1.3 script 的 async / defer 区别
- 无
async/defer:下载+执行会阻塞 HTML 解析。 defer:并行下载;等 DOM 解析完成后按顺序执行;适合业务脚本。async:并行下载;下载完立刻执行(可能打断解析);顺序不保证;适合统计/埋点。- 追问
type="module":模块脚本默认行为更接近defer(并行下载,解析后执行)。
1.4 meta viewport
常用写法:
html
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
- 作用:控制移动端布局视口宽度与缩放,避免页面被缩小。
- 工程提醒
- 不建议为了"防缩放"随意加
user-scalable=no(可访问性风险)。
- 不建议为了"防缩放"随意加
1.5 img 的 alt、懒加载与图片性能
alt:图片加载失败的替代文本;对 SEO/读屏重要。- 懒加载
- 原生:
loading="lazy" - 更强控制:IntersectionObserver
- 原生:
- 响应式图片 :
srcset/sizes(按容器加载不同分辨率)。
1.6 表单与可访问性(A11y)
label与input绑定label for="id"+input id="id",或label包裹input。
button默认类型form内默认type="submit",非提交按钮要显式写type="button"。
2. CSS 基础与原理篇
2.1 选择器优先级(Specificity)
- 常见优先级从高到低
!important> 行内样式 >#id>.class/[attr]/:pseudo-class>tag/::pseudo-element> 通配*/继承
- 同级规则
- 优先级相同:后写覆盖先写。
- 坑
:not()本身不加权重,但括号里的选择器会增加权重。
2.2 盒模型与 box-sizing
- 标准盒模型 :
width/height只包含content。 - 工程推荐 :全局
box-sizing: border-box;,布局更符合"视觉宽度"。
2.3 BFC(块级格式化上下文)
- 人话解释:BFC 是一个独立的渲染区域/布局"结界",内部布局不会在某些方面影响外部。
- 常见触发方式
overflow非visibledisplay: flow-root(推荐)/flex/grid/inline-blockposition: absolute/fixed
- 经典用途
- 清除浮动造成的父元素高度塌陷
- 避免 margin 合并
- 两栏布局:让右侧自适应不被浮动覆盖
2.4 浮动与清除浮动
- 塌陷原因:浮动元素脱离普通流,不撑开父元素高度。
- 清除方式
- 伪元素 clearfix
- 触发 BFC:
overflow: hidden或display: flow-root
2.5 position:relative/absolute/fixed/sticky
relative:不脱离文档流;偏移相对自身原位置。absolute:脱离文档流;相对最近定位祖先。fixed:相对视口;注意某些场景会受祖先transform影响。sticky:滚动到阈值后吸顶;必须指定top/left/...。
2.6 Flex:flex: 1、压缩、溢出与 min-width: 0
flex: 1常见解释 :flex: 1 1 0%,用于均分剩余空间。- 高频坑:长文本把布局撑爆
- Flex 子项默认
min-width: auto,内容过长会撑开。 - 工程解法 :在需要截断/可滚动的子项上加
min-width: 0。
- Flex 子项默认
2.7 Grid:二维布局加分项
- 更适合二维栅格布局;常用
repeat()、minmax()、fr、gap。
2.8 常见居中方案
- Flex:
css
.parent { display: flex; justify-content: center; align-items: center; }
- Grid:
css
.parent { display: grid; place-items: center; }
- 绝对定位 + transform:
css
.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
2.9 z-index 与层叠上下文(Stacking Context)
- 结论 :
z-index只在同一层叠上下文里比较。 - 常见创建层叠上下文
position非 static +z-index非 autotransform非 none、opacity < 1等
2.10 继承、层叠、计算值(CSS 三板斧)
- 继承 :如
color、font-*常继承;margin/padding/border不继承。 - 层叠:来源 + 权重 + 顺序共同决定。
2.11 响应式单位与媒体查询
- 单位:
%/rem/em/vw/vh各有场景。 - 断点:
@media (max-width: 768px) { ... }等。
2.12 transition vs animation 与性能要点
transition:状态变化触发。animation:@keyframes更复杂时间线。- 性能建议 :优先动画
transform/opacity,避免高频动画top/left/width/height。
3. 工程化与落地(公司最常用)
3.1 移动端适配选型:rem / vw / rpx / scale
- 核心结论
- 你不应该让开发"手写 rem/vw",而是:代码里写
px,构建阶段自动转换。 - 场景选型:
- 新 H5 项目 :更偏向
vw(PostCSS 转换) - 老项目/兼容性要求极高 :
rem(动态 root + PostCSS 转换) - uni-app/小程序 :
rpx - 大屏可视化 :容器等比缩放
transform: scale()
- 新 H5 项目 :更偏向
- 你不应该让开发"手写 rem/vw",而是:代码里写
3.2 H5(Vue/React)方案:PostCSS 自动转换(推荐写 px)
方案 A:vw(推荐)+ postcss-px-to-viewport
- 典型配置(
postcss.config.js)
js
module.exports = {
plugins: {
'postcss-px-to-viewport': {
viewportWidth: 375,
unitPrecision: 5,
viewportUnit: 'vw',
selectorBlackList: ['.ignore', '.hairlines'],
minPixelValue: 1,
mediaQuery: false,
exclude: [/node_modules/],
},
},
}
- 公司里最常见的坑
- UI 库(如 Vant)设计基准可能与业务设计稿不同(375 vs 750),不做隔离会导致 UI 库整体缩小/放大。
- 常见处理:
excludeUI 库,或者使用支持动态viewportWidth的插件版本按路径区分。
方案 B:rem(经典)+ amfe-flexible + postcss-pxtorem
- 核心点 :动态设置
html的font-size,并在构建阶段将px转rem。 - 典型配置要点(按 UI 库/业务代码区分 rootValue)
js
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue({ file }) {
return file.indexOf('vant') !== -1 ? 37.5 : 75
},
propList: ['*'],
selectorBlackList: ['.norem'],
},
},
}
3.3 uni-app / 小程序:rpx 与安全区
- 单位 :优先
rpx,常配合 750 设计稿心智最一致。 - 布局 :以
flex为主,少用硬编码高度。 - 安全区(底部 Home 指示条)
css
.page {
padding-bottom: env(safe-area-inset-bottom);
}
3.4 PC 响应式(B 端/官网):版心 + 断点 + Flex/Grid
- 不要在 PC 全站做 rem/vw 等比缩放(屏幕跨度太大,体验不可控)。
- 常见落地组合
- 版心:
max-width: 1200px/1440px; margin: 0 auto; - 布局:Flex/Grid
- 断点:对关键布局重排
- 版心:
css
@media screen and (max-width: 992px) {
.sidebar { display: none; }
}
3.5 大屏可视化:容器等比缩放(transform: scale)
- 适用:强视觉还原、固定画布(如 1920x1080)。
- 核心代码(监听 resize 计算 scale)
js
function fitScreen() {
const designW = 1920
const designH = 1080
const scaleX = window.innerWidth / designW
const scaleY = window.innerHeight / designH
const scale = Math.min(scaleX, scaleY)
const el = document.getElementById('screen')
el.style.transform = `scale(${scale})`
el.style.transformOrigin = 'left top'
}
fitScreen()
window.addEventListener('resize', fitScreen)
- 注意 :如果涉及点击/拖拽坐标,需要按
scale反算。
3.6 移动端 1px 问题(Retina)
- 现象 :高 DPR 屏上
1px视觉上变粗。 - 常见落地:伪元素 + 缩放
css
.border-1px {
position: relative;
}
.border-1px::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background: #ccc;
transform: scaleY(0.5);
transform-origin: 0 0;
}
3.7 隐藏元素:display:none / visibility:hidden / opacity:0
display: none:不占位;触发 reflow;不可点击。visibility: hidden:占位;触发 repaint;不可点击。opacity: 0:占位;通常 repaint;仍可点击(除非配合pointer-events: none)。
3.8 响应式布局 SOP(步骤 + 不同场景方案)
你可以把这一节当成:面试回答模板 + 项目落地 SOP(标准操作流程)。
3.8.1 先给结论:响应式不是一个技术点,是"策略组合"
- A. 等比缩放 :页面整体按比例放大缩小
- 常见:大屏看板、强还原活动页
- B. 响应式重排 :不同宽度下布局结构变化
- 常见:PC 官网 / B 端
- C. 流式自适应 :布局不大改,但局部宽高、字体、间距自适应
- 常见:移动端业务 H5
3.8.2 落地步骤(SOP:从需求到上线)
-
Step 1:明确输入条件(必须问清)
- 设计基准:设计稿宽度(
375/750/1200/1920x1080) - 目标设备:移动端 H5(WebView/浏览器)/ PC / 小程序(含 uni-app)/ 大屏
- 是否允许重排:是否能接受某些屏幕变成单列、某些模块折行
- 兼容性要求:最低 iOS/Android/浏览器版本
- 关键体验约束:固定底栏/弹窗、长列表、图表/Canvas 等
- 设计基准:设计稿宽度(
-
Step 2:先选布局骨架(优先级:Grid > Flex > 传统)
- 二维区域布局/栅格:优先
grid - 一维布局(横排/竖排):优先
flex - 避免用
float作为布局系统(除非老项目维护)
- 二维区域布局/栅格:优先
-
Step 3:确定"尺寸体系"(决定 rem/vw/px/clamp 的组合)
- 移动端 H5:推荐"写
px+ PostCSS 自动转换为vw/rem" - PC:以
px为主 + 版心 + 断点(必要时少量%/fr) - 大屏:内部按设计稿
px,外层容器transform: scale()
- 移动端 H5:推荐"写
-
Step 4:断点策略(不是越多越好)
- 移动端:通常少断点,更多靠流式布局;必要时单独考虑 Pad(
>=768) - PC:常用 3-5 个断点(如
1200/992/768/576)就够用 - 大屏:优先等比缩放,不建议靠大量断点救火
- 移动端:通常少断点,更多靠流式布局;必要时单独考虑 Pad(
-
Step 5:上线前兜底(公司里最容易翻车的地方)
- 文本溢出:单行/多行省略号,Flex 子项记得
min-width: 0 - 图片:
max-width: 100%、必要时object-fit: cover - 安全区:
env(safe-area-inset-bottom) - 性能:动画只动
transform/opacity;长列表考虑虚拟列表
- 文本溢出:单行/多行省略号,Flex 子项记得
3.8.3 不同场景的"对口方案"(可直接落地)
-
移动端 H5(业务页/内嵌页)
- 目标:流式自适应为主,不追求像素级完全一致
- 推荐:
flex/grid+ PostCSS(px -> vw)+clamp()做上下限 + 安全区/1px/弹窗兜底
-
PC 官网 / B 端后台
- 目标:断点重排 + 版心控制阅读宽度
- 推荐:Grid 做栅格区域 + Flex 做组件内部;
max-width版心;关键断点重排(侧边栏折叠等)
-
uni-app / 小程序
- 目标:利用平台原生适配能力
- 推荐:
rpx + flex;优先使用生态组件库,减少引入写死px的第三方 H5 样式
-
大屏可视化(DataV/看板)
- 目标:严格保真,不换行、不乱跑位
- 推荐:内部按设计稿
px写,外层transform: scale(),交互坐标按 scale 反算
3.8.4 面试一句话收尾(背下来)
"响应式我会先明确目标是等比缩放还是断点重排。移动端业务页用 Flex/Grid + PostCSS 的 vw(必要时 clamp)保证流式自适应;PC 端用版心 + 断点做结构重排;小程序用 rpx;大屏用容器 scale 保真。最后统一补齐文本溢出、安全区、1px、弹窗与性能兜底。"
4. 高频场景题(面试直接用)
4.1 三栏布局:两侧固定,中间自适应
-
可背诵答案(30 秒版)
- "我会优先用 flex:左右两栏固定宽度,中间一栏
flex: 1占满剩余空间。中间为了防止长文本把布局撑爆,会显式加min-width: 0,再配合overflow: hidden; text-overflow: ellipsis;或内部滚动。"
- "我会优先用 flex:左右两栏固定宽度,中间一栏
-
推荐实现(Flex)
html
<div class="layout">
<aside class="left">left</aside>
<main class="mid">middle middle middle ...</main>
<aside class="right">right</aside>
</div>
css
.layout {
display: flex;
}
.left,
.right {
width: 200px;
flex: 0 0 200px;
}
.mid {
flex: 1;
min-width: 0; /* 关键:允许在 flex 容器内缩小,避免长内容撑爆 */
}
- 高频追问
- 为什么要
min-width: 0:Flex 子项默认min-width: auto,内容过长会让它不愿意缩小。 - 不用 flex 你还有方案吗:Grid(更适合二维),以及老方案(float + BFC/定位)但现代不推荐。
- 为什么要
4.2 弹窗 z-index: 9999 仍被遮住
-
可背诵答案(30 秒版)
- "
z-index只在同一个层叠上下文里比较。如果弹窗的祖先元素创建了层叠上下文(比如transform、opacity<1、position+z-index),那弹窗的z-index再大也只能在这个上下文里排队,盖不住别的上下文。工程上我通常把弹窗挂到body(React Portal / Vue Teleport),从根层级统一管理。"
- "
-
如何快速定位(排查路径)
- 检查弹窗及其祖先是否存在:
transform: translateZ(0)/transform: ...opacity < 1position非 static 且z-index非 autofilter、will-change等
- 检查弹窗及其祖先是否存在:
-
工程落地建议
- 组件库/业务统一方案 :全站只有一个
#modal-root,所有弹窗都挂载到这里。 - 管理策略:用"弹窗栈"管理层级(比如每开一个弹窗,z-index 递增)。
- 组件库/业务统一方案 :全站只有一个
4.3 position: sticky 不生效
-
可背诵答案(30 秒版)
- "
sticky需要一个滚动容器,并且必须指定top/left/right/bottom其中一个阈值。常见失效原因是祖先设置了overflow: hidden/auto/scroll改变了滚动容器,或者容器高度不足导致根本触发不了吸附。"
- "
-
常见失效清单(面试官最爱挖坑)
- 没写
top(最常见) - 父级/祖先
overflow非visible(尤其overflow: hidden) - 滚动发生在另一个容器(不是你以为的 window)
- sticky 元素所在容器高度不够(滚动距离不足)
- 没写
-
参考代码
css
.sticky {
position: sticky;
top: 0;
z-index: 10;
}
4.4 回流(reflow)/重绘(repaint)与优化
-
可背诵答案(60 秒版)
- "回流是布局计算阶段(尺寸/位置变化导致 Layout 重新算),重绘是像素绘制阶段(颜色/阴影变化触发 Paint)。回流一定会引起重绘,重绘不一定回流。优化上:尽量减少触发布局的属性变化,把动画放到
transform/opacity,批量读写 DOM,避免强制同步布局(比如频繁读offsetHeight)。长列表用虚拟列表,图片用懒加载。"
- "回流是布局计算阶段(尺寸/位置变化导致 Layout 重新算),重绘是像素绘制阶段(颜色/阴影变化触发 Paint)。回流一定会引起重绘,重绘不一定回流。优化上:尽量减少触发布局的属性变化,把动画放到
-
常见触发回流的操作(会被追问)
- 改几何属性:
width/height/padding/margin/top/left/border(部分) - 插入/删除 DOM 节点,改变字体大小
- 读取布局信息会触发"强制同步布局":
offsetHeight/getBoundingClientRect(在你前面有写操作时)
- 改几何属性:
-
工程级优化清单
- 动画:只动
transform/opacity(必要时will-change,但别滥用) - DOM:合并操作(改 class 而不是逐条改 style),读写分离
- 长列表:虚拟列表/分页渲染
- 新特性加分:
content-visibility: auto;(对长页面有帮助)
- 动画:只动
4.5 两栏布局:左固定右自适应(最常用)
- Flex 推荐写法
css
.wrap { display: flex; }
.left { width: 240px; flex: 0 0 240px; }
.right { flex: 1; min-width: 0; }
- 追问点
- 右侧内容长导致撑开:同样用
min-width: 0。
- 右侧内容长导致撑开:同样用
4.6 文本溢出省略号:单行/多行
- 单行省略号
css
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
- 多行省略号(常问,含兼容性)
css
.clamp {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
- 追问点
- 多行省略号是非标准方案(WebKit 私有),复杂场景可能要用 JS 计算。
4.7 图片底部为什么会有"缝隙"?怎么解决
- 原因(面试点)
img默认是 inline 元素,会按基线对齐,基线下方留空给"下行字母"(descender)空间。
- 解决方案
img { display: block; }- 或者父元素
line-height: 0(不推荐,影响可读性) - 或
vertical-align: middle/bottom;
4.8 移动端底部安全区(iPhone 刘海屏/小白条)
- CSS 落地
css
.footer {
padding-bottom: env(safe-area-inset-bottom);
}
- 追问点
- 除了 padding,还要做"固定底栏 + 占位",避免内容被遮挡。
4.9 滚动穿透(弹窗打开后背景还能滚)怎么处理
- 典型场景
- 移动端弹窗(mask)出现后,背景页面仍能滚动。
- 工程思路
- Web:打开弹窗时锁住 body 滚动(记录滚动位置,关闭后恢复)。
- iOS 上对
position: fixed/滚动容器要特别小心。
4.10 清除浮动有哪些方式?为什么现在更推荐 Flex/Grid
-
可背诵答案(60 秒版)
- "清除浮动本质是解决
float脱离普通文档流导致的父元素高度塌陷。常见方案有三类:- 经典
clearfix伪元素清除; - 让父容器触发 BFC(比如
overflow: hidden); - 更现代语义化的
display: flow-root。 但在新业务里我更倾向用 Flex/Grid 直接做布局,原因是 float 本身是为文字环绕设计的,不适合作为布局系统;Flex/Grid 更语义、更稳定、响应式更好,后期维护也不会出现各种清除浮动/塌陷的历史问题。"
- 经典
- "清除浮动本质是解决
-
先把原理说清楚:为什么会"高度塌陷"
- 浮动元素会脱离普通流,父元素计算高度时只看普通流子元素,导致:
- 父容器高度变成 0(或只等于非浮动子元素高度)
- 后续兄弟元素上移/覆盖
- 浮动元素会脱离普通流,父元素计算高度时只看普通流子元素,导致:
-
方案 A:
clearfix(经典方案,兼容性强)
css
.clearfix::after {
content: "";
display: block;
clear: both;
}
-
优点
- 兼容性极好;不依赖布局上下文;老项目常见。
-
缺点
- 属于"历史包袱式"的补丁写法:你得记得给父容器加类名;结构不够语义化。
-
追问点
- 为什么
clear: both有效:它会让伪元素排在浮动元素下方,从而撑开父容器高度。
- 为什么
-
方案 B:触发 BFC(常用但要注意副作用)
css
.bfc {
overflow: hidden; /* 或 auto/scroll,非 visible */
}
-
优点
- 一行代码解决塌陷;顺便能隔离 margin 合并等问题。
-
缺点 / 风险
- 可能裁剪溢出内容(比如阴影、下拉菜单、绝对定位的浮层)。
- 如果你用
auto/scroll可能引入滚动条。
-
方案 C:
display: flow-root(推荐写法:语义明确、无裁剪副作用)
css
.flow-root {
display: flow-root;
}
-
优点
- 直接创建新的 BFC,且不像
overflow:hidden那样裁剪内容。 - 可读性强:看代码就知道"这是个独立的块级格式化上下文"。
- 直接创建新的 BFC,且不像
-
缺点
- 老旧浏览器兼容性不如 clearfix(现代项目通常没问题)。
-
为什么现代更推荐 Flex/Grid(工程化理由)
- 语义与目的匹配
float设计初衷是"文字环绕图片",不是布局系统;拿 float 做布局会不断触发补丁需求。
- 更少的隐式规则/坑
- float 布局经常伴随:清除浮动、塌陷、浮动覆盖、margin 合并等问题。
- Flex/Grid 天然是布局模型,容器与子项职责清晰。
- 响应式更自然
- Flex 的自适应、换行、对齐;Grid 的二维栅格与区域布局,做响应式更直观。
- 可维护性更好
- 代码更短、更一致;团队新人不需要背一堆历史兼容技巧。
- 语义与目的匹配
-
加分回答:什么时候仍然会用 float?
- 文字环绕图片(比如富文本内容)
- 老项目维护(不大动结构的情况下,用 clearfix/BFC 快速止血)