专题知识学习: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');

继承规则

核心继承机制

  1. 文本相关属性默认继承
    • 字体属性:font-family, font-size, font-weight, font-style
    • 文本属性:color, line-height, text-align, text-indent
    • 其他:letter-spacing, word-spacing, text-transform
  2. 布局相关属性默认不继承
    • 盒模型: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 }

关键技术要点

  1. content 属性必须设置(空字符串也要设置)
  2. 伪元素不接受 DOM 事件
  3. 默认位于主元素下层,可通过 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 详解(块级格式化上下文)

触发条件

满足任意一条即可:

  1. 根元素(<html>
  2. 浮动元素(float不为none)
  3. 绝对定位元素(position为absolute或fixed)
  4. display为inline-block、table-cell、table-caption、flex、inline-flex、grid、inline-grid等
  5. overflow不为visible的块元素(hidden、auto、scroll)
  6. 弹性项目(display: flex或inline-flex的直接子元素)
  7. 网格项目(display: grid或inline-grid的直接子元素)
  8. 多列容器(column-count或column-width不为auto,且column-count:1也属于)
  9. 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[最终渲染]
  1. 图层创建:当浏览器检测到 GPU 加速属性时,会将元素提升到独立的合成图层
  2. 纹理上传:图层内容作为纹理上传到 GPU 显存
  3. GPU 处理:GPU 执行变换、动画和合成操作
  4. 图层合成:浏览器将多个图层合成为最终图像

核心触发条件(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层叠顺序(从高到低)为:

  1. 用户代理!important(浏览器默认)
  2. 用户!important
  3. 作者!important(开发者)
  4. 作者普通样式
  5. 用户普通样式
  6. 用户代理普通样式

权重实战考察

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))
  }})()`
);

第七章:实战与前沿技术

7.1 CSS 绘制复杂图形(clip-path、SVG + CSS)

7.2 暗黑模式实现(prefers-color-scheme)

7.3 视差滚动(background-attachment)

7.4 CSS Houdini(自定义属性、Paint API)

7.5 未来 CSS 趋势(@container、subgrid、:has())