前端大厂面试 —— HTML5 & CSS 高频面试题
本文整理了字节跳动、腾讯、阿里巴巴、美团等一线互联网大厂前端面试中高频出现的 HTML5 与 CSS 问题,涵盖基础概念、布局方案、性能优化、新特性等核心知识点。
一、HTML5 篇
1. HTML5 有哪些新特性?
高频指数:⭐⭐⭐⭐⭐
HTML5 的新特性主要包括以下几类:
- 语义化标签:
<header>、<nav>、<main>、<article>、<section>、<aside>、<footer>、<figure>、<figcaption> - 多媒体支持:
<video>、<audio>原生支持音视频播放 - 图形绘制:
<canvas>2D 绘图、内联 SVG 支持 - 表单增强:新增
date、email、url、range、number、search、color等 input 类型,以及placeholder、required、pattern、autofocus等属性 - 本地存储:
localStorage、sessionStorage替代 Cookie 进行本地数据存储 - 离线应用:Application Cache(已废弃)、Service Worker
- WebSocket:支持全双工通信
- Web Worker:多线程后台运算
- 地理定位:Geolocation API
- 拖放 API:原生 Drag and Drop
- History API:
pushState、replaceState实现无刷新跳转
2. 如何理解 HTML 语义化?
高频指数:⭐⭐⭐⭐⭐
什么是语义化: 根据内容的结构和含义,选择合适的标签来构建页面,让标签本身就能表达内容的意义。
为什么要语义化:
- 对开发者友好:代码结构清晰,增强可读性,便于团队协作和维护
- 对机器友好:搜索引擎爬虫能更好地理解页面结构,有利于 SEO
- 对用户友好:屏幕阅读器等辅助设备能正确解析内容,提升无障碍访问体验
- 样式丢失可读:即使没有 CSS,页面也能呈现良好的内容结构
常用语义化标签:
| 标签 | 语义 |
|---|---|
<header> | 页眉/头部区域 |
<nav> | 导航链接区域 |
<main> | 页面主要内容(唯一) |
<article> | 独立的文章内容 |
<section> | 文档中的章节 |
<aside> | 侧边栏/附属内容 |
<footer> | 页脚区域 |
<figure> / <figcaption> | 图片/图表及其标题 |
<mark> | 高亮文本 |
<time> | 时间/日期 |
<details> / <summary> | 折叠/展开内容 |
3. DOCTYPE 的作用是什么?
高频指数:⭐⭐⭐⭐
<!DOCTYPE html> 声明位于文档最前面,用于告诉浏览器以哪种标准来解析文档。
- 标准模式(Standards Mode):浏览器按照 W3C 标准解析渲染页面
- 怪异模式(Quirks Mode):浏览器模拟老旧浏览器的行为来渲染页面,向后兼容
如果不声明 DOCTYPE,浏览器会进入怪异模式,可能导致不同浏览器下渲染结果不一致。
HTML5 只需要简单地声明 <!DOCTYPE html> 即可。
4. 行内元素、块级元素、行内块元素有什么区别?
高频指数:⭐⭐⭐⭐⭐
| 特性 | 块级元素 | 行内元素 | 行内块元素 |
|---|---|---|---|
| 独占一行 | ✅ 是 | ❌ 否 | ❌ 否 |
| 设置宽高 | ✅ 有效 | ❌ 无效 | ✅ 有效 |
| 默认宽度 | 父容器 100% | 内容撑开 | 内容撑开 |
| margin/padding | 四个方向均有效 | 水平方向有效,垂直方向不影响布局 | 四个方向均有效 |
| 常见标签 | div、p、h1-h6、ul、li、form | span、a、strong、em、img、input | img、input、button、select、textarea |
转换方式:
display: block; /* 转为块级 */
display: inline; /* 转为行内 */
display: inline-block; /* 转为行内块 */5. src 和 href 的区别?
高频指数:⭐⭐⭐
- src(source):引入外部资源并替换当前元素。浏览器解析到
src时会暂停其他资源的处理,直到该资源加载、编译、执行完毕(阻塞)。常用于<script>、<img>、<iframe> - href(hypertext reference):建立当前文档与引用资源之间的链接关系。浏览器会并行下载资源,不会阻塞文档解析。常用于
<a>、<link>
这就是为什么建议把
<script>放在<body>底部或使用defer/async属性。
6. script 标签中 defer 和 async 的区别?
高频指数:⭐⭐⭐⭐⭐
三种加载方式的对比:
<script src="script.js"></script> <!-- 默认:阻塞解析 -->
<script src="script.js" async></script> <!-- 异步加载,加载完立即执行 -->
<script src="script.js" defer></script> <!-- 异步加载,DOMContentLoaded 前执行 -->| 属性 | 下载方式 | 执行时机 | 执行顺序 | 适用场景 |
|---|---|---|---|---|
| 无 | 阻塞 HTML 解析 | 下载完立即执行 | 按书写顺序 | 需要立即执行的脚本 |
async | 并行下载 | 下载完立即执行(中断解析) | 不保证顺序 | 独立脚本(如统计、广告) |
defer | 并行下载 | HTML 解析完毕后、DOMContentLoaded 之前 | 按书写顺序 | 依赖 DOM 的脚本 |
7. 说说对 Web Worker 的理解?
高频指数:⭐⭐⭐
JavaScript 是单线程的,Web Worker 允许在后台线程中运行脚本,不会阻塞主线程的 UI 渲染。
特点:
- 运行在独立线程中,不影响页面性能
- 不能直接操作 DOM
- 通过
postMessage和onmessage与主线程通信 - 同源限制
// 主线程
const worker = new Worker('worker.js');
worker.postMessage({ data: 'hello' });
worker.onmessage = (e) => {
console.log('收到 Worker 返回的数据:', e.data);
};
// worker.js
self.onmessage = (e) => {
const result = heavyCalculation(e.data);
self.postMessage(result);
};8. 说说 localStorage、sessionStorage 和 Cookie 的区别?
高频指数:⭐⭐⭐⭐⭐
| 特性 | Cookie | localStorage | sessionStorage |
|---|---|---|---|
| 存储大小 | 约 4KB | 约 5MB | 约 5MB |
| 生命周期 | 可设置过期时间 | 永久存储,除非手动清除 | 会话结束(标签页关闭)即清除 |
| 与服务器通信 | 每次请求自动携带在 HTTP 头中 | 不参与通信 | 不参与通信 |
| 作用域 | 同源 + 同路径 | 同源 | 同源 + 同标签页 |
| API 易用性 | 需手动解析字符串 | getItem/setItem 简洁 | 同 localStorage |
| 适用场景 | 身份认证、用户偏好 | 持久化数据(主题、Token) | 临时数据(表单草稿) |
9. 什么是 Canvas?Canvas 和 SVG 的区别?
高频指数:⭐⭐⭐⭐
Canvas 是 HTML5 新增的绘图元素,通过 JavaScript 操作 Canvas API 在画布上绘制 2D 图形。
| 特性 | Canvas | SVG |
|---|---|---|
| 绘制方式 | 通过 JavaScript 逐像素绘制 | 使用 XML 描述 2D 图形 |
| 渲染方式 | 位图(像素) | 矢量图 |
| 事件处理 | 不支持为单独图形绑定事件 | 每个元素都可绑定事件 |
| 缩放 | 放大会失真 | 任意缩放不失真 |
| 性能 | 适合大量像素操作(游戏、数据可视化) | 适合少量图形、图标 |
| DOM | 不生成 DOM 元素 | 每个图形都是 DOM 元素 |
| 适用场景 | 游戏、图像处理、实时图表 | 图标、Logo、地图、可交互图形 |
10. 如何实现浏览器内多个标签页之间的通信?
高频指数:⭐⭐⭐⭐
- localStorage +
storage事件监听(最常用)
// 页面 A:写入数据
localStorage.setItem('message', JSON.stringify({ data: 'hello', timestamp: Date.now() }));
// 页面 B:监听变化
window.addEventListener('storage', (e) => {
if (e.key === 'message') {
console.log('收到消息:', JSON.parse(e.newValue));
}
});- BroadcastChannel API
const channel = new BroadcastChannel('my_channel');
channel.postMessage('hello'); // 发送
channel.onmessage = (e) => { ... } // 接收- SharedWorker
- WebSocket(服务端中转)
- postMessage(需要有对目标窗口的引用)
11. HTML5 的离线存储怎么使用?原理是什么?
高频指数:⭐⭐⭐
HTML5 离线存储主要有两种方案:
方案一:Application Cache(已废弃,了解即可)
通过 manifest 文件声明需要缓存的资源,浏览器会自动缓存。
方案二:Service Worker(推荐)
Service Worker 是运行在浏览器后台的独立线程,可以拦截网络请求、管理缓存,实现离线访问。
// 注册 Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
// sw.js
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open('v1').then((cache) => {
return cache.addAll(['/index.html', '/styles.css', '/app.js']);
})
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
})
);
});12. 说说对 HTML5 拖放 API 的理解?
高频指数:⭐⭐⭐
拖放的核心流程和事件:
| 事件 | 触发对象 | 说明 |
|---|---|---|
dragstart | 被拖元素 | 开始拖动时触发 |
drag | 被拖元素 | 拖动过程中持续触发 |
dragend | 被拖元素 | 拖动结束时触发 |
dragenter | 目标元素 | 拖入目标区域时触发 |
dragover | 目标元素 | 在目标区域内移动时持续触发 |
dragleave | 目标元素 | 离开目标区域时触发 |
drop | 目标元素 | 在目标区域释放时触发 |
关键点: 必须在 dragover 中调用 e.preventDefault() 才能触发 drop 事件。
二、CSS 篇
13. 说说 CSS 盒模型?
高频指数:⭐⭐⭐⭐⭐
每个 HTML 元素都可以看作一个矩形盒子,由四部分组成:content(内容)→ padding(内边距)→ border(边框)→ margin(外边距)。
两种盒模型:
/* 标准盒模型(W3C):width/height 只包含 content */
box-sizing: content-box; /* 默认值 */
/* IE 盒模型(怪异盒模型):width/height 包含 content + padding + border */
box-sizing: border-box; /* 实际开发常用 */实际开发中的最佳实践:
*, *::before, *::after {
box-sizing: border-box;
}14. CSS 选择器有哪些?优先级如何计算?
高频指数:⭐⭐⭐⭐⭐
常见选择器:
| 类别 | 选择器 | 示例 |
|---|---|---|
| 通用选择器 | * | * |
| 元素选择器 | element | div |
| 类选择器 | .class | .container |
| ID 选择器 | #id | #app |
| 属性选择器 | [attr=value] | [type="text"] |
| 后代选择器 | A B | div p |
| 子选择器 | A > B | ul > li |
| 相邻兄弟选择器 | A + B | h1 + p |
| 通用兄弟选择器 | A ~ B | h1 ~ p |
| 伪类选择器 | :pseudo | :hover、:nth-child() |
| 伪元素选择器 | ::pseudo | ::before、::after |
优先级权重(从高到低):
!important(最高,慎用)- 内联样式(
style=""):1,0,0,0 - ID 选择器:
0,1,0,0 - 类/伪类/属性选择器:
0,0,1,0 - 元素/伪元素选择器:
0,0,0,1 - 通配符/继承:
0,0,0,0
口诀: !important > 内联 > ID > 类 > 元素 > 继承/通配
15. CSS 中可继承与不可继承的属性有哪些?
高频指数:⭐⭐⭐
可继承属性:
- 字体相关:
font-family、font-size、font-weight、font-style - 文本相关:
color、text-align、text-indent、line-height、letter-spacing、word-spacing - 可见性:
visibility - 光标:
cursor - 列表:
list-style
不可继承属性:
- 盒模型:
width、height、margin、padding、border - 背景:
background - 定位:
position、top、left、right、bottom - 布局:
display、float、clear、overflow - 弹性/网格:
flex、grid相关属性
16. 说说 BFC(块级格式化上下文)?
高频指数:⭐⭐⭐⭐⭐
BFC(Block Formatting Context) 是一个独立的渲染区域,内部元素的布局不会影响外部元素。
触发 BFC 的条件:
overflow不为visible(如hidden、auto、scroll)display为inline-block、flex、inline-flex、grid、table-cell等position为absolute或fixedfloat不为none- 根元素
<html>
BFC 的应用场景:
- 解决 margin 重叠问题
<!-- 两个 BFC 之间的 margin 不会重叠 -->
<div style="overflow: hidden;">
<p style="margin-bottom: 20px;">段落1</p>
</div>
<div style="overflow: hidden;">
<p style="margin-top: 20px;">段落2</p>
</div>- 清除浮动
.clearfix {
overflow: hidden; /* 触发 BFC,包含浮动子元素 */
}- 阻止元素被浮动元素覆盖(自适应两栏布局)
.left { float: left; width: 200px; }
.right { overflow: hidden; } /* 触发 BFC,不会与浮动元素重叠 */17. 实现水平垂直居中的方式有哪些?
高频指数:⭐⭐⭐⭐⭐
方法一:Flex 布局(最推荐)
.parent {
display: flex;
justify-content: center;
align-items: center;
}方法二:Grid 布局
.parent {
display: grid;
place-items: center;
}方法三:绝对定位 + transform
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}方法四:绝对定位 + margin auto(已知宽高)
.child {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
margin: auto;
width: 200px;
height: 200px;
}方法五:绝对定位 + 负 margin(已知宽高)
.child {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
height: 200px;
margin-top: -100px;
margin-left: -100px;
}方法六:行内元素水平垂直居中
.parent {
text-align: center;
line-height: 200px; /* 等于容器高度 */
height: 200px;
}18. 如何实现两栏布局?三栏布局(圣杯/双飞翼)?
高频指数:⭐⭐⭐⭐⭐
两栏布局(左固定 + 右自适应)
Flex 方案:
.container { display: flex; }
.left { width: 200px; flex-shrink: 0; }
.right { flex: 1; }浮动 + BFC 方案:
.left { float: left; width: 200px; }
.right { overflow: hidden; } /* 触发 BFC */三栏布局(左右固定 + 中间自适应)
Flex 方案(最推荐):
.container { display: flex; }
.left { width: 200px; flex-shrink: 0; }
.center { flex: 1; }
.right { width: 200px; flex-shrink: 0; }圣杯布局:
.container { padding: 0 200px; }
.center { float: left; width: 100%; }
.left {
float: left; width: 200px;
margin-left: -100%;
position: relative; left: -200px;
}
.right {
float: left; width: 200px;
margin-left: -200px;
position: relative; right: -200px;
}双飞翼布局:
.center { float: left; width: 100%; }
.center-inner { margin: 0 200px; }
.left { float: left; width: 200px; margin-left: -100%; }
.right { float: left; width: 200px; margin-left: -200px; }19. 说说 Flex 弹性布局?
高频指数:⭐⭐⭐⭐⭐
Flex 布局的核心概念是 主轴(main axis) 和 交叉轴(cross axis)。
容器属性(设置在父元素上):
| 属性 | 说明 | 常用值 |
|---|---|---|
flex-direction | 主轴方向 | row、column、row-reverse、column-reverse |
flex-wrap | 是否换行 | nowrap、wrap、wrap-reverse |
justify-content | 主轴对齐 | flex-start、center、space-between、space-around、space-evenly |
align-items | 交叉轴对齐 | flex-start、center、flex-end、stretch、baseline |
align-content | 多行交叉轴对齐 | 同 justify-content |
gap | 子项间距 | 10px、10px 20px |
子项属性:
| 属性 | 说明 | 默认值 |
|---|---|---|
flex-grow | 放大比例 | 0(不放大) |
flex-shrink | 缩小比例 | 1(自动缩小) |
flex-basis | 初始主轴尺寸 | auto |
align-self | 单独的交叉轴对齐 | auto |
order | 排列顺序 | 0 |
常用简写:
flex: 1; /* flex: 1 1 0% —— 等分剩余空间 */
flex: auto; /* flex: 1 1 auto —— 按内容分配 */
flex: none; /* flex: 0 0 auto —— 不伸缩 */
flex: 0 0 200px; /* 固定 200px,不伸缩 */20. 说说 Grid 网格布局?
高频指数:⭐⭐⭐⭐
Grid 是二维布局系统,可以同时控制行和列。
.container {
display: grid;
grid-template-columns: 200px 1fr 200px; /* 三列:固定-自适应-固定 */
grid-template-rows: 80px 1fr 60px; /* 三行:头-内容-尾 */
gap: 10px; /* 网格间距 */
}
/* 子项跨行/列 */
.item {
grid-column: 1 / 3; /* 从第1条网格线到第3条 */
grid-row: 1 / 2;
}常用函数:
repeat(3, 1fr):重复三列等分minmax(200px, 1fr):最小 200px,最大自适应auto-fill/auto-fit:自动填充列数
Grid vs Flex:
| 维度 | Flex | Grid |
|---|---|---|
| 布局方向 | 一维(行或列) | 二维(行和列同时) |
| 适用场景 | 组件内部布局、导航栏 | 页面整体布局、复杂网格 |
| 控制方式 | 基于内容流 | 基于网格线精确控制 |
21. CSS 中的定位方式有哪些?
高频指数:⭐⭐⭐⭐⭐
| 定位方式 | 说明 | 是否脱离文档流 | 定位基准 |
|---|---|---|---|
static | 默认值,正常文档流 | 否 | 无 |
relative | 相对定位 | 否(保留原始空间) | 自身原始位置 |
absolute | 绝对定位 | 是 | 最近的非 static 祖先元素 |
fixed | 固定定位 | 是 | 浏览器视口 |
sticky | 粘性定位 | 否 | 滚动容器,超过阈值后表现为 fixed |
sticky 使用注意事项:
.sticky-header {
position: sticky;
top: 0; /* 必须指定至少一个阈值 */
}- 父元素不能设置
overflow: hidden或overflow: auto - 粘性定位的范围被限制在父容器的 content 区域内
22. 如何清除浮动?
高频指数:⭐⭐⭐⭐
浮动元素脱离文档流,会导致父元素高度塌陷。
方法一:clearfix 伪元素(最推荐)
.clearfix::after {
content: '';
display: block;
clear: both;
}方法二:触发 BFC
.parent {
overflow: hidden; /* 或 auto */
}方法三:额外标签法
<div style="clear: both;"></div>方法四:使用 Flex / Grid 替代浮动(现代方案)
.parent {
display: flex; /* 直接用 Flex 布局,不再需要 float */
}23. CSS 中 display、visibility、opacity 隐藏元素的区别?
高频指数:⭐⭐⭐⭐⭐
| 属性 | display: none | visibility: hidden | opacity: 0 |
|---|---|---|---|
| 是否占据空间 | ❌ 不占据 | ✅ 占据 | ✅ 占据 |
| 是否触发事件 | ❌ 不触发 | ❌ 不触发 | ✅ 可触发 |
| 是否影响子元素 | 子元素一同消失 | 子元素可通过 visibility: visible 单独显示 | 子元素一同透明 |
| 是否触发重排 | ✅ 触发 | ❌ 仅重绘 | ❌ 仅重绘 |
| 过渡动画 | ❌ 不支持 | ✅ 支持 | ✅ 支持 |
| 无障碍 | 屏幕阅读器忽略 | 屏幕阅读器忽略 | 屏幕阅读器可读 |
24. 说说对重绘(Repaint)和重排/回流(Reflow)的理解?
高频指数:⭐⭐⭐⭐⭐
重排(Reflow): 当元素的几何属性(位置、尺寸)发生变化时,浏览器需要重新计算元素的布局,然后重新渲染。
重绘(Repaint): 当元素的外观(颜色、背景、阴影等)发生变化,但不影响布局时,浏览器只需要重新绘制受影响的部分。
重排一定触发重绘,但重绘不一定触发重排。
触发重排的操作:
- 修改元素尺寸(
width、height、padding、margin、border) - 修改元素位置(
top、left) - 修改 DOM 结构(增删节点)
- 读取布局信息(
offsetWidth、clientHeight、getComputedStyle()) - 窗口大小变化
性能优化建议:
- 批量修改样式,使用
class切换而非逐个修改 - 使用
transform代替top/left做动画(不触发重排) - 使用
will-change提示浏览器优化 - 将频繁重排的元素脱离文档流(
position: absolute/fixed) - 读取布局属性时做缓存,避免反复读取
/* 优化前:触发重排 */
.box { top: 100px; left: 100px; }
/* 优化后:不触发重排,GPU 加速 */
.box { transform: translate(100px, 100px); }25. CSS 如何实现响应式设计?
高频指数:⭐⭐⭐⭐⭐
核心手段:
- 媒体查询(Media Query)
/* 移动优先 */
.container { width: 100%; }
@media screen and (min-width: 768px) {
.container { width: 750px; }
}
@media screen and (min-width: 1200px) {
.container { width: 1170px; }
}- 弹性布局(Flex / Grid)
- 相对单位:
%、rem、em、vw、vh、vmin、vmax - 弹性图片:
max-width: 100%; height: auto; - 视口设置:
<meta name="viewport" content="width=device-width, initial-scale=1.0"> - CSS 容器查询(Container Query)—— 新特性
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card { flex-direction: row; }
}常见断点:
| 设备 | 宽度 |
|---|---|
| 手机 | < 768px |
| 平板 | 768px - 1024px |
| 桌面 | > 1024px |
| 大屏 | > 1200px |
26. CSS 中 em、rem、vw、vh 等单位的区别?
高频指数:⭐⭐⭐⭐
| 单位 | 参考基准 | 说明 |
|---|---|---|
px | 绝对单位 | 像素 |
em | 父元素 font-size | 相对父元素,会层层叠加 |
rem | 根元素(html)font-size | 相对根元素,全局统一 |
% | 父元素对应属性 | 宽度相对父元素宽度,字号相对父元素字号 |
vw | 视口宽度的 1% | 100vw = 视口宽度 |
vh | 视口高度的 1% | 100vh = 视口高度 |
vmin | vw 和 vh 中的较小值 | 适合保持比例 |
vmax | vw 和 vh 中的较大值 | 适合保持比例 |
最佳实践: 在 <html> 上设置 font-size: 62.5%(即 10px),然后全局使用 rem 单位:
html { font-size: 62.5%; } /* 1rem = 10px */
body { font-size: 1.6rem; } /* 16px */
h1 { font-size: 2.4rem; } /* 24px */27. 说说伪类和伪元素的区别?
高频指数:⭐⭐⭐⭐
伪类(Pseudo-class): 用于选择元素的某种状态,以单冒号 : 表示。
a:hover { color: red; } /* 鼠标悬停状态 */
li:first-child { ... } /* 第一个子元素 */
input:focus { ... } /* 获得焦点 */
li:nth-child(2n) { ... } /* 偶数子元素 */伪元素(Pseudo-element): 用于创建不在 DOM 中的虚拟元素,以双冒号 :: 表示。
p::before { content: '👉'; } /* 在元素内容前插入 */
p::after { content: ''; } /* 在元素内容后插入 */
p::first-line { ... } /* 第一行 */
p::first-letter { ... } /* 首字母 */
input::placeholder { ... } /* 占位符 */
::selection { ... } /* 选中文本 */核心区别:
- 伪类选择的是已有元素的特定状态
- 伪元素创建的是文档中本不存在的"虚拟"元素
28. CSS3 有哪些新特性?
高频指数:⭐⭐⭐⭐
| 类别 | 新特性 |
|---|---|
| 选择器 | :nth-child()、:not()、::placeholder、属性选择器增强 |
| 边框 | border-radius、box-shadow、border-image |
| 背景 | background-size、background-origin、background-clip、多重背景 |
| 渐变 | linear-gradient、radial-gradient、conic-gradient |
| 文字 | text-shadow、word-wrap、text-overflow、@font-face |
| 2D/3D 变换 | transform:translate、rotate、scale、skew、perspective |
| 过渡 | transition |
| 动画 | @keyframes、animation |
| 弹性布局 | display: flex |
| 网格布局 | display: grid |
| 多列布局 | column-count、column-gap |
| 滤镜 | filter、backdrop-filter |
| 自定义属性 | CSS 变量 --var-name、var() |
| 媒体查询 | @media 增强 |
| 容器查询 | @container(较新) |
| 混合模式 | mix-blend-mode、background-blend-mode |
29. 如何用纯 CSS 实现三角形?
高频指数:⭐⭐⭐⭐
原理: 利用 border 的实现机制——当元素宽高为 0 时,四条边框以三角形形式拼接。
/* 向上的三角形 */
.triangle-up {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid #333;
}
/* 向右的三角形 */
.triangle-right {
width: 0;
height: 0;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
border-left: 100px solid #333;
}现代方案:使用 clip-path
.triangle {
width: 100px;
height: 100px;
background: #333;
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}30. 如何实现 CSS 动画?transition 和 animation 的区别?
高频指数:⭐⭐⭐⭐
transition(过渡): 需要事件触发(如 hover),从状态 A 到状态 B 的变化。
.box {
width: 100px;
transition: width 0.3s ease-in-out;
}
.box:hover {
width: 200px;
}animation(动画): 可自动执行,支持多个关键帧,更灵活。
@keyframes slide {
0% { transform: translateX(0); }
50% { transform: translateX(200px); }
100% { transform: translateX(0); }
}
.box {
animation: slide 2s ease-in-out infinite;
}| 特性 | transition | animation |
|---|---|---|
| 触发方式 | 需要事件触发(hover等) | 可自动播放 |
| 关键帧 | 只有起始和结束两个状态 | 可定义多个关键帧 |
| 循环播放 | 不支持 | 支持 infinite |
| 暂停控制 | 不支持 | animation-play-state |
| JS 事件 | transitionend | animationstart/animationend/animationiteration |
31. 说说 CSS 变量(自定义属性)?
高频指数:⭐⭐⭐
/* 定义变量 */
:root {
--primary-color: #409eff;
--font-size-base: 16px;
--spacing: 8px;
}
/* 使用变量 */
.button {
background-color: var(--primary-color);
font-size: var(--font-size-base);
padding: var(--spacing) calc(var(--spacing) * 2);
}
/* 带默认值 */
.text {
color: var(--text-color, #333);
}
/* 通过 JS 动态修改 */document.documentElement.style.setProperty('--primary-color', '#ff6700');应用场景: 主题切换、暗黑模式、Design Token 管理。
32. 如何实现移动端 1px 边框?
高频指数:⭐⭐⭐⭐
在高倍屏(dpr >= 2)下,CSS 的 1px 会被渲染为物理像素的 2px 或 3px,看起来偏粗。
方案一:伪元素 + transform 缩放(最常用)
.border-1px {
position: relative;
}
.border-1px::after {
content: '';
position: absolute;
left: 0; top: 0;
width: 200%;
height: 200%;
border: 1px solid #ddd;
transform: scale(0.5);
transform-origin: left top;
box-sizing: border-box;
pointer-events: none;
border-radius: inherit;
}方案二:使用 box-shadow
.border-1px {
box-shadow: 0 0 0 0.5px #ddd;
}方案三:border-image + SVG
方案四:设置 viewport 的 initial-scale
33. CSS 性能优化有哪些方法?
高频指数:⭐⭐⭐⭐
选择器优化
- 避免使用通配符
* - 避免深层嵌套(不超过 3 层)
- 避免使用标签选择器限定类选择器(如
div.header)
- 避免使用通配符
减少重绘重排
- 使用
transform代替top/left - 使用
opacity代替visibility - 批量修改 DOM,使用文档碎片或离线 DOM
- 使用
资源优化
- 压缩 CSS 文件
- 使用 CSS Sprites(精灵图)减少请求
- 合理使用
@import(会阻塞加载,建议用<link>)
渲染优化
- 使用
will-change提示浏览器做 GPU 加速 - 使用
contain属性限制重排范围 - 减少使用
box-shadow、filter等耗性能属性
- 使用
加载优化
- 关键 CSS 内联(Critical CSS)
- 非关键 CSS 异步加载
- 利用
preload预加载关键资源
34. 如何实现暗黑模式(Dark Mode)?
高频指数:⭐⭐⭐
方案一:CSS 变量 + 媒体查询
:root {
--bg-color: #ffffff;
--text-color: #333333;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
}
}
body {
background-color: var(--bg-color);
color: var(--text-color);
}方案二:CSS 变量 + data 属性切换
[data-theme='dark'] {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
}// 切换主题
document.documentElement.setAttribute('data-theme', 'dark');35. 如何画一条 0.5px 的线?
高频指数:⭐⭐⭐
/* 方法一:transform 缩放 */
.line {
height: 1px;
background: #000;
transform: scaleY(0.5);
transform-origin: 0 0;
}
/* 方法二:使用 SVG */
.line {
background: none;
height: 1px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='1'%3E%3Cline x1='0' y1='0.5' x2='100%25' y2='0.5' stroke='%23000'/%3E%3C/svg%3E");
}
/* 方法三:使用渐变 */
.line {
height: 1px;
background: linear-gradient(to bottom, transparent 50%, #000 50%);
}三、综合高频题
36. 什么是 CSS 层叠上下文(Stacking Context)?
高频指数:⭐⭐⭐⭐
层叠上下文是 HTML 元素的三维概念,决定了元素在 Z 轴上的显示顺序。
创建层叠上下文的条件:
position为relative/absolute/fixed且z-index不为autoopacity值小于 1transform值不为nonefilter值不为nonedisplay: flex/grid的子元素且z-index不为autoisolation: isolatewill-change指定了任意属性
层叠顺序(从低到高):
- 背景和边框(层叠上下文的背景/边框)
z-index为负值的定位元素- 块级元素(正常文档流中的)
- 浮动元素
- 行内/行内块元素
z-index: 0/auto的定位元素z-index为正值的定位元素
37. 如何实现文本溢出省略号?
高频指数:⭐⭐⭐⭐⭐
单行溢出省略:
.ellipsis {
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出隐藏 */
text-overflow: ellipsis; /* 省略号 */
}多行溢出省略(WebKit 方案):
.ellipsis-multi {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; /* 最多显示 3 行 */
overflow: hidden;
}兼容性方案(利用伪元素):
.ellipsis-multi {
position: relative;
max-height: 4.5em; /* line-height * 行数 */
line-height: 1.5em;
overflow: hidden;
}
.ellipsis-multi::after {
content: '...';
position: absolute;
bottom: 0;
right: 0;
padding-left: 20px;
background: linear-gradient(to right, transparent, #fff 50%);
}38. margin 塌陷和 margin 合并是什么?如何解决?
高频指数:⭐⭐⭐⭐
margin 合并(Margin Collapsing): 两个垂直相邻的块级元素,上方的 margin-bottom 和下方的 margin-top 会合并为其中的较大值。
margin 塌陷: 父子元素之间,子元素的 margin-top 会"穿透"父元素,表现为父元素的 margin-top。
解决方案:
/* 方法一:为父元素触发 BFC */
.parent { overflow: hidden; }
/* 方法二:为父元素添加 border 或 padding */
.parent { border-top: 1px solid transparent; }
.parent { padding-top: 1px; }
/* 方法三:使用 flex 布局 */
.parent { display: flex; flex-direction: column; }39. 如何用 CSS 实现一个自适应的正方形?
高频指数:⭐⭐⭐
方法一:padding-bottom 百分比(经典方案)
.square {
width: 50%;
padding-bottom: 50%; /* padding 的百分比基于父元素的宽度 */
height: 0;
background: #333;
}方法二:aspect-ratio(现代方案,推荐)
.square {
width: 50%;
aspect-ratio: 1 / 1;
background: #333;
}方法三:vw 单位
.square {
width: 50vw;
height: 50vw;
background: #333;
}40. 什么是 CSS 的 contain 属性?
高频指数:⭐⭐⭐
contain 属性用于声明元素和它的内容尽可能独立于文档树的其余部分,让浏览器可以对该元素的布局、样式、绘制、大小等进行局部优化。
.widget {
contain: layout; /* 该元素内部的布局变化不会影响外部 */
contain: paint; /* 该元素的子元素不会显示在其边界之外 */
contain: size; /* 该元素大小不受子元素影响 */
contain: content; /* 等价于 layout + paint */
contain: strict; /* 等价于 layout + paint + size */
}应用场景: 大量列表项、卡片、Widget 等独立组件,使用 contain 可以显著减少重排范围,提升渲染性能。
四、场景题 & 编程题
41. 实现一个自适应的搜索框布局
题目描述: 左侧搜索框自适应宽度,右侧按钮固定宽度。
.search-bar {
display: flex;
}
.search-input {
flex: 1;
height: 40px;
border: 1px solid #ddd;
border-radius: 4px 0 0 4px;
padding: 0 12px;
outline: none;
}
.search-btn {
width: 80px;
height: 40px;
border: none;
background: #409eff;
color: #fff;
border-radius: 0 4px 4px 0;
cursor: pointer;
}42. 实现一个加载动画(Spinner)
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #409eff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}43. 实现一个 Tooltip 气泡提示
.tooltip {
position: relative;
display: inline-block;
cursor: pointer;
}
.tooltip::after {
content: attr(data-tip);
position: absolute;
bottom: 120%;
left: 50%;
transform: translateX(-50%);
padding: 6px 12px;
background: #333;
color: #fff;
border-radius: 4px;
font-size: 14px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
}
.tooltip::before {
content: '';
position: absolute;
bottom: calc(120% - 6px);
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: #333;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip:hover::after,
.tooltip:hover::before {
opacity: 1;
}<span class="tooltip" data-tip="这是一个提示">鼠标悬停我</span>五、总结:面试知识图谱
HTML5 & CSS 面试知识图谱
│
├── HTML5
│ ├── 语义化标签与 SEO
│ ├── 新增表单类型与属性
│ ├── 多媒体(audio / video)
│ ├── Canvas & SVG
│ ├── 本地存储(localStorage / sessionStorage)
│ ├── 离线存储(Service Worker)
│ ├── Web Worker
│ ├── WebSocket
│ ├── 地理定位 & 拖放 API
│ └── History API
│
├── CSS 基础
│ ├── 盒模型(标准 / IE)
│ ├── 选择器与优先级
│ ├── 可继承与不可继承属性
│ ├── 伪类与伪元素
│ ├── CSS 单位(px / em / rem / vw / vh)
│ └── CSS 变量
│
├── CSS 布局
│ ├── 正常流 / 浮动 / 定位
│ ├── BFC
│ ├── Flex 弹性布局
│ ├── Grid 网格布局
│ ├── 两栏 / 三栏布局
│ ├── 水平垂直居中
│ └── 响应式设计 / 媒体查询
│
├── CSS 进阶
│ ├── 层叠上下文 & z-index
│ ├── 重绘与重排
│ ├── CSS 性能优化
│ ├── CSS3 动画 / 过渡
│ ├── 暗黑模式
│ ├── 1px 问题
│ └── contain 属性
│
└── 编码实战
├── 三角形 / 0.5px 线
├── 文本溢出省略
├── 加载动画
├── 自适应正方形
└── Tooltip 气泡面试建议:
- 面试中不仅要回答"是什么",还要能说出"为什么"和"怎么用"
- 布局类题目建议能手写 CSS 代码
- 性能优化类的问题要结合浏览器渲染原理来回答
- 对于 CSS3 新特性要关注兼容性和渐进增强策略
- 多关注新标准:容器查询、
:has()选择器、subgrid等