专题知识学习:CSS
第一章:CSS 基础与核心概念
1.1 CSS 语法与选择器(基础选择器、组合选择器、属性选择器)
基础语法结构
/* 标准规则 */
selector {
property: value; /* 声明块 */
}
基础选择器
元素选择器
div { color: red; }
- 权重:0,0,0,1
- 适用场景:全局样式覆盖
类选择器
.active { background: blue; }
- 权重:0,0,1,0
- 实践:BEM命名规范(block__element–modifier)
ID 选择器
#header { height: 60px; }
- 权重:0,1,0,0
- 禁用场景:React/Vue中易导致样式污染(组件化开发慎用)
通配选择器
* { box-sizing: border-box; }
- 权重:0,0,0,0
- 性能影响:大型项目避免过度使用
组合选择器
后代选择器
nav a { color: green; } /* 所有层级后代 */
- 权重:各选择器权重相加
- 性能陷阱:深层嵌套增加渲染成本(建议限制 3 层)
子选择器
ul > li { list-style: none; } /* 仅直接子元素 */
- 与后代选择器区别:不匹配非直接嵌套元素
相邻兄弟选择器
h1 + p { margin-top: 0; } /* 紧邻的下一个兄弟 */
- 典型场景:表单元素间隔控制
通用兄弟选择器
h2 ~ p { color: gray; } /* 后续所有同级兄弟 */
- 应用案例:目录标题与内容样式关联
属性选择器
| 选择器类型 | 示例 | 匹配规则 | 权重 |
|---|---|---|---|
| [attr] | [target] | 存在该属性即可 | 0,0,1,0 |
| [attr=value] | [lang=”en”] | 属性值完全匹配 | 0,0,1,0 |
| [attr~=value] | [class~=”logo”] | 属性值包含该词(空格分隔) | 0,0,1,0 |
| [attr=value] | [lang=”zh”] | 属性值为zh或以zh-开头 | 0,0,1,0 |
| [attr^=value] | [href^=”https”] | 属性值以指定字符串开头 | 0,0,1,0 |
| [attr$=value] | [src$=”.png”] | 属性值以指定字符串结尾 | 0,0,1,0 |
| [attr*=value] | [data*=”error”] | 属性值包含子字符串 | 0,0,1,0 |
思考
Q:.nav li > a 和 .nav > li > a 的权重与作用域差异?
权重相同(0,0,1,2),但后者限制 li 必须为 .nav 的直接子元素
Q:div:not([class]) 会匹配哪些元素?
所有没有 class 属性的 div 元素
1.2 盒模型(标准盒模型 vs. 怪异盒模型)
核心概念对比
| 特性 | 标准盒模型(W3C) | 怪异盒模型(Quirks Mode) |
|---|---|---|
| 触发条件 | box-sizing: content-box | box-sizing: border-box |
| 宽度计算 | width = content宽度 | width = content + padding + border |
| 高度计算 | height = content高度 | height = content + padding + border |
| 默认场景 | 现代浏览器默认模式 | 传统IE5及更早浏览器 |
代码验证
<div class="std-box">标准盒模型</div>
<div class="weird-box">怪异盒模型</div>
.std-box {
box-sizing: content-box; /* 默认值可省略 */
width: 100px;
padding: 20px;
border: 5px solid red;
/* 实际占用宽度:100 + 20*2 + 5*2 = 150px */
}
.weird-box {
box-sizing: border-box;
width: 100px;
padding: 20px;
border: 5px solid blue;
/* 实际占用宽度:100px (content自动压缩为50px) */
}
思考
Q:为什么大型项目普遍采用 border-box?
- 开发体验优化:轻松实现栅格化布局,无需计算 padding
- 性能优势:减少重排计算(浏览器无需重新计算内容区尺寸)
- 设计系统适配:确保 UI 标注尺寸与实际渲染尺寸一致
1.3 布局模式(块级、行内、行内块、Flex、Grid)
块级布局(Block)
display: block;
核心特性
- 独占一行,默认宽度撑满父容器
- 可设置宽高/margin/padding所有方向
- 典型元素:
<div>、<p>、<section>
行内布局(Inline)
display: inline;
核心特性
- 不独占一行,宽度由内容决定
- 不可设置宽高,垂直方向的 margin/padding 不生效
- 典型元素:
<span>、<a>、<em>
行内块布局(Inline-block)
display: inline-block;
核心特性
- 不独占一行但可以设置宽高(兼具块级布局和行内布局特性)
- 默认基线对齐(引发经典垂直对齐问题)
思考
- 如何消除行内块元素间隙:父容器font-size: 0或HTML代码无空格
- 垂直对齐控制:vertical-align: middle/top/bottom
Flex布局
display: flex;
核心特性
- 主轴/交叉轴双轴控制
- 子项弹性伸缩(flex-grow/shrink/basis)
思考
- 实现等高布局:
align-items: stretch - 圣杯布局:
flex: 1+order属性 - 性能优化:避免过度嵌套
实战实例
.container {
display: flex;
flex-wrap: wrap;
gap: 10px; /* 替代margin方案 */
}
.item {
flex: 1 0 calc(33.33% - 10px); /* 三栏自适应 */
}
Grid网格布局
display: grid;
核心特性
- 二维布局系统(行列显式定义)
- 网格线/网格区域命名控制
渲染性能排序
Block > Flex ≈ Grid > Inline-block(复合层创建成本)
1.4 常用单位(px、em、rem、vw/vh、%)
绝对单位与相对单位的对比
| 单位类型 | 代表单位 | 基准参照物 | 适用场景 |
|---|---|---|---|
| 绝对单位 | px | 设备物理像素 | 边框/阴影等固定尺寸 |
| 相对单位 | em/rem | 字体大小/根字体大小 | 响应式文本/组件间距 |
| 视口单位 | vw/vh | 视窗宽高 | 全屏布局/自适应元素 |
| 百分比 | % | 父元素对应属性值 | 流式布局/继承比例 |
核心单位详解
px(像素)
- 本质:与设备物理像素挂钩(但受 DPR 影响)
- 陷阱:
.box { width: 2px; /* 高清屏可能实际渲染为4物理像素 */ }
em
- 计算规则:
1em = 当前元素 font-size - 级联问题:
<div class="parent" style="font-size: 20px"> <div class="child" style="font-size: 1.2em"> <!-- 24px --> <div class="grandchild" style="width: 2em"> <!-- 48px (!) --> </div> </div> </div>
rem(Root em)
- 计算规则:
1rem = 根元素 font-size
vw/vh(视口单位)
- 计算规则:
1vw = 视口宽度的 1%,1vh = 视口高度的 1% - 陷阱:移动端vh包含浏览器工具栏区域(可用dvh单位解决)
%(百分比)
参照基准:
属性 参照对象 width/height 父元素的内容区宽度/高度 padding/margin 父元素的内容区宽度 top/left 包含块的高度/宽度 经典面试题
.parent { width: 200px; padding: 10%; } /* 实际padding值为20px(基于父元素width计算) */
1.5 层叠与继承(z-index、!important、继承规则)
层叠上下文的核心原理
形成条件(触发 BFC 的升级版)
- position: relative/absolute/fixed + z-index ≠ auto
- opacity < 1
- transform/filter 非 none
- flex/grid容器的子项且z-index ≠ auto
黄金规则
- 每个层叠上下文自成体系(内部 z-index 仅在该上下文中比较)
- 兄弟元素按 z-index 数值排序
- 不同上下文的比较取决于父级层叠上下文的层级
- 7层堆叠顺序(从底到顶):
- 层叠上下文的背景/边框
- z-index < 0 的子元素
- 块级元素(非定位)
- 浮动元素
- 行内元素(非定位)
- z-index: auto 的定位元素
- z-index ≥ 1 的子元素
示例
<div style="position: relative; z-index: 1;">
<div style="position: absolute; z-index: 100;">A</div>
</div>
<div style="position: relative; z-index: 2;">
<div style="position: absolute; z-index: 1;">B</div>
</div>
最终显示顺序:B 覆盖 A(父级上下文 z-index: 2 > 1)
!important 终极权重
权重等级表
| 来源 | 示例 | 权重值 |
|---|---|---|
| 用户代理!important | 浏览器默认样式 | ∞+3 |
| 用户!important | 用户自定义样式表 | ∞+2 |
| 作者!important | 开发者写的!important | ∞+1 |
| 动画关键帧 | @keyframes | ∞ |
| 普通作者声明 | 常规CSS规则 | 按选择器权重 |
破解 !important
/* 原始问题样式 */
.btn { color: red !important; }
/* 解决方案1:更高权重!important */
html body .btn { color: blue !important; }
/* 解决方案2:JavaScript修改内联样式 */
element.style.setProperty('color', 'green', 'important');
继承规则
核心继承机制
- 文本相关属性默认继承
- 字体属性:font-family, font-size, font-weight, font-style
- 文本属性:color, line-height, text-align, text-indent
- 其他:letter-spacing, word-spacing, text-transform
- 布局相关属性默认不继承
- 盒模型:width, height, margin, padding, border
- 定位:position, top, left, z-index
- 显示:display, float, overflow
可继承属性清单
- 文本相关:`font-family`, `color`, `line-height`, `letter-spacing`等
- 列表相关:`list-style-type`, `list-style-position`等
- 表格相关:`border-collapse`, `border-spacing`等
- 可见性:`visibility`
- 光标:`cursor`
显式继承技巧
.ant-input {
font: inherit; /* 强制继承父元素字体设置 */
color: initial; /* 使用浏览器默认颜色 */
color: unset; /* 如果是继承属性则继承,否则用初始值 */
display: revert; /* 使用浏览器默认的 display 值 */
}
继承链中断场景
<div style="font-size: 16px;">
<span style="font-size: 1.5em;">24px</span>
<!-- 子元素设置非继承属性如width会中断 -->
</div>
第二章:CSS 布局技术
2.1 传统布局(浮动 float、定位 position)
浮动布局(float)
.float-item {
float: left | right | none;
clear: both | left | right; /* 清除浮动影响 */
}
核心机制
- 文档流破坏:浮动元素会脱离普通流,其他盒子会“无视它”(但文本内容会围绕)
- 包裹性:浮动元素会默认收缩宽度以适应内容(除非显式设置宽度)
经典应用场景
(1)多栏布局(早期实现方式)
.left-col { float: left; width: 200px; }
.right-col { margin-left: 210px; }
(2)图文混排
img {
float: left;
margin-right: 15px;
shape-outside: circle(); /* 高级文字环绕 */
}
陷阱:高度塌陷问题
<div class="parent">
<div class="float-child"></div>
</div>
<!-- parent高度为0 -->
定位布局(position) - 精准控制的利器
各大定位类型对比
| 类型 | 脱离文档流 | 定位基准 | 典型应用场景 |
|---|---|---|---|
| static | 否 | 正常流 | 默认值 |
| relative | 否 | 自身原始位置 | 微调元素/建立定位上下文 |
| absolute | 是 | 最近非static祖先 | 弹窗/下拉菜单/工具提示 |
| fixed | 是 | 视口 | 固定导航栏/悬浮按钮 |
| sticky | 是(滚动时) | 最近滚动容器 | 吸顶效果/表头固定 |
粘性定位(sticky)的阈值控制
.sticky-header {
position: sticky;
top: 20px; /* 距离视口顶部20px时触发固定 */
z-index: 100;
}
失效条件:
- 父元素设置 overflow: hidden
- 未指定 top/bottom/left/right 任一值
2.2 Flex 弹性布局(flex-direction、justify-content、align-items)
Flexbox(弹性盒子布局)是 CSS3 中引入的一种强大的布局模式,它提供了一种更有效的方式来布置、对齐和分配容器内项目之间的空间,即使它们的大小是未知或动态变化的。
基本概念
Flex 容器与项目:
- Flex 容器(Flex Container):设置了 display: flex 或 display: inline-flex 的元素
- Flex 项目(Flex Items):Flex 容器的直接子元素
主轴和交叉轴:
- 主轴(Main Axis):Flex 项目沿此轴排列,方向由 flex-direction 决定
- 交叉轴(Cross Axis):与主轴垂直的轴
flex 弹性布局最核心的三要素:
- flex-direction
- justify-content
- align-items
flex-direction - 主轴方向控制
/* 响应式布局切换 */
.container {
flex-direction: row; /* 桌面端 */
}
@media (max-width: 768px) {
.container {
flex-direction: column; /* 移动端 */
}
}
作用:定义 Flex 容器的主轴方向,直接影响子项的排列方式
属性详解
| 属性值 | 效果图示 | 典型应用场景 |
|---|---|---|
| row(默认) | → → → → | 水平导航栏/商品列表 |
| row-reverse | ← ← ← ← | 从右到左的特殊布局需求 |
| column | ↓ ↓ ↓ ↓ |
移动端垂直菜单/瀑布流 |
| column-reverse | ↑ ↑ ↑ ↑ |
聊天消息时间倒序展示 |
justify-content - 主轴对齐方式
/* 表格工具栏布局 */
.toolbar {
display: flex;
justify-content: space-between; /* 左右分组 */
padding: 0 16px;
}
/* 弹性网格布局 */
.grid {
display: flex;
flex-wrap: wrap;
justify-content: space-around; /* 卡片四周留白均匀 */
}
作用:控制子项在主轴上的对齐与空间分配
属性详解
| 属性值 | 效果图示 | 空间分配规则 |
|---|---|---|
| flex-start | [■ ■ ■]________ | 向主轴起点聚集(默认) |
| flex-end | ________[■ ■ ■] | 向主轴终点聚集 |
| center | ____[■ ■ ■]____ |
居中排列 |
| space-between | [■][■][■] | 首尾贴边,中间均分 |
| space-around | [■][■][■] | 每个项目两侧间距相等 |
| space-evenly | [■][■][■] | 项目与容器间距完全均分 |
align-items - 交叉轴对齐方式
/* 表单输入行对齐 */
.form-row {
display: flex;
align-items: baseline; /* 让label和input文字基线对齐 */
}
/* 垂直居中终极方案 */
.modal {
display: flex;
align-items: center;
justify-content: center;
}
作用:控制子项在交叉轴上的对齐方式(单行布局)
属性详解
| 属性值 | 对齐规则 |
|---|---|
| stretch(默认) | 拉伸填满容器高度 |
| flex-start | 向交叉轴起点对齐 |
| flex-end | 向交叉轴终点对齐 |
| center | 居中对齐 |
| baseline | 按文本基线对齐 |
Flex 其他容器属性
flex-wrap
控制项目是否换行,其值有:
- nowrap(默认):不换行
- wrap:换行,第一行在上
- wrap-reverse:换行,第一行在下
flex-flow
flex-direction 和 flex-wrap 的简写
.container {
flex-flow: column wrap;
}
align-content
定义多根轴线的对齐方式(只有一根轴线时无效)
.container {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
Flex 项目属性
order
- 定义项目的排列顺序,数值越小越靠前
.item { order: <integer>; /* 默认 0 */ }
flex-grow
- 定义项目的放大比例
- 默认0(不放大)
- 所有项目的flex-grow值比例决定如何分配剩余空间
.item { flex-grow: <number>; /* 默认 0 */ }
flex-shrink
- 定义项目的缩小比例
.item { flex-shrink: <number>; /* 默认 1 */ }
flex-basis
- 定义在分配多余空间前,项目占据的主轴空间
- flex: 1中的0%表示”我最初不需要空间”
.item { flex-basis: <length> | auto; /* 默认 auto */ }
flex
- flex-grow, flex-shrink 和 flex-basis 的简写
.item { flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ] }
常用简写值:
- flex: 0 1 auto(默认)
- flex: 1 → flex: 1 1 0%
- flex: auto → flex: 1 1 auto
- flex: none → flex: 0 0 auto
align-self
- 允许单个项目有与其他项目不一样的对齐方式
.item { align-self: auto | flex-start | flex-end | center | baseline | stretch; }
三属性联调实践
(1)圣杯布局实现
.holy-grail {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.header, .footer {
flex: 0 0 auto;
}
.content {
flex: 1;
display: flex;
flex-direction: row;
}
.main {
flex: 1;
}
.sidebar {
flex: 0 0 200px;
order: -1; /* 左侧边栏 */
}
(2)等高卡片组
.card-group {
display: flex;
align-items: stretch; /* 关键设置 */
}
.card {
flex: 1;
/* 无需设置高度 */
}
高频面试题
(1)justify-content: space-between 最后一行左对齐怎么实现?
.grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
/* 添加占位元素 */
.grid::after {
content: "";
flex: auto; /* 或固定宽度 */
}
(2)如何让 flex 项目在交叉方向上溢出容器?
.container {
display: flex;
align-items: flex-start; /* 关键设置 */
overflow: auto;
}
(3)flex 实现两栏布局,右侧内容溢出时出现滚动条?
.layout {
display: flex;
height: 100vh;
}
.sidebar { flex: 0 0 200px; }
.main {
flex: 1;
overflow: auto;
}
2.3 Grid 网格布局(grid-template、grid-area、fr 单位)
核心概念
grid 布局属于二维布局模型:同时控制行和列的排布,与 flexbox (一维)形成互补
.container {
display: grid; /* 开启网格布局 */
}
Grid 容器与项目
- Grid 容器:设置 display: grid 或 display: inline-grid 的元素
- Grid 项目:Grid 容器的直接子元素
网格线(Grid Lines)
- 划分网格的垂直线和水平线
- 垂直线定义列,水平线定义行
- 从1开始编号(也可以从-1反向计数)
网格轨道(Grid Track)
- 两条相邻网格线之间的空间
- 行轨道(Row Track):两条水平线之间的空间
- 列轨道(Column Track):两条垂直线之间的空间
网格单元格(Grid Cell)
- 四条网格线包围的最小单位区域
- 行和列的交叉区域
网格区域(Grid Area)
- 一个或多个单元格组成的矩形区域
- 通过 grid-template-areas 定义命名区域
Grid 容器属性
显式网格定义
grid-template-columns / grid-template-rows
定义列和行的尺寸
.container {
grid-template-columns: 100px 200px auto;
grid-template-rows: 50px 100px;
}
常用单位:
- 固定单位:px
- 弹性单位:fr (fraction)
- 自动尺寸:auto
- 内容适应:min-content, max-content
- 最小最大值:minmax(200px, 1fr)
示例:
.container {
grid-template-columns: 1fr 2fr 1fr; /* 三列,比例1:2:1 */
grid-template-rows: minmax(100px, auto) 200px;
}
grid-template-areas
定义网格区域的命名布局
.container {
grid-template-areas:
"header header header"
"sidebar content content"
"footer footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }
隐式网格控制
grid-auto-columns / grid-auto-rows
定义隐式创建的轨道尺寸
.container {
grid-auto-rows: 100px; /* 自动创建的行高度 */
}
grid-auto-flow
控制自动放置算法
.container {
grid-auto-flow: row | column | row dense | column dense;
}
间距控制
gap (grid-gap)
定义行和列之间的间距
.container {
gap: 20px; /* 行列间距相同 */
gap: 10px 20px; /* 行间距 列间距 */
/* 旧版语法 */
grid-row-gap: 10px;
grid-column-gap: 20px;
}
对齐方式
justify-items / align-items
控制单元格内项目的对齐方式
.container {
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
}
justify-content / align-content
控制整个网格在容器内的对齐方式
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
Grid 项目属性
项目定位
grid-column / grid-row
定义项目占据的网格区域
.item {
grid-column: 1 / 3; /* 从第1到第3列线 */
grid-row: 1; /* 只占据第1行 */
/* 简写 */
grid-column: 2 / span 2; /* 从第2列开始,跨越2列 */
grid-row: span 2; /* 跨越2行 */
}
grid-area
为项目指定命名区域或位置
.item {
/* 方式1:使用命名区域 */
grid-area: header;
/* 方式2:定位 */
grid-area: 1 / 1 / 3 / 3; /* row-start / column-start / row-end / column-end */
}
项目对齐
justify-self / align-self
控制单个项目的对齐方式
.item {
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
}
grid-template 系列属性详解
grid-template-columns/rows
- 作用:定义显示网格的列/行尺寸
.container { display: grid; /* 开启网格布局 */ grid-template-columns: 200px 1fr; /* 两列:固定+弹性 */ grid-template-rows: 80px auto 60px; /* 三行 */ gap: 16px; /* 网格间隙 */ }
grid-template-areas
- 作用:可视化布局声明
.dashboard { grid-template-areas: "header header header" "sidebar content ." "footer footer footer"; } .header { grid-area: header; } /* 其他区域同理 */ - 规则:相同命名区域必须形成矩形;点号(.)表示空白区域
复合写法 grid-template
/* 行 / 列 / 区域 */
grid-template:
"head head" 80px
"nav main" 1fr
/ 200px 1fr;
grid-area 详解
基础定义
grid-area 是 CSS Grid 布局中用于精确控制网格项位置的核心属性,是以下属性的复合写法:
grid-row-start / grid-column-start / grid-row-end / grid-column-end
四大核心功能
(1)作为 grid-template-areas 的命名引用
.container {
grid-template-areas:
"header header"
"sidebar main";
}
.header { grid-area: header; } /* 自动填充对应区域 */
.sidebar { grid-area: sidebar; }
(2)作为定位简写(行开始/列开始/行结束/列结束)
/*3 行 3 列共 9 格*/
.container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 列 */
grid-template-rows: repeat(3, 100px); /* 3 行 */
}
/*第 2 行第 1 列开始,第 4 行第 3 列结束,占用第2-3行,第1-2列*/
.item {
grid-area: 2 / 1 / 4 / 3;
}
(3)配合命名线使用
.container {
grid-template-columns: [main-start] 1fr [content-start] 1fr [main-end];
}
.item {
grid-area: 1 / content-start / 3 / main-end;
}
(4)自适应布局案例
@media (max-width: 768px) {
.app {
grid-template-areas:
"header"
"content"
"sidebar";
}
}
fr 单位 - 网格专属空间分配
核心特性
- 按比例分配容器剩余可用空间,与 Flex 的 flex-grow 类似但计算时机不同
- 与
minmax()组合实现弹性限制grid-template-columns: 300px minmax(0, 2fr) 1fr;
计算规则
grid-template-columns: 1fr 2fr 100px;
- 总宽度 = 容器宽度 - 固定列宽(100px)- 列间距(gap)
- 剩余空间按 1:2 比例分配
与百分比的区别
| 特性 | fr | % |
|---|---|---|
| 计算基准 | 剩余空间 | 父容器总空间 |
| 是否受网格间隙(gap)影响 | 分配前扣除gap | 包含gap |
| 组合弹性 | 可与固定宽度混合 | 需配合calc |
高频面试问题
(1)grid-area 如何实现跨行跨列
/* 跨3行2列 */
.item {
grid-area: 2 / 1 / span 3 / span 2;
}
(2)同名 grid-area 的项目会发生什么
- 根据 DOM 顺序层叠(后者覆盖前者),可通过 z-index 控制层级
(3)如何使用 grid-area 实现圣杯布局
.container {
grid-template-areas:
"header header"
"sidebar main";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
兼容性
- 所有现代浏览器都支持
- 可以使用
@supports检测@supports (display: grid) { .item { grid-area: main; } }
2.4 多列布局(column-count、column-gap)
多列布局专为文本内容的分栏展示设计,适合新闻阅读、文档排版等场景
核心属性
column-count - 分栏数量控制
- 作用:指定内容分为多少列
- 取值:
.container { column-count: 3; /* 固定3栏 */ }- auto(默认):由其他属性(如column-width)决定列数
- 整数:强制分栏数量(内容不足时会留空)
column-gap - 栏间间距
- 作用:控制列与列之间的间隙
- 语法:
.container { column-gap: 2em; /* 相对单位 */ column-gap: 24px; /* 固定像素 */ column-gap: normal; /* 浏览器默认值(通常1em) */ } - 与Grid/Flex的gap区别:多列布局的gap仅支持单值(不支持行列分别设置)
完整属性体系
| 属性 | 作用 | 示例值 |
|---|---|---|
| column-width | 每列理想宽度(实际可能调整) | 200px / auto |
| column-count | 最大分栏数 | 3 / auto |
| column-gap | 栏间间距 | 1em / 20px |
| column-rule | 栏间分隔线(类似border) | 1px solid #ddd |
| column-fill | 内容填充方式 | auto / balance |
| column-span | 元素跨列(仅all/none) | all(标题跨所有列) |
2.5 响应式布局(@media 查询、移动优先策略)
响应式核心机制:@media 查询
作用:根据设备特性(宽度、分辨率、方向等)应用不同的CSS规则
基础语法结构
@media [媒体类型] [and] (媒体特征) {
/* 条件满足时应用的CSS */
}
关键媒体特征
| 特征 | 应用场景 | 示例值 |
|---|---|---|
| min-width / max-width | 视口宽度断点 | (min-width: 768px) |
| orientation | 设备方向 | (orientation: portrait) |
| resolution | 屏幕分辨率 | (min-resolution: 2dppx) |
| hover | 输入设备是否支持悬停 | (hover: hover) |
| prefers-color-scheme | 系统深色模式 | (prefers-color-scheme: dark) |
复合条件查询
/* 平板横屏且最小宽度1024px */
@media screen and (min-width: 1024px) and (orientation: landscape) {
.sidebar { display: block; }
}
移动优先(mobile-first)策略
核心理念
先为移动设备编写基础样式,再通过 min-width 逐步增强大屏体验
代码实现范式
/* 基础样式(移动端) */
.container {
padding: 12px;
font-size: 14px;
}
/* 平板适配(≥768px) */
@media (min-width: 768px) {
.container {
padding: 20px;
font-size: 16px;
}
}
/* 桌面端适配(≥1200px) */
@media (min-width: 1200px) {
.container {
max-width: 1140px;
margin: 0 auto;
}
}
第三章:CSS 视觉与动画
3.1 背景与边框(background、border-radius、box-shadow)
背景 - background 复合属性
现代 CSS 背景已发展为包含 8 个子属性的强大系统
分层背景(支持多背景图)
.hero {
background:
linear-gradient(rgba(0,0,0,0.3), transparent),
url('hero-bg.jpg') center/cover no-repeat,
#f5f5f5; /* 兜底颜色 */
}
- 层叠顺序:先声明的背景在上层
关键子属性详解
| 属性 | 作用 | 示例值 |
|---|---|---|
| background-image | 设置背景图像/渐变 | url(‘img.png’), linear-gradient(to right, red, blue) |
| background-size | 控制尺寸(需配合position) | cover/contain/100px 50px |
| background-position | 定位起始点 | center/right |
| background-repeat | 重复行为 | no-repeat/space/round |
| background-origin | 定位基准(与border/padding的关系) | border-box/content-box |
| background-clip | 绘制区域 | text(文字镂空效果) |
| background-attachment | 滚动行为 | fixed(视口固定背景) |
| background-blend-mode | 混合模式 | multiply/screen |
性能优化技巧
(1)雪碧图(sprite)自动化
.icon {
background: url('sprite.png') no-repeat;
background-position: -120px -80px; /* 通过工具自动计算 */
}
(2)WebP 格式优先
.banner {
background-image: url('image.webp');
background-image: image-set('image.webp' type('image/webp'), 'image.jpg' type('image/jpeg'));
}
border-radius 高级技巧
椭圆与复杂形状
.btn {
/* 水平半径 / 垂直半径 */
border-radius: 50% 20% 30% 40% / 60% 30% 70% 40%;
}
- 8值语法:分别控制四个角的x/y轴半径
圆角头像
.avatar {
border-radius: 50%;
aspect-ratio: 1; /* 确保宽高相等 */
}
胶囊按钮
.pill-button {
border-radius: 9999px; /* 超大值实现 */
/* 或 */
border-radius: calc(1em + 4px); /* 动态适应字体 */
}
隐藏陷阱
- 子元素溢出:父元素设置overflow: hidden
- 背景剪裁:配合background-clip: border-box
box-shadow 立体感打造
可叠加多层的阴影系统
完整语法
box-shadow: [inset] x-offset y-offset blur spread color;
参数详解:
- inset:内阴影
- spread:阴影扩展(正数放大/负数收缩)
- 支持 RGBA 透明度控制
高级应用
(1)多层阴影
.card {
box-shadow:
0 2px 4px rgba(0,0,0,0.1),
0 8px 16px rgba(0,0,0,0.1); /* 立体层次 */
}
(2)霓虹效果
.neon {
box-shadow: 0 0 10px #0ff, 0 0 20px #0ff;
}
(3)边框替代方案(不占空间)
.border-alternative {
box-shadow: 0 0 0 2px #f00; /* 2px纯色外框 */
}
组合实战案例
(1)玻璃拟态
.glass {
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10px);
border-radius: 12px;
border: 1px solid rgba(255,255,255,0.1);
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
(2)文档卡片悬浮
.doc-card {
transition: box-shadow 0.2s;
}
.doc-card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
transform: translateY(-2px);
}
高频面试问题
Q:如何实现 1px 细线边框
.thin-border {
box-shadow: 0 0 0 0.5px #000; /* 高清屏解决方案 */
}
Q:background-clip: text 的兼容性如何?
- 需配合-webkit-text-fill-color: transparent
- 备用方案:SVG文本背景
3.2 渐变与滤镜(linear-gradient、backdrop-filter)
CSS渐变 - 从基础到三维质感
CSS 渐变可替代图片实现高性能视觉效果
linear-gradient 线性渐变
background: linear-gradient(
[方向或角度],
color-stop1,
color-stop2,
...
);
方向控制
/* 关键词 */ to right, to bottom right /* 角度 */ 45deg, 0.25turn色标高级控制
background: linear-gradient( to right, #ff0000 0%, /* 纯红色起点 */ #ff0000 20%, /* 保持纯红到20% */ #0000ff 80%, /* 过渡到蓝色 */ #0000ff 100% /* 纯蓝色终点 */ )案例:微信小程序按钮
.btn-primary { background: linear-gradient(90deg, #07C160 0%, #09A855 100%); }
radial-gradient 径向渐变
background: radial-gradient(
[形状 at 位置],
color-stop1,
color-stop2
);
形状控制
circle at center, ellipse at 20% 30%案例:logo 效果
.logo { background: radial-gradient( circle at 30% 40%, #ff0037 0%, transparent 60% ); }
conic-gradient 锥形渐变
/* 饼图/色轮实现 */
background: conic-gradient(
red 0deg 90deg,
green 90deg 180deg,
blue 180deg 270deg,
yellow 270deg 360deg
);
CSS滤镜 - 视觉魔法
滤镜可对元素本身或背景进行实时图像处理。
filter 常用函数
| 滤镜函数 | 效果 | 示例值 |
|---|---|---|
| blur() | 高斯模糊 | blur(5px) |
| brightness() | 明暗度调整 | brightness(1.2) |
| contrast() | 对比度调整 | contrast(150%) |
| drop-shadow() | 投影(优于box-shadow) | drop-shadow(2px 2px 4px #000) |
| hue-rotate() | 色相旋转 | hue-rotate(90deg) |
| grayscale() | 灰度化 | grayscale(100%) |
抖音风格特效:
.video-filter {
filter: contrast(1.2) brightness(1.1) hue-rotate(15deg);
}
backdrop-filter 背景滤镜
仅处理元素背后的内容(需配合半透明背景):
.modal {
background: rgba(255,255,255,0.3);
backdrop-filter: blur(10px) saturate(180%);
}
- 适用场景:
- 毛玻璃效果
- 弹窗背景虚化
- 兼容性方案:
@supports not (backdrop-filter: blur(10px)) { .modal { background: rgba(255,255,255,0.9); /* 降级处理 */ } }
高级组合技巧
渐变 + 滤镜实现 3D 按钮
.btn-3d {
background: linear-gradient(
145deg,
#ffffff 0%,
#c8c8c8 50%,
#ffffff 100%
);
filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
&:active {
filter: brightness(0.95) drop-shadow(0 2px 4px rgba(0,0,0,0.1));
}
}
3.3 过渡与动画(transition、@keyframes、animation)
CSS过渡(transition)
实现属性变化的平滑过渡(适合简单的交互效果)
核心属性
.element {
transition:
[property] [duration] [timing-function] [delay];
}
- 参数详解:
- property:要过渡的属性(如 all、opacity)
- duration:持续时间(0.3s 或 300ms)
- timing-function:速度曲线(ease-in-out)
- delay:延迟时间(可选)
贝塞尔曲线进阶
/* 自定义缓动曲线(阿里Ant Motion规范) */
transition: transform 0.4s cubic-bezier(0.68, -0.6, 0.32, 1.6);
- 常用预设:
- ease-in-out:平滑加减速
- linear:均速
- steps(4):分步动画
实践
(1)硬件加速
.card {
transition: transform 0.3s;
will-change: transform; /* 预提示浏览器 */
}
.card:hover {
transform: translateY(-5px);
}
关键帧动画(@keyframes)
定义复杂的多阶段动画,适合需要精确控制的场景。
基本语法
@keyframes slideIn {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
/* 或百分比控制 */
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
动画属性(animation)
.element {
animation:
[name] [duration] [timing-function] [delay]
[iteration-count] [direction] [fill-mode];
}
- 参数扩展:
- iteration-count:播放次数(infinite表示无限循环)
- direction:alternate(往返播放)
- fill-mode:forwards(保留最后一帧)
视频加载动画案例
@keyframes dotPulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.5); opacity: 0.7; }
}
.loading-dot {
animation: dotPulse 1.5s infinite ease-in-out;
}
.loading-dot:nth-child(2) {
animation-delay: 0.2s;
}
.loading-dot:nth-child(3) {
animation-delay: 0.4s;
}
可动画属性性能排行
| 属性类型 | 性能影响 | 推荐场景 |
|---|---|---|
| transform | 最优 | 位移/旋转/缩放 |
| opacity | 优 | 淡入淡出 |
| color | 中 | 非高频变化 |
| width/height | 差 | 避免在动画中使用 |
3.4 变形(transform:rotate、scale、translate)
transform 核心功能总览
在不影响文档流的前提下,对元素进行视觉变形,包含四大类操作:
| 变形类型 | 函数示例 | 变形基准点(默认) |
|---|---|---|
| 旋转(Rotate) | rotate(45deg) | 元素中心 |
| 缩放(Scale) | scale(1.2) | 元素中心 |
| 位移(Translate) | translate(20px, 50px) | 元素自身位置 |
| 倾斜(Skew) | skew(15deg) | 元素中心 |
二维变形详解
(1)旋转 - rotate
.transform-rotate {
transform: rotate(30deg); /* 顺时针旋转 */
}
进阶控制:
- rotateX(45deg):绕X轴旋转(3D效果)
- rotateY(180deg):绕Y轴旋转(镜面翻转)
- rotateZ(90deg):等同于rotate()(Z轴垂直于屏幕)
(2)缩放 - scale
.transform-scale {
transform: scale(1.5); /* 整体放大1.5倍 */
/* 或分开控制 */
transform: scaleX(1.2) scaleY(0.8);
}
陷阱:
- 缩放不影响布局(相邻元素不会自动避让)
- 可能引发文字模糊(需配合transform-origin调整基准点)
(3)位移 - translate
.transform-translate {
transform: translate(50%, -20px); /* 水平50% 垂直-20px */
}
百分比计算基准:
- translateX(50%):基于元素自身宽度
- left: 50%:基于父容器宽度
(4)倾斜 - skew
.transform-skew {
transform: skew(15deg, -10deg); /* X轴15° Y轴-10° */
}
应用场景:创建平行四边形按钮、斜切 banner 效果
变形属性性能排序
| 变形类型 | 性能影响 | 推荐场景 |
|---|---|---|
| translate | 最优 | 位移动画 |
| scale | 优 | 缩放效果 |
| rotate | 中 | 避免高频旋转 |
| filter+变形 | 差 | 谨慎组合使用 |
3.5 3D 变换(perspective、transform-style)
3D 变换核心概念
CSS 3D 变换通过模拟三维坐标系(X/Y/Z 轴)实现立体效果,关键依赖两个属性:
| 属性 | 作用 | 默认值 |
|---|---|---|
| perspective | 定义观察者与3D空间的视觉距离 | none |
| transform-style | 决定子元素是否保留3D变换特性 | flat |
perspective 景深控制
原理:模拟人眼到3D物体的距离,数值越小透视效果越强。
基础用法
.container {
perspective: 1000px; /* 推荐值:500-2000px */
}
.card {
transform: rotateY(45deg); /* 此时会有3D透视效果 */
}
两种设置方式
(1)场景景深(父元素设置,影响所有子元素)
.scene {
perspective: 1200px;
}
(2)个体景深(元素自身设置,仅影响当前元素)
.card {
transform: perspective(1200px) rotateY(45deg);
}
性能优化
- 避免动态修改perspective(触发重排)
- 移动端建议值≥800px(防止过度变形)
transform-style 3D 空间继承
控制子元素是否在独立 3D 空间中渲染:
| 值 | 效果 | 应用场景 |
|---|---|---|
| flat | 子元素被压扁到2D平面(默认) | 普通变形 |
| preserve-3d | 子元素保持3D空间关系 | 复杂3D组合体 |
典型案例:立方体制作
<div class="cube">
<div class="face front">Front</div>
<div class="face back">Back</div>
<!-- 其他4个面 -->
</div>
.cube {
transform-style: preserve-3d;
transform: rotateX(15deg) rotateY(30deg);
}
.face {
position: absolute;
width: 200px;
height: 200px;
}
.front { transform: translateZ(100px); }
.back { transform: rotateY(180deg) translateZ(100px); }
/* 其他面类似 */
3D 变换函数进阶
三维位移
| 函数 | 轴方向 | 示例 |
|---|---|---|
| translateZ(z) | 垂直于屏幕(远近) | translateZ(50px) |
| translate3d(x,y,z) | 三维复合位移 | translate3d(0, 10%, 20px) |
三维旋转
| 函数 | 旋转轴 | 示例 |
|---|---|---|
| rotateX(angle) | 水平轴(上下翻转) | rotateX(45deg) |
| rotateY(angle) | 垂直轴(左右翻转) | rotateY(180deg) |
| rotate3d(x,y,z,a) | 自定义旋转轴 | rotate3d(1,1,0,45deg) |
性能优化
(1)复合动画策略
/* 错误示范:连续修改不同属性 */
@keyframes bad-animation {
0% { transform: rotateX(0); }
50% { transform: translateY(100px); }
100% { transform: rotateX(180deg); }
}
/* 正确做法:保持相同变换属性 */
@keyframes good-animation {
0% { transform: rotateX(0) translateY(0); }
100% { transform: rotateX(180deg) translateY(100px); }
}
第四章:CSS 高级特性
4.1 变量(CSS Custom Properties)
基础概念与语法
CSS 变量(又成自定义属性)是 CSS 的动态存储机制,具有级联继承特性
定义与使用
/* 定义变量(带--前缀) */
:root {
--primary-color: #4285f4;
--spacing-unit: 8px;
}
/* 使用变量(通过var()函数) */
.button {
background-color: var(--primary-color);
padding: var(--spacing-unit) calc(var(--spacing-unit) * 2);
}
作用域规则
- 全局变量:定义在
:root选择器内 - 局部变量:定义在特定选择器内
.card { --card-shadow: 0 2px 8px rgba(0,0,0,0.1); /* 仅.card内有效 */ }
核心特性解析
动态计算能力
:root {
--base-size: 16px;
--h1-size: calc(var(--base-size) * 2);
}
h1 { font-size: var(--h1-size); }
回退机制
.element {
color: var(--undefined-var, #f00); /* 变量不存在时使用#f00 */
}
类型灵活性
:root {
--theme-gradient: linear-gradient(to right, #ff8a00, #da1b60);
--mobile-breakpoint: 768px;
--transition-config: 0.3s ease-in-out;
}
应用场景示例:主题切换
/* 定义主题变量 */
:root {
--bg-color: #fff;
--text-color: #333;
}
/* 暗色模式 */
[data-theme="dark"] {
--bg-color: #222;
--text-color: #f0f0f0;
}
body {
background: var(--bg-color);
color: var(--text-color);
transition: background 0.3s, color 0.3s;
}
// JS切换主题
document.documentElement.setAttribute('data-theme', 'dark');
4.2 伪类与伪元素(:hover、::before、::selection)
核心概念区分
| 特性 | 伪类(Pseudo-class) | 伪元素(Pseudo-element) |
|---|---|---|
| 语法 | 单冒号(:hover) | 双冒号(::before) |
| 作用对象 | 选择元素的特定状态 | 创建元素的虚拟子元素 |
| DOM表现 | 不创建新节点 | 创建文档树外的抽象元素 |
| 典型应用 | 交互状态(如:hover) | 装饰性内容(如::before) |
伪类详解(状态选择器)
动态交互伪类
| 伪类 | 触发条件 | 示例 |
|---|---|---|
| :hover | 鼠标悬停 | a:hover { color: red } |
| :active | 元素被激活(如点击按下) | button:active { transform: scale(0.98) } |
| :focus | 获得焦点(表单/可聚焦元素) | input:focus { border-color: blue } |
| :focus-visible | 键盘聚焦时生效 | 兼容outline无障碍设计 |
结构伪类
| 伪类 | 匹配规则 | 示例 |
|---|---|---|
| :first-child | 父元素的首个子元素 | li:first-child { font-weight: bold } |
| :nth-child(n) | 第n个子元素(支持公式) | tr:nth-child(2n+1) { background: #f5f5f5 } |
| :not(selector) | 反向选择器 | div:not(.hidden) { display: block } |
伪元素详解(虚拟内容生成)
核心伪元素
| 伪元素 | 作用 | 示例 |
|---|---|---|
| ::before | 在元素内容前插入 | .alert::before { content: “!” } |
| ::after | 在元素内容后插入 | 清除浮动/工具提示 |
| ::first-line | 选中首行文本 | p::first-line { font-size: 1.2em } |
| ::selection | 用户选中的文本 | ::selection { background: gold } |
关键技术要点
- content 属性必须设置(空字符串也要设置)
- 伪元素不接受 DOM 事件
- 默认位于主元素下层,可通过
z-index调整
组合使用技巧示例:纯 CSS 实现工具提示
[data-tooltip] {
position: relative;
}
[data-tooltip]:hover::after {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 4px 8px;
border-radius: 4px;
white-space: nowrap;
}
4.3 BFC(块级格式化上下文)与 IFC(行内格式化上下文)
核心概念对比
| 特性 | BFC(Block Formatting Context) | IFC(Inline Formatting Context) |
|---|---|---|
| 布局方向 | 垂直排列 | 水平排列 |
| 元素类型 | 块级元素参与 | 行内级元素参与 |
| 宽度计算 | 撑满父容器(除非指定宽度) | 由内容决定 |
| 边距处理 | 垂直边距可能合并 | 水平边距有效,垂直边距不影响行高 |
| 经典应用 | 清除浮动/防止边距合并 | 文字对齐/行内元素排列 |
BFC 详解(块级格式化上下文)
触发条件
满足任意一条即可:
- 根元素(
<html>) - 浮动元素(float不为none)
- 绝对定位元素(position为absolute或fixed)
- display为inline-block、table-cell、table-caption、flex、inline-flex、grid、inline-grid等
- overflow不为visible的块元素(hidden、auto、scroll)
- 弹性项目(display: flex或inline-flex的直接子元素)
- 网格项目(display: grid或inline-grid的直接子元素)
- 多列容器(column-count或column-width不为auto,且column-count:1也属于)
- contain值为layout、content或paint的元素
/* 任一条件即可触发 */ .container { display: flow-root; /* 最纯净的BFC */ overflow: hidden; /* 非visible */ float: left/right; position: absolute/fixed; display: inline-block/table-cell/flex/grid; }
核心特性
- 独立的渲染区域
- BFC 内部的元素不会影响外部元素
- 外部元素也不会影响 BFC 内部
- 垂直方向排列
- 内部块级盒子垂直排列(一个接一个)
- 边距折叠解决
- 同一个 BFC 内相邻块级元素的垂直外边距会折叠
- 不同 BFC 之间不会发生边距折叠
- 清除浮动
- BFC 会计算内部所有浮动元素的高度
- 解决父元素高度塌陷问题
- 避免环绕
- BFC 区域不会与浮动元素重叠
示例
<div class="bfc-container"> <!-- 触发BFC -->
<div style="margin: 20px"></div>
</div>
<!-- 外部元素不再发生边距合并 -->
.clearfix::after {
content: "";
display: table; /* 创建BFC */
clear: both;
}
IFC 详解(行内格式化上下文)
触发条件
/* 默认由行内级元素自动创建 */
.inline-container {
display: inline/inline-block/inline-flex;
font-size: 16px; /* 影响line-height计算 */
}
核心特性
- 行框(line box)概念:每行文本生成一个矩形行框,高度由
line-height决定 - 垂直对齐控制:
vertical-align: middle相对行框对齐 - 空白符处理:连续多个空白符合并为单个空格,换行符转为空格
布局场景对比
浮动元素处理
| 方案 | BFC | IFC |
|---|---|---|
| 效果 | 包含浮动,阻止文字环绕 | 无法包含浮动,允许文字环绕 |
| 代码 | overflow: hidden | 默认行为 |
垂直对齐
| 方案 | BFC | IFC |
|---|---|---|
| 控制 | 通过margin/padding调整 | 通过 vertical-align 精确控制 |
| 精度 | 整块调整 | 像素级对齐 |
高频面试
Q:BFC 如何解决边距合并
创建独立布局环境,阻断与外部元素的边距折叠
Q:IFC 中 vertical-align 失效的原因?
- 检查元素是否真是行内级(display 值)
- 确认父元素有有效
line-height
Q:BFC与display: flow-root的区别?
flow-root是专为BFC设计的新值,无副作用(不触发滚动条/裁剪)
4.4 CSS 性能优化(will-change、contain、GPU 加速)
will-change:性能优化预告系统
- 作用:预先告知浏览器元素可能发生的变化,让浏览器提前优化
正确使用姿势
.optimize {
will-change: transform, opacity; /* 明确指定要变化的属性 */
transition: transform 0.3s, opacity 0.3s;
}
.optimize:hover {
transform: scale(1.1);
opacity: 0.8;
}
最佳实践
(1)适用场景
- 复杂动画元素
- 即将发生变化的滚动区域
(2)避坑指南
- 不要过度使用(每个页面 <= 5 个)
- 动画结束后移除(通过 js)
element.addEventListener('animationend', () => { element.style.willChange = 'auto'; });
contain:布局隔离核武器
- 作用:限制浏览器重绘/回流范围,类似于 React 的 shouldComponentUpdate
关键属性值
| 值 | 优化方向 | 适用场景 |
|---|---|---|
| layout | 隔离布局计算 | 频繁移动的独立组件 |
| paint | 限制绘制区域 | 弹窗/下拉菜单 |
| size | 忽略子元素尺寸影响 | 固定尺寸容器 |
| strict | 全部隔离(性能最强) | 复杂动画组件 |
.product-card {
contain: strict; /* 卡片内部变化不影响外部布局 */
}
GPU加速:复合层优化策略
GPU 加速的本质
浏览器将特定元素的渲染工作从 CPU 转移到 GPU 处理,利用图形硬件的并行计算能力。这种优化通过创建独立的复合层实现。
GPU 加速的工作原理
graph TD
A[浏览器解析CSS] --> B{检测GPU加速属性}
B -->|是| C[创建独立图层]
B -->|否| D[使用CPU渲染]
C --> E[上传图层到GPU]
E --> F[GPU处理变换/动画]
F --> G[图层合成]
G --> H[最终渲染]
- 图层创建:当浏览器检测到 GPU 加速属性时,会将元素提升到独立的合成图层
- 纹理上传:图层内容作为纹理上传到 GPU 显存
- GPU 处理:GPU 执行变换、动画和合成操作
- 图层合成:浏览器将多个图层合成为最终图像
核心触发条件(chromium 内核为例)
(1)3D 变换属性
.transform-3d {
transform: translate3d(0, 0, 0); /* 最常用hack */
transform: rotateY(10deg); /* 任意3D函数 */
transform: perspective(500px); /* 景深设置 */
}
作用机制:强制浏览器将元素视为 3D 空间对象,自动触发层提升
(2)透明度动画 + 硬件加速
.fade-in {
will-change: opacity; /* 预先声明 */
transition: opacity 0.3s;
}
特殊场景:仅当与 transform 或 filter 组合时 GPU 加速才稳定生效
(3)滤镜效果
.filter-gpu {
filter: blur(5px); /* 高斯模糊 */
backdrop-filter: saturate(180%); /* 背景滤镜 */
}
性能警告:filter 属性可能引发重绘(需配合 will-change 优化)
(4)强制层提升属性
| 属性 | 效果 | 推荐指数 |
|---|---|---|
| will-change: transform | 最标准做法 | ★★★★★ |
| backface-visibility: hidden | 旧版兼容方案 | ★★★☆☆ |
| perspective: 1000px | 创建3D上下文 | ★★★★☆ |
优化原理
- 将元素提升到独立复合层
- 避免与主线程的布局计算相互阻塞
浏览器渲染管线分析
graph TD
A[Style Recalc] --> B[Layout]
B --> C[Paint]
C --> D[Composite]
D -->|GPU加速| E[Layer Drawing]
关键阶段:
- Composite:浏览器决定哪些元素需要独立图层
- Layer Drawing:GPU实际渲染图层
层创建规则
(1)显式触发条件
- 3D 或透视变换(perspective、transform3d)
- 视频/canvas/webGL 等嵌入式内容
- 对 opacity/transform 等做 CSS 动画
- 具有 filter 或 mask 属性的元素
(2)隐式触发条件
- 重叠元素(z-index 较高可能被提升)
- 滚动容器内的固定位置元素
- 使用 position:fixed 的元素
注意事项
- 内存消耗:每个复合层约占用 1MB 内存
- 层爆炸:避免超过 100 个复合层(chromium 限制)
/* 错误:过度创建复合层 */ .card { transform: translateZ(0); box-shadow: 0 0 10px rgba(0,0,0,0.5); } /* 正确:合并优化 */ .optimized-card { will-change: transform, box-shadow; }
总结
- 硬件(GPU)加速的关键是使用GPU友好的CSS属性:
- 当使用transform属性时,无论是CSS还是JavaScript实现的动画,都能达到60FPS的流畅效果;而使用传统CSS属性(如width/height)实现的动画则性能明显下降
- GPU友好的CSS属性:
- transform(translate, scale, rotate等)
- opacity
- filter(部分效果)
- will-change(提前声明优化)
组合优化方案
(1)虚拟列表优化
.list-item {
contain: strict;
will-change: transform;
position: absolute;
transform: translateY(var(--pos));
}
(2)高性能动画三件套
.smooth-animation {
transform: translateZ(0);
will-change: transform;
contain: strict;
/* 只使用opacity/transform变化 */
transition: transform 0.3s cubic-bezier(0.2, 0, 0.1, 1);
}
(3)谷歌Chrome团队建议
- 对position: fixed元素始终使用will-change: transform
- 滚动容器设置overflow: auto而非scroll(避免常驻层)
4.5 现代 CSS 特性(aspect-ratio、gap、scroll-snap)
aspect-ratio:实现元素宽高比的终极解决方案
基础用法
.media-box {
aspect-ratio: 16/9; /* 宽度:高度=16:9 */
width: 100%; /* 宽度优先,高度自动计算 */
}
计算规则
高度 = 宽度 x (分母/分子)
特殊场景处理
| 场景 | 解决方案 |
|---|---|
| 同时设置宽高 | aspect-ratio会覆盖height |
| 最小/最大高度限制 | 使用min-height/max-height |
| 替换元素(如img) | 优先使用元素原生宽高比 |
gap:取代 margin 的智能间距系统
多布局通用语法
.grid-layout {
display: grid;
gap: 20px; /* 行列间距统一 */
}
.flex-layout {
display: flex;
gap: 10px 15px; /* 行间距 列间距 */
}
浏览器兼容策略
.grid {
/* 旧版Grid支持 */
grid-gap: 20px;
/* 标准写法 */
gap: 20px;
}
scroll-snap:精准控制滚动
完整属性体系
| 属性 | 作用 | 示例值 |
|---|---|---|
| scroll-snap-type | 容器滚动捕捉类型 | x mandatory |
| scroll-snap-align | 子项对齐位置 | start center end |
| scroll-snap-stop | 是否强制停留 | normal always |
| scroll-padding | 滚动视窗内边距 | 20px |
横向轮播图实现
<div class="carousel">
<div class="slide">1</div>
<div class="slide">2</div>
</div>
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-padding: 20px; /* 避免内容被遮挡 */
}
.slide {
scroll-snap-align: start;
flex: 0 0 80vw; /* 每屏显示一个 */
}
浏览器支持与降级方案
特性检测策略
// 检测aspect-ratio支持
const supportsAspectRatio = CSS.supports('aspect-ratio: 1/1');
// 检测gap支持(Flexbox版本)
const supportsFlexGap = CSS.supports('gap: 10px', 'display: flex');
渐进增强写法
.container {
/* 旧版Flex布局间距 */
margin: -5px;
}
.item {
margin: 5px;
}
@supports (gap: 10px) {
.container {
gap: 10px;
margin: 0;
}
.item {
margin: 0;
}
}
第五章:CSS 工程化与架构
5.1 CSS 预处理(Sass/Less 变量、嵌套、Mixin)
5.2 CSS 模块化(BEM、CSS Modules、CSS-in-JS)
5.3 PostCSS 与 Autoprefixer
5.4 原子化 CSS(Tailwind CSS、UnoCSS)
5.5 设计系统与 CSS 架构(主题切换、变量管理)
第六章:CSS 面试高频考点
6.1 CSS 优先级与权重深度考察
基础概念考察
Q:请解释 CSS 选择器的权重计算规则?
权重由四个分量组成,按 (a, b, c, d) 计算:
- a:行内样式
- b:ID选择器数量(如 #header)
- c:类/伪类/属性选择器数量(如 .class, :hover, [type=”text”])
- d:元素/伪元素选择器数量(如 div, ::before)
| 选择器类型 | 权重值 | 示例 |
|---|---|---|
| 行内样式 | 1,0,0,0 | <div style="..."> |
| ID选择器 | 0,1,0,0 | #header |
| 类/属性/伪类选择器 | 0,0,1,0 | .class, [type], :hover |
| 元素/伪元素选择器 | 0,0,0,1 | div, ::before |
示例:
#nav .item:hover::before {} /* 权重:0,1,2,1 */
!important的作用:
!important不是权重值的一部分,而是一个独立的标志,它会改变样式声明的优先级顺序。- 当出现
!important时,它会覆盖普通声明(无论权重多高),但多个!important之间仍然按照权重规则比较。 - 带有
!important的行内样式(权重:1,0,0,0 + !important) - 带有
!important的外部样式(根据选择器权重,如:0,1,0,0 + !important) - 如果行内样式没有
!important,而其他地方有!important,则行内样式会被覆盖。
注意:
- 继承的样式权重小于给自身设置样式的权重
- 当选择器相同的情况下,行内样式权重 > 内部样式权重 > 外部样式权重
陷阱:!important 的权重真的最高吗?
- 当多个 !important 冲突时,仍需按选择器权重比较
- !important 会破坏样式层叠,应尽量避免
结合非作者样式之后的综合CSS层叠顺序(从高到低)为:
- 用户代理!important(浏览器默认)
- 用户!important
- 作者!important(开发者)
- 作者普通样式
- 用户普通样式
- 用户代理普通样式
权重实战考察
Q:判断以下样式的最终生效颜色?
<div id="box" class="container warning" style="color: yellow">Text</div>
#box { color: red; } /* A */
.container { color: blue; } /* B */
div.warning { color: green; } /* C */
div { color: orange !important; } /* D */
分析过程:
- ABCD 和行内样式的权重分别为:
- A:0,1,0,0
- B:0,0,1,0
- C:0,0,1,1
- D:1,0,0,1
- 行内样式:1,0,0,0
- 对比各权重:D 的权重最高 -> 最终 orange 颜色生效
层叠规则高阶问题
Q:在相同权重下,样式如何决定优先级?
完整层叠顺序
!important声明- 来源优先级(从高到低):
- 用户代理样式(浏览器默认)
- 用户样式表
- 开发者样式表
- 开发者
!important - 用户
!important
- 选择器权重
- 代码顺序(后定义的覆盖先定义)
/* 样式表A */ :root { --color: red; } .box { color: var(--color); } /* 样式表B(后加载) */ :root { --color: blue; }
最终颜色为 blue(变量遵循代码顺序)
CSS 变量与权重考察
Q:CSS自定义属性的权重如何计算?
关键规则:
- 变量本身没有权重,继承所在规则的权重
- 使用 var() 时,最终值权重=变量声明权重 + 使用处选择器权重
:root { --text-color: red; } /* 权重:0,1,0,0 */ #box { --text-color: blue; } /* 权重:0,1,0,0 */ p { color: var(--text-color); } /* 继承变量声明处的权重 */
此时 <div id="box"><p>Text</p></div> 显示蓝色(相同权重下后定义生效)
6.2 居中布局的 N 种方式
水平居中
行内/行内块元素
.parent {
text-align: center; /* 传统方案 */
}
.child {
display: inline-block;
}
块级元素(固定宽度)
.child {
width: 300px;
margin: 0 auto; /* 经典auto margins */
}
flexbox 方案
.parent {
display: flex;
justify-content: center; /* 主轴居中 */
}
grid 方案
.parent {
display: grid;
place-items: center; /* 简写属性 */
}
垂直居中
单行文本
.parent {
height: 100px;
line-height: 100px; /* 行高=容器高度 */
}
表格单元格方式
.parent {
display: table-cell;
vertical-align: middle; /* 垂直居中 */
}
flexbox 方案
.parent {
display: flex;
align-items: center; /* 交叉轴居中 */
}
绝对定位 + 负边距(传统方案)
.child {
position: absolute;
top: 50%;
height: 100px;
margin-top: -50px; /* 高度的一半 */
}
完全居中(水平 + 垂直)
flexbox 终极方案
.parent {
display: flex;
justify-content: center;
align-items: center;
}
grid 终极方案
.parent {
display: grid;
place-content: center; /* 简写属性 */
}
绝对定位 + transform
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 自适应宽高 */
}
绝对定位 + margin auto
.child {
position: absolute;
inset: 0; /* 全方向0 */
margin: auto;
width: fit-content;
height: fit-content;
}
特殊场景方案
视口居中(vw/vh)
.modal {
position: fixed;
top: 50vh;
left: 50vw;
transform: translate(-50%, -50%);
}
多行文本居中
.parent {
display: grid;
}
.child {
margin: auto; /* 神奇的小技巧 */
}
浮动元素居中
.parent::after {
content: "";
display: table;
clear: both;
}
.child {
float: left;
position: relative;
left: 50%;
transform: translateX(-50%);
}
6.3 清除浮动的方法与 BFC 应用
清除浮动的核心方法
经典 clear fix 方案(最可靠)
.clearfix::after {
content: "";
display: block;
clear: both; /* 关键属性 */
}
/* 兼容IE6/7 */
.clearfix {
*zoom: 1;
}
适用场景:所有需要清除浮动的容器
创建 BFC 容器(现代方案)
.container {
overflow: hidden; /* 或 auto/scroll */
display: flow-root; /* 最纯净的BFC */
}
优势:无需额外 HTML 元素
空 div 法(不推荐但常见)
<div class="float-left"></div>
<div style="clear: both;"></div> <!-- 清除浮动 -->
伪元素 + table 布局(兼容性最佳)
.clearfix::after {
content: "";
display: table;
clear: both;
}
BFC 在清除浮动上的应用
核心原理
当元素创建 BFC 时,会形成独立的布局环境,必须包含其内的所有浮动元素,以避免父容器高度塌陷。这是 CSS 规范中明确规定的 BFC 特性之一。
具体实现方法
(1)overflow(最常用)
.container {
overflow: hidden; /* 或 auto/scroll */
/* 触发BFC */
}
特点:
- 兼容性好(IE7+)
- 可能意外裁剪内容或产生滚动条
(2)display: flow-root(现代方案)
.container {
display: flow-root; /* 专为清除浮动设计 */
}
优势:
- 无副作用(不会裁剪内容)
- 语义明确(Chrome58+/Firefox52+/Edge16+)
(3)浮动元素父容器(自清除)
.container {
float: left; /* 自身浮动也创建BFC */
width: 100%; /* 保持宽度 */
}
适用场景:需要兼容 IE6/7 的古老项目
(4)display 表格属性
.container {
display: table; /* 或 inline-table/table-cell */
width: 100%; /* 需要指定宽度 */
}
注意:会改变元素默认显式特性
6.4 响应式设计与移动端适配(REM、Viewport)
如何利用 rem 实现移动端适配
标准答案
// 动态设置根字体大小(推荐1rem=10px比例)
document.documentElement.style.fontSize =
document.documentElement.clientWidth / 7.5 + 'px';
// 设计稿750px时,1rem=100px
配套 CSS
/* 配合PostCSS插件自动转换 */
.btn {
width: 1.6rem; /* 设计稿160px → 1.6rem */
}
追问
- 为什么用 7.5?:设计稿宽度750px ÷ 100(目标rem值) = 7.5
- 如何解决字体闪烁?:添加CSS先设置默认字号
html { font-size: 50px } /* 默认值 */ @media (min-width: 375px){ html { font-size: calc(100vw / 7.5) } }
viewport 进阶
Q:<meta name="viewport">各参数的作用?
<meta name="viewport"
content="width=device-width,
initial-scale=1.0,
maximum-scale=1.0,
user-scalable=no,
viewport-fit=cover">
- width=device-width:视口=设备宽度(避免默认980px缩放)
- initial-scale=1.0:初始缩放比例
- viewport-fit=cover:全面屏适配(iOS专属)
陷阱:为什么 andriod 不需要设置 viewport-fit?
Android系统会自动处理刘海屏,而iOS需要显式声明
如何实现高清屏下的真实 1px 边框?
.border-1px {
position: relative;
}
.border-1px::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1px;
background: #000;
transform: scaleY(0.5);
transform-origin: 0 0;
}
原理:利用 transform 缩放物理像素,避免直接使用 0.5px 的兼容性问题
6.5 CSS 渲染优化(减少重排、重绘)
基础概念考察
Q:解释重排(reflow)和重绘(repaint)的区别
- 重排:几何属性变更(宽/高/位置等)导致的布局重新计算,代价高昂
- 重绘:外观属性变化(背景/颜色等)导致的像素重绘,不涉及布局变化
- 关键差异:重排必定触发重绘,反之不会
Q:哪些CSS属性会触发重排?哪些仅触发重绘?
| 重排触发属性 | 仅重绘属性 |
|---|---|
| width/height | color |
| margin/padding | background |
| display | border-radius |
| font-size | box-shadow |
| 获取布局属性(offsetTop) | visibility: hidden |
深度原理考察
Q:浏览器渲染管线中如何避免布局抖动(Layout Thrashing)?
读写分离原则:
// 错误写法(交替读写导致多次重排)
for(let i=0; i<100; i++) {
el.style.width = i + 'px';
console.log(el.offsetWidth);
}
// 正确写法(批量读写)
let widths = [];
for(let i=0; i<100; i++) {
el.style.width = i + 'px';
widths.push(i);
}
console.log(widths);
Q:如何利用CSS Containment优化渲染性能?
.widget {
contain: strict; /* 最严格的隔离 */
/* 等效于 contain: size layout paint style */
}
- 原理:限制浏览器重排/重绘的影响范围
- 适用场景:复杂动画组件、高频更新的UI模块
Q:请描述从输入URL到页面渲染完成过程中,CSS优化的完整机会点
- 资源加载阶段:
- 关键CSS
- 异步加载非关键CSS(media=”print”)
- 解析阶段:
- 减少@import使用
- 内联首屏关键CSS(Critical CSS)
- 渲染阶段:
- 避免同步布局(Force Synchronous Layout)
- 使用CSS动画代替JS动画
- 交互阶段:
- 防抖处理resize/scroll事件
- 使用passive: true优化触摸事件
6.6 浏览器渲染流程(CSSOM、Critical CSS)
CSSOM 构建过程考察
Q:描述CSSOM树的构建流程及其阻塞特性
- 解析阶段
- 浏览器逐条解析 CSS 规则,生成 CSSOM 树(与 DOM 树并行构建)
@import和<link>会触发同步阻塞(除非显式异步加载)<!-- 阻塞渲染 --> <link rel="stylesheet" href="main.css"> <!-- 异步加载 --> <link rel="stylesheet" href="print.css" media="print" onload="this.media='all'">
- 计算阶段
- 将 CSS 规则转换为样式规则表(Style Rules)
- 遇到 JavaScript 访问 CSSOM 属性时触发同步解析(强制完成 CSSOM 构建)
Q:如何验证 CSSOM 构建阻塞?
// 测试代码(放在<head>中)
console.time('cssom');
getComputedStyle(document.documentElement);
console.timeEnd('cssom');
// 时间差=CSSOM构建耗时
Critical CSS实战方案
Q:首屏优化的Critical CSS提取策略?
工具链:
# 使用Penthouse提取关键CSS
npm install penthouse -g
penthouse http://example.com critical.css
实施步骤:
<!-- 内联关键CSS -->
<style>
.header, .hero { /* 首屏可见区域样式 */ }
</style>
<!-- 异步加载剩余CSS -->
<link rel="preload" href="full.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="full.css"></noscript>
CSS与JavaScript
Q:为什么说”CSS会阻塞JavaScript执行”?
- 默认行为:
- 浏览器遇到
<script>时会暂停 DOM 构建 - 如果存在未完成的 CSSOM 构建,JavaScript执行将被阻塞
<link rel="stylesheet" href="slow.css"> <script> // 此脚本必须等待slow.css下载并解析完成 console.log('After CSSOM'); </script>
- 浏览器遇到
Q:优化方案?
<!-- 方案1:添加defer -->
<script defer src="app.js"></script>
<!-- 方案2:动态注入CSS -->
<script>
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'non-critical.css';
document.head.appendChild(link);
</script>
如何设计CSS性能监控埋点系统
// 1. 监控CSS加载时间
const cssResource = performance.getEntriesByType('resource')
.find(r => r.initiatorType === 'css');
// 2. 检测未使用CSS
const { unusedRules } = await chrome.devtools.inspectedWindow.eval(
`(${() => {
const used = new Set();
Array.from(document.querySelectorAll('*'))
.forEach(el => used.add(el.className));
return unusedRules: Array.from(document.styleSheets)
.flatMap(sheet => Array.from(sheet.cssRules)
.filter(rule => !used.has(rule.selectorText))
}})()`
);