Skip to content

CSS 速查表

用于描述网页呈现样式的样式表语言。

01

选择器

基础选择器

CSS 选择器用于定位 HTML 元素以应用样式。类型选择器匹配元素名称(p、div)。类选择器(.)匹配 class 属性且可重复使用。ID 选择器(#)匹配单个元素且应唯一。通配选择器(*)匹配所有元素。使用逗号分组选择器以共享样式。

css
/* Type selector - all <p> elements */
p { color: #333; }

/* Class selector - elements with class="btn" */
.btn { padding: 8px 16px; }

/* ID selector - element with id="header" */
#header { background: #fff; }

/* Universal selector - all elements */
* { box-sizing: border-box; }

/* Grouping selector */
h1, h2, h3 { font-family: Arial, sans-serif; }

组合器

组合器定义元素之间的关系。后代组合器(空格)匹配任意嵌套元素。子代组合器(>)仅匹配直接子元素。相邻兄弟组合器(+)匹配紧随其后的元素。通用兄弟组合器(~)匹配之后的所有兄弟元素。理解组合器对于无需额外类即可精确设置样式至关重要。

css
/* Descendant - any <a> inside .nav */
.nav a { text-decoration: none; }

/* Child - direct <li> children of <ul> */
ul > li { list-style: none; }

/* Adjacent sibling - <p> right after <h1> */
h1 + p { font-size: 1.2em; }

/* General sibling - all <p> after <h1> */
h1 ~ p { color: gray; }

属性选择器

属性选择器根据属性值匹配元素。[attr] 匹配属性存在。[attr=val] 匹配精确值。^= 匹配前缀,$= 匹配后缀,*= 匹配子串。它们在为表单输入、按类型的链接或带 data 属性的元素设置样式时非常强大,无需添加额外类。

css
/* Elements with type attribute */
[type] { border: 1px solid #ccc; }

/* Exact match */
[type="text"] { padding: 4px; }

/* Starts with */
a[href^="https"] { color: green; }

/* Ends with */
a[href$=".pdf"] { color: red; }

/* Contains */
a[href*="example"] { font-weight: bold; }

伪类

伪类根据状态或位置选择元素。交互类::hover、:focus、:active、:visited、:disabled。结构类::first-child、:last-child、:nth-child(n)、:nth-of-type(n)。:not() 否定选择器。:nth-child(odd/even) 创建斑马条纹。:nth-child(3n) 选择每第 3 个元素。这些减少了额外类的需求。

css
/* Interactive states */
a:hover { color: red; }
a:visited { color: purple; }
input:focus { border-color: blue; }
input:disabled { background: #eee; }
button:active { transform: scale(0.98); }

/* Structural */
li:first-child { font-weight: bold; }
li:last-child { border: none; }
li:nth-child(odd) { background: #f9f9f9; }
li:nth-child(3n) { color: blue; }
p:not(.highlight) { color: #333; }

伪元素

伪元素(::双冒号)为元素的特定部分设置样式。::before 和 ::after 插入生成内容(需要 content 属性)。::first-letter 和 ::first-line 为文本部分设置样式。::selection 为高亮文本设置样式。::placeholder 为输入占位符设置样式。注意:::before/::after 默认是内联的——设置 display:block 以获得块级行为。

css
/* First line of a paragraph */
p::first-line { font-weight: bold; }

/* First letter (drop cap) */
p::first-letter { font-size: 3em; float: left; }

/* Insert content before/after */
.quote::before { content: "\201C"; }
.quote::after { content: "\201D"; }

/* Selection styling */
::selection { background: yellow; color: black; }

/* Placeholder styling */
input::placeholder { color: #999; }

优先级与 !important

优先级决定当选择器冲突时应用哪条规则。内联样式 > ID > 类 > 类型。当优先级相同时,后定义的规则胜出。!important 覆盖一切但会破坏层叠——应避免使用。使用 DevTools 检查优先级。优先使用基于类的选择器以提高可维护性。通过重复类来提高优先级(.btn.btn)是一种 hack——应避免使用。

css
/* Specificity hierarchy (low to high):
   1. Type selectors (p, div)         = 0,0,0,1
   2. Class selectors (.btn)          = 0,0,1,0
   3. ID selectors (#header)          = 0,1,0,0
   4. Inline styles (style="...")     = 1,0,0,0
   5. !important                      = overrides all
*/

/* ID beats class */
#nav .link { color: red; }   /* wins */
.nav .link { color: blue; }

/* Avoid !important unless necessary */
.critical { color: red !important; }
02

盒模型

外边距与内边距

每个元素都是一个盒子,包含内容、内边距、边框和外边距。内边距在边框内部(影响背景),外边距在外部(透明)。简写:1 个值 = 所有边,2 个值 = 上/下 左/右,3 个 = 上 左/右 下,4 个 = 上 右 下 左(顺时针)。margin: 0 auto 使具有定义宽度的块级元素水平居中。

css
.box {
  /* TRBL: top right bottom left */
  margin: 10px 20px 10px 20px;

  /* Shorthand: top/bottom  left/right */
  margin: 10px 20px;

  /* All sides */
  padding: 15px;

  /* Individual sides */
  margin-top: 0;
  padding-left: 24px;

  /* Center horizontally (block) */
  margin: 0 auto;
}

边框与轮廓

border 在内边距周围添加线条,影响布局。outline 在边框外部绘制且不影响布局——适用于焦点指示器。border-radius 圆角(单个值或每个角:左上 右上 右下 左下)。outline-offset 在边框和轮廓之间添加间距。始终为可访问性提供可见的焦点样式。

css
.box {
  /* Shorthand: width style color */
  border: 2px solid #333;

  /* Individual sides */
  border-bottom: 3px dashed red;
  border-radius: 8px;

  /* Outline (doesn't affect layout) */
  outline: 2px solid blue;
  outline-offset: 4px;
}

/* Remove default focus, add custom */
button:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(0,123,255,0.5);
}

盒尺寸

box-sizing: content-box(默认)表示 width/height 仅应用于内容——内边距和边框会增加总尺寸。box-sizing: border-box 将内边距和边框包含在 width/height 中,使尺寸可预测。始终全局设置 border-box 以获得一致的布局。这是最重要的 CSS 重置之一。

css
/* Default: width = content only */
.content-box {
  box-sizing: content-box;
  width: 200px;
  padding: 20px;
  border: 5px solid;
  /* Total width: 200 + 40 + 10 = 250px */
}

/* Recommended: width includes padding+border */
.border-box {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 5px solid;
  /* Total width: 200px */
}

/* Apply globally */
*, *::before, *::after {
  box-sizing: border-box;
}

盒阴影

box-shadow 添加阴影效果:offset-x offset-y blur-radius spread-radius color。正偏移将阴影向右/下移动。inset 创建内阴影。多个阴影分层(第一个 = 顶层)。使用 rgba 创建自然融合的半透明阴影。阴影非常适合营造深度,但过度使用会损害性能——优先使用细微的阴影。

css
/* offset-x offset-y blur spread color */
.card {
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

/* Multiple shadows */
.button {
  box-shadow:
    0 1px 2px rgba(0,0,0,0.1),
    0 4px 8px rgba(0,0,0,0.05);
}

/* Inset shadow */
.input:focus {
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}

/* No shadow */
.no-shadow { box-shadow: none; }

显示与可见性

display: none 将元素从布局中完全移除(不占空间)。visibility: hidden 隐藏元素但保留其空间。opacity: 0 使其透明但仍可交互。block 元素占据全部宽度并换行。inline 元素随文本流动。inline-block 结合了内联流动和块级尺寸(width、height)。使用 display: none 切换内容。

css
/* Display types */
div { display: block; }           /* full width, line break */
span { display: inline; }         /* content width, no break */
.inline-block { display: inline-block; } /* inline but block props */
.flex { display: flex; }          /* flex container */
.grid { display: grid; }          /* grid container */
.none { display: none; }          /* removed from layout */

/* Visibility (keeps space) */
.hidden { visibility: hidden; }

/* Opacity (keeps space, can interact) */
.fade { opacity: 0; }
03

颜色与单位

颜色格式

CSS 支持多种颜色格式。Hex(#rrggbb)最常见。RGB/RGBA 添加 alpha 透明度。HSL(色相 0-360,饱和度%,亮度%)很直观——改变色相切换颜色,改变亮度调整明暗。currentColor 继承元素的 color 属性。现代 CSS 还支持 oklch() 和 color() 以获得更宽的色域。使用 rgba/hsla 实现透明度。

css
/* Named colors */
.color { color: red; background: tomato; }

/* Hexadecimal */
.hex { color: #ff6600; }        /* 6-digit */
.hex-short { color: #f60; }     /* 3-digit shorthand */

/* RGB / RGBA */
.rgb { color: rgb(255, 102, 0); }
.rgba { background: rgba(0, 0, 0, 0.5); }

/* HSL / HSLA (hue, saturation, lightness) */
.hsl { color: hsl(20, 100%, 50%); }
.hsla { background: hsla(120, 100%, 50%, 0.3); }

/* Current color keyword */
.box { color: blue; border: 2px solid currentColor; }

长度单位

px 是绝对且可预测的。em 相对于父元素的 font-size(嵌套时会叠加)。rem 相对于根(html)元素的 font-size——一致且更适合可访问性。% 相对于父元素。vh/vw 相对于视口(100vh = 全高)。使用 rem 设置字体大小,% 用于布局,px 用于边框/精细细节。

css
/* Absolute units */
.px { font-size: 16px; }     /* 1px = 1/96 inch */
.pt { font-size: 12pt; }     /* 1pt = 1/72 inch */

/* Relative to parent font-size */
.em { font-size: 1.5em; }    /* 1.5x parent */

/* Relative to root font-size (html) */
.rem { font-size: 1.2rem; }  /* 1.2x root (usually 16px) */

/* Relative to parent dimensions */
.pct { width: 50%; }         /* 50% of parent */

/* Viewport units */
.vh { height: 100vh; }       /* 100% of viewport height */
.vw { width: 50vw; }         /* 50% of viewport width */
.vmin { font-size: 2vmin; }  /* 2% of smaller dimension */

CSS 函数

calc() 执行混合单位的数学运算(例如 100% - 250px)。min() 选择最小值(非常适合响应式最大宽度)。max() 选择最大值。clamp(min, preferred, max) 创建在边界之间缩放的流式值——非常适合响应式排版。var() 引用自定义属性并带有可选回退值。这些函数使 CSS 无需媒体查询即可实现动态效果。

css
/* calc() - mathematical calculations */
.sidebar { width: calc(100% - 250px); }
.gap { margin: calc(1rem + 10px); }

/* min() / max() - choose smaller/larger */
.responsive { width: min(90%, 1200px); }
.min-width { width: max(300px, 50%); }

/* clamp() - fluid sizing with bounds */
.title { font-size: clamp(1.5rem, 4vw, 3rem); }

/* var() - use custom properties */
.btn { color: var(--primary, #007bff); }

渐变

渐变创建平滑的颜色过渡。linear-gradient(direction, color1, color2) 沿方向(to right、45deg)变化。radial-gradient 从中心点向外扩展。conic-gradient 围绕中心旋转。可以添加带位置的颜色停止点:linear-gradient(to right, red 0%, blue 50%, green 100%)。渐变是图像而非颜色,可在任何接受 background-image 的地方使用。

css
/* Linear gradient */
.bg1 {
  background: linear-gradient(to right, #ff0000, #0000ff);
}

/* Diagonal with angle */
.bg2 {
  background: linear-gradient(45deg, #ff0000, #00ff00, #0000ff);
}

/* Radial gradient */
.bg3 {
  background: radial-gradient(circle, #ff0000, #0000ff);
}

/* Conic gradient */
.bg4 {
  background: conic-gradient(red, yellow, green, blue, red);
}

滤镜与混合模式

filter 应用视觉效果:blur()、brightness()、contrast()、grayscale()、sepia()、hue-rotate()、invert()、opacity()、saturate()。多个滤镜可链式组合。mix-blend-mode 将元素与其后面的内容混合(multiply、screen、overlay 等)。backdrop-filter 对元素后面的区域应用滤镜(非常适合毛玻璃效果)。滤镜可能影响性能——谨慎使用。

css
/* Filters */
img.bw { filter: grayscale(100%); }
img.blur { filter: blur(5px); }
img.bright { filter: brightness(1.5); }
img.sepia { filter: sepia(0.8); }

/* Multiple filters */
img.vintage {
  filter: sepia(0.5) contrast(1.2) brightness(0.9);
}

/* Blend mode */
.overlay {
  background: rgba(255,0,0,0.5);
  mix-blend-mode: multiply;
}
04

排版

字体属性

font-family 接受回退列表——浏览器使用第一个可用的字体。始终以通用字体系列结尾(serif、sans-serif、monospace)。font-weight 范围从 100(细)到 900(粗)。line-height: 1.5 表示 1.5 倍字体大小——1.4-1.6 最适合正文可读性。font 简写必须至少包含 size 和 family。

css
body {
  /* Font shorthand: style weight size/line-height family */
  font: italic bold 16px/1.5 Arial, sans-serif;

  /* Individual properties */
  font-family: "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  font-weight: 400;  /* 100-900, normal=400, bold=700 */
  font-style: italic; /* normal, italic, oblique */
  line-height: 1.5;
}

文本样式

text-align 控制水平对齐。text-decoration 添加线条(下划线、上划线、删除线)。text-transform 改变大小写。letter-spacing(字距)和 word-spacing 调整字符和单词之间的间距。white-space: nowrap 防止文本换行。对于垂直对齐,使用 vertical-align(内联)或 flexbox/grid 对齐(块级)。

css
p {
  text-align: justify;        /* left, right, center, justify */
  text-decoration: underline; /* none, overline, line-through */
  text-transform: capitalize; /* uppercase, lowercase, capitalize */
  text-indent: 2em;           /* indent first line */
  letter-spacing: 0.05em;     /* tracking */
  word-spacing: 0.1em;
  white-space: nowrap;        /* prevent wrapping */
}

a {
  text-decoration: none;
  color: #0066cc;
}

文本溢出与换行

要用省略号截断文本,需要三个属性:white-space: nowrap、overflow: hidden 和 text-overflow: ellipsis。overflow-wrap: break-word 断开长单词以防止溢出。word-break: break-all 在任意字符处断开。text-wrap: balance(较新)平衡标题的行长度。始终设置 max-width 或 width 才能使截断生效。

css
/* Truncate with ellipsis */
.truncate {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 200px;
}

/* Break long words */
.break-word {
  overflow-wrap: break-word;
  word-break: break-all;
}

/* Balance text wrapping (newer) */
h1 {
  text-wrap: balance;
}

Web 字体(@font-face)

@font-face 加载自定义字体。woff2 是现代格式(最佳压缩)。提供 woff 作为回退。font-display: swap 立即显示回退文本,然后在字体加载后替换(防止不可见文本)。始终声明回退字体系列。Google Fonts 通过 @import 或 <link> 提供托管字体。预加载关键字体以提高性能。

css
@font-face {
  font-family: 'MyCustomFont';
  src: url('fonts/custom.woff2') format('woff2'),
       url('fonts/custom.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

body {
  font-family: 'MyCustomFont', Arial, sans-serif;
}

/* Google Fonts import */
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');

列表与链接样式

list-style: none 移除默认项目符号,用于自定义导航或样式化列表。list-style-type 改变项目符号(disc、circle、square、decimal、none)。list-style-position: inside 将项目符号放在内容区域内。对于链接,LVHA 顺序很重要::link、:visited、:hover、:active。这确保了链接状态的正确层叠。

css
/* Reset list styles */
ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* Custom bullets */
ul.custom {
  list-style-type: square;
  list-style-position: inside;
}

/* Image bullets */
ul.image {
  list-style-image: url('bullet.png');
}

/* Link states (order matters!) */
a:link { color: blue; }
a:visited { color: purple; }
a:hover { color: red; text-decoration: underline; }
a:active { color: orange; }
05

Flexbox 布局

Flex 容器

display: flex 创建一个 flex 容器。justify-content 沿主轴对齐项目(row 中为水平方向)。align-items 沿交叉轴对齐(垂直方向)。flex-direction 改变主轴方向。flex-wrap 允许项目换行到新行。gap 设置项目之间的间距(替代外边距 hack)。Flexbox 非常适合一维布局(行或列)。

css
.container {
  display: flex;

  /* Main axis alignment */
  justify-content: space-between;
  /* flex-start, center, flex-end, space-around, space-evenly */

  /* Cross axis alignment */
  align-items: center;
  /* flex-start, center, flex-end, stretch, baseline */

  /* Direction */
  flex-direction: row;
  /* row, row-reverse, column, column-reverse */

  /* Wrapping */
  flex-wrap: wrap;
  /* nowrap, wrap, wrap-reverse */

  /* Gap between items */
  gap: 16px;
}

Flex 项目

flex-grow 控制项目如何分配额外空间(0 = 不增长,1 = 等量增长)。flex-shrink 控制空间不足时项目如何收缩。flex-basis 设置初始尺寸。简写 flex: 1 表示 flex-grow:1、flex-shrink:1、flex-basis:0%。align-self 为单个项目覆盖容器的 align-items。order 在不改变 DOM 的情况下视觉重排项目。

css
.item {
  /* Grow: how much space to take (0 = don't grow) */
  flex-grow: 1;

  /* Shrink: how much to shrink when space is tight */
  flex-shrink: 0;

  /* Basis: initial size before growing/shrinking */
  flex-basis: 200px;

  /* Shorthand: flex: grow shrink basis */
  flex: 1 0 200px;

  /* Override align-items for this item */
  align-self: flex-end;

  /* Order (default 0, lower = earlier) */
  order: -1;
}

常见 Flexbox 模式

Flexbox 使居中变得简单:justify-content: center + align-items: center。对于粘性页脚,将 body 设为 flex 列,min-height: 100vh,让主内容 flex: 1。对于导航栏,justify-content: space-between 将第一个和最后一个项目推到两端。这些模式解决了在 flexbox 出现之前难以处理的常见布局问题。

css
/* Center anything */
.center {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

/* Sticky footer */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.main { flex: 1; }

/* Navbar: logo left, links right */
.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

Flex 方向与换行

flex-direction: column 创建垂直布局(用于堆叠)。flex-wrap: wrap 允许项目在空间不足时流到新行。flex: 1 1 300px 表示项目从 300px 开始,增长以填充空间,并按需收缩。align-content 控制换行行之间的间距(仅在 wrap 时有效)。此模式创建响应式卡片网格。

css
/* Horizontal (default) */
.row { display: flex; flex-direction: row; }

/* Vertical */
.column { display: flex; flex-direction: column; }

/* Reverse */
.row-rev { display: flex; flex-direction: row-reverse; }

/* Wrap to new lines */
.cards {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}
.card { flex: 1 1 300px; } /* grow, shrink, basis */

/* Align wrapped lines */
.cards { align-content: space-between; }

Flexbox 对齐深入解析

在 flex-direction: column 中,主轴为垂直方向,交叉轴为水平方向——justify-content 和 align-items 的角色互换。flex 项目上的 margin: auto 吸收所有可用空间,完美居中。这是 justify-content/align-items 的替代方案。理解哪个轴是'主轴'哪个是'交叉轴'是掌握 flexbox 对齐的关键。

css
.container {
  display: flex;
  flex-direction: column;

  /* Main axis = vertical (column) */
  justify-content: flex-start;
  /* push items to top, center, bottom, or spread */

  /* Cross axis = horizontal (column) */
  align-items: stretch;
  /* stretch items to full width */
}

/* Center a single item perfectly */
.wrapper {
  display: flex;
  min-height: 100vh;
}
.centered {
  margin: auto; /* centers in both axes */
}
06

CSS Grid 布局

Grid 容器

display: grid 创建二维布局。grid-template-columns 定义列大小:fr 单位按比例分配可用空间。repeat(3, 1fr) 创建 3 个等宽列。repeat(auto-fit, minmax(250px, 1fr)) 创建自动调整列数的响应式网格——这是响应式网格的'圣杯'。gap 替代外边距用于间距。

css
.grid {
  display: grid;

  /* Define columns */
  grid-template-columns: 200px 1fr 200px;
  /* fixed, flexible, fixed */

  /* Or repeat */
  grid-template-columns: repeat(3, 1fr);
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

  /* Define rows */
  grid-template-rows: auto 1fr auto;

  /* Gap (formerly grid-gap) */
  gap: 20px;
  row-gap: 10px;
  column-gap: 20px;
}

Grid 项目放置

Grid 项目可以通过 grid-column: span N 跨越多个单元格。也可以使用行号:grid-column: 1 / 3 表示从第 1 行开始,到第 3 行结束。行号从 1(左/上)到 N+1(右/下)编号。grid-area 将项目分配到命名区域。Grid 允许精确的二维放置——项目可以同时跨越行和列。

css
.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

/* Span multiple columns */
.featured {
  grid-column: span 2;
}

/* Explicit placement */
.sidebar {
  grid-column: 1 / 3;  /* start at line 1, end at line 3 */
  grid-row: 1 / 4;
}

/* Named areas */
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }

Grid 模板区域

grid-template-areas 使用命名字符串创建布局的可视化映射。每个字符串代表一行;每个名称代表一列。通过将 grid-area 设置为匹配的名称来放置项目。这是创建复杂布局最易读的方式。使用 '.' 表示空单元格。相同的名称可以跨越多个单元格。在媒体查询中更改区域以实现响应式布局。

css
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  gap: 10px;
  min-height: 100vh;
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }

Grid 对齐

Grid 有 6 个对齐属性。align-items/justify-items 在其网格单元格内对齐项目。align-content/justify-content 在容器内对齐整个网格轨道(仅在网格较小时可见)。align-self/justify-self 按项目覆盖。place-items: center 是 align-items + justify-items 的简写。place-content: center 组合两种内容对齐。

css
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);

  /* Align items within their cell (cross axis) */
  align-items: center;  /* start, center, end, stretch */

  /* Justify items within their cell (main axis) */
  justify-items: center;

  /* Align the entire grid (if smaller than container) */
  align-content: center;
  justify-content: center;
}

/* Override for individual item */
.item {
  align-self: end;
  justify-self: start;
}

响应式 Grid(Auto-fit)

repeat(auto-fit, minmax(300px, 1fr)) 创建根据可用空间自动调整列数的网格——项目至少 300px 并增长以填充。这消除了卡片布局的媒体查询。auto-fill 保留空列(项目保持左侧),auto-fit 折叠空列(项目拉伸)。大多数情况下使用 auto-fit。结合容器上的 max-width 可获得最佳效果。

css
/* Auto-responsive grid - no media queries needed! */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

/* Fixed number of columns per breakpoint */
@media (min-width: 768px) {
  .cards {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 1024px) {
  .cards {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Auto-fill vs auto-fit:
   auto-fit collapses empty tracks
   auto-fill keeps empty tracks */
07

定位

定位类型

static 是默认值(正常文档流)。relative 相对于其正常位置偏移且不影响其他元素(创建定位上下文)。absolute 从文档流中移除并相对于最近的已定位祖先定位。fixed 相对于视口定位(滚动时保持)。sticky 在 relative 和 fixed 之间切换——正常滚动然后在阈值处固定。

css
/* Static (default) - normal flow */
.static { position: static; }

/* Relative - offset from normal position */
.relative {
  position: relative;
  top: 10px;
  left: 20px;
}

/* Absolute - positioned relative to nearest positioned ancestor */
.absolute {
  position: absolute;
  top: 0;
  right: 0;
}

/* Fixed - positioned relative to viewport */
.fixed {
  position: fixed;
  bottom: 0;
  width: 100%;
}

/* Sticky - scrolls then sticks */
.sticky {
  position: sticky;
  top: 0;
}

绝对定位

绝对定位需要一个已定位的祖先(relative、absolute、fixed 或 sticky)。如果没有,则相对于视口定位。top/right/bottom/left 属性相对于对应边缘偏移。要居中绝对定位的元素,使用 top:50%、left:50% 配合 transform: translate(-50%,-50%)。绝对定位将元素从正常文档流中移除。

css
/* Parent must be positioned */
.container {
  position: relative;
  width: 400px;
  height: 300px;
}

/* Position relative to container */
.badge {
  position: absolute;
  top: 10px;
  right: 10px;
}

/* Center absolutely positioned element */
.modal {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

粘性定位

position: sticky 是混合模式——元素正常滚动直到达到阈值(例如 top: 0),然后固定。非常适合粘性页眉、侧边栏和表格标题。元素在其父容器内固定(当父容器滚动过去时停止固定)。如果任何祖先有 overflow: hidden/auto/scroll,sticky 将不起作用。始终设置 z-index 以防止重叠问题。

css
/* Sticky header */
.header {
  position: sticky;
  top: 0;
  background: white;
  z-index: 100;
  padding: 1rem;
}

/* Sticky sidebar */
.sidebar {
  position: sticky;
  top: 80px; /* offset for fixed header */
  height: calc(100vh - 80px);
  overflow-y: auto;
}

/* Note: sticky doesn't work if a parent has
   overflow: hidden or overflow: auto */

Z-index 与层叠上下文

z-index 控制已定位元素的堆叠顺序(值越高越在上层)。它仅对已定位元素(非 static)有效。层叠上下文由带 z-index 的已定位元素、opacity < 1、transform 或 filter 创建。在层叠上下文内,子元素的 z-index 值相对于该上下文——子元素永远不会出现在其父元素具有更高 z-index 的兄弟元素之上。这是常见的混淆来源。

css
/* Higher z-index = closer to viewer */
.modal-overlay {
  position: fixed;
  z-index: 9999;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.5);
}

.modal {
  position: fixed;
  z-index: 10000; /* above overlay */
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}

/* Stacking context: z-index only works
   within the same stacking context */
.parent { position: relative; z-index: 1; }
.child { position: absolute; z-index: 9999; }
/* child can't exceed parent's stacking level */

浮动与清除(传统)

float 是 flexbox/grid 出现之前的主要布局方法。它将元素从正常文档流中移除并推到左/右,文本环绕在其周围。clear 防止元素出现在浮动元素旁边。clearfix hack 强制容器包围浮动的子元素。如今,仅将 float 用于其预期目的:使文本环绕图像。对于布局,使用 flexbox 或 grid。

css
/* Float text around an image */
img.float-left {
  float: left;
  margin: 0 1rem 1rem 0;
}

/* Clear floats */
.clear { clear: both; }
.clear-left { clear: left; }
.clear-right { clear: right; }

/* Clearfix hack for containers */
.clearfix::after {
  content: "";
  display: table;
  clear: both;
}

/* Modern alternative: use flexbox or grid */
/* Float is mainly for text wrapping now */
08

响应式设计

媒体查询

媒体查询根据条件应用样式。min-width(移动优先)是首选——基础样式针对移动设备,然后为更大屏幕增强。max-width(桌面优先)则相反。其他条件:prefers-color-scheme(深色/浅色)、print、orientation(纵向/横向)、prefers-reduced-motion。始终在 HTML 中设置 viewport meta 标签,媒体查询才能在移动设备上工作。

css
/* Mobile-first: base styles first, then min-width */

/* Base (mobile) */
.container { flex-direction: column; }

/* Tablet and up */
@media (min-width: 768px) {
  .container { flex-direction: row; }
}

/* Desktop and up */
@media (min-width: 1024px) {
  .container { max-width: 1200px; margin: 0 auto; }
}

/* Print styles */
@media print {
  .no-print { display: none; }
}

/* Dark mode */
@media (prefers-color-scheme: dark) {
  body { background: #1a1a1a; color: #eee; }
}

流式排版

clamp(min, preferred, max) 创建随视口大小平滑缩放的流式排版——无需媒体查询。首选值(通常基于 vw)在 min 和 max 边界之间缩放。min() 选择较小值(非常适合响应式最大宽度)。此方法减少了所需的媒体查询数量并创建更平滑的缩放。始终设置合理的 min/max 以保证可读性。

css
/* clamp() for fluid font sizes */
h1 {
  font-size: clamp(1.5rem, 5vw, 3rem);
  /* min: 1.5rem, preferred: 5vw, max: 3rem */
}

/* Fluid spacing */
.container {
  padding: clamp(1rem, 3vw, 3rem);
}

/* Fluid width */
.content {
  width: min(90%, 1200px);
  margin: 0 auto;
}

/* Viewport-based sizing */
.hero {
  height: 100vh;
  font-size: clamp(2rem, 8vw, 5rem);
}

容器查询

容器查询(CSS Containment Module Level 3)允许根据父容器的大小而非视口设置元素样式。container-type: inline-size 声明一个容器。@container 在容器满足条件时应用样式。这比媒体查询更模块化——组件适应其容器而非屏幕。非常适合在不同布局上下文中可重用的组件。

css
/* Define a container */
.card-container {
  container-type: inline-size;
  /* or: container: sidebar / inline-size; */
}

/* Query the container's size */
@container (min-width: 400px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

@container (max-width: 399px) {
  .card {
    display: flex;
    flex-direction: column;
  }
}

响应式图像与媒体

max-width: 100% + height: auto 使图像响应式(缩小但从不放大)。padding-bottom hack 创建响应式 16:9 视频嵌入。现代的 aspect-ratio 属性更简洁——设置比例,浏览器计算高度。始终在图像上设置 width 和 height 属性以防止布局偏移(CLS)。使用 object-fit: cover 在固定尺寸内裁剪图像。

css
/* Responsive image */
img {
  max-width: 100%;
  height: auto;
}

/* Responsive video (16:9 aspect ratio) */
.video-wrapper {
  position: relative;
  padding-bottom: 56.25%; /* 9/16 */
  height: 0;
}
.video-wrapper iframe {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
}

/* Aspect ratio property */
.box {
  aspect-ratio: 16 / 9;
  width: 100%;
}

移动优先策略

移动优先意味着将移动样式作为基础,然后通过 min-width 媒体查询逐步为更大屏幕增强。这确保移动用户(通常在较慢的连接上)下载更少的 CSS。常见断点:768px(平板)、1024px(桌面)、1440px(大屏)。使用相对单位(rem、%、vw)而非固定 px 以获得更好的可扩展性。在真实设备上测试,而不仅仅是浏览器 DevTools。

css
/* 1. Start with mobile base styles */
.nav { display: none; } /* hidden on mobile */
.menu-toggle { display: block; }

/* 2. Enhance for larger screens */
@media (min-width: 768px) {
  .nav { display: flex; }
  .menu-toggle { display: none; }
}

/* 3. Common breakpoints */
/* Mobile: < 768px */
/* Tablet: 768px - 1023px */
/* Desktop: 1024px - 1439px */
/* Large: >= 1440px */

/* 4. Use relative units */
body { font-size: 1rem; } /* not 16px */
09

过渡与动画

过渡

transition 在属性值之间创建平滑变化。语法:transition: property duration timing-function delay。计时函数:ease(默认)、linear、ease-in、ease-out、ease-in-out、cubic-bezier()。只有可动画属性才能过渡。避免 transition: all(性能问题)。过渡在伪类变化(:hover、:focus)或通过 JavaScript 更改类时触发。

css
.button {
  background: #007bff;
  transition: background 0.3s ease, transform 0.2s ease;
}

.button:hover {
  background: #0056b3;
  transform: translateY(-2px);
}

/* Transition all properties (use sparingly) */
.card {
  transition: all 0.3s ease;
}

/* Shorthand: property duration timing-function delay */
.box {
  transition: opacity 0.5s ease-in 0.2s;
}

变换

transform 修改元素而不影响布局(不同于 margin/position)。translate 移动它(translateX、translateY 或 translate(x,y))。scale 调整大小(1 = 100%)。rotate 旋转它(deg、rad、turn)。skew 扭曲它。多个变换按顺序链式应用。变换是 GPU 加速的——性能极佳。始终与 transition 配合以获得平滑效果。transform-origin 改变旋转中心点。

css
.box {
  transition: transform 0.3s ease;
}

/* Translate (move) */
.box:hover { transform: translate(10px, 20px); }
.box:hover { transform: translateX(50%); }

/* Scale (resize) */
.box:hover { transform: scale(1.1); }

/* Rotate */
.box:hover { transform: rotate(45deg); }

/* Skew */
.box:hover { transform: skew(10deg, 5deg); }

/* Combine transforms */
.box:hover {
  transform: translate(10px, 0) scale(1.1) rotate(5deg);
}

关键帧动画

@keyframes 定义动画步骤。0%/from 是开始,100%/to 是结束。可以添加中间步骤(25%、50%、75%)。animation 简写:name duration timing-function delay iteration-count direction fill-mode。infinite 永远循环。direction: alternate 在偶数迭代时反向。fill-mode: forwards 保持最终状态。动画自动运行,不同于过渡。

css
@keyframes bounce {
  0%   { transform: translateY(0); }
  50%  { transform: translateY(-20px); }
  100% { transform: translateY(0); }
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.ball {
  animation: bounce 0.5s ease infinite;
}

.element {
  animation: fadeIn 1s ease forwards;
  /* name duration timing delay iteration direction fill-mode */
}

动画属性

单独的动画属性提供精细控制。animation-iteration-count 可以是数字或 infinite。animation-direction: alternate 先正向再反向播放(非常适合乒乓效果)。animation-fill-mode: forwards 在结束后保持最终状态。animation-play-state: paused 冻结动画——适用于悬停暂停。多个动画用逗号分隔:animation: spin 1s, fade 2s;。

css
.spinner {
  animation-name: spin;
  animation-duration: 1s;
  animation-timing-function: linear;
  animation-delay: 0s;
  animation-iteration-count: infinite;
  animation-direction: normal; /* alternate, reverse */
  animation-fill-mode: none;   /* forwards, backwards, both */
  animation-play-state: running; /* paused */
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Pause on hover */
.spinner:hover {
  animation-play-state: paused;
}

性能与减少动画

为了流畅的 60fps 动画,仅动画化 transform 和 opacity——它们是 GPU 加速的且不触发布局(重排)。动画化 width、margin、top 等会强制浏览器为每一帧重新计算布局,导致卡顿。始终尊重 prefers-reduced-motion: reduce——一些用户会感到晕动症或有前庭障碍。为这些用户提供即时过渡或禁用动画。

css
/* Only animate transform and opacity for performance */
.good {
  transition: transform 0.3s, opacity 0.3s;
}

/* Avoid animating these (cause reflow/repaint): */
/* margin, padding, width, height, top, left */

/* Respect user's motion preference */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}
10

变量与高级函数

自定义属性(变量)

自定义属性(CSS 变量)存储可重用的值。在 :root 中定义以全局访问。使用 var(--name) 引用。它们层叠并可在任何作用域中被覆盖——非常适合主题化(深色/浅色模式)。与预处理器变量不同,它们是动态的(在运行时更改)且可以用 JavaScript 操作。始终提供回退值:var(--primary, #007bff)。这是管理设计令牌的现代方式。

css
:root {
  /* Colors */
  --primary: #007bff;
  --primary-dark: #0056b3;
  --text: #333;
  --bg: #fff;

  /* Spacing scale */
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 2rem;

  /* Font sizes */
  --font-base: 16px;
  --font-lg: 1.5rem;
}

.button {
  background: var(--primary);
  padding: var(--space-sm) var(--space-md);
  font-size: var(--font-base);
  color: white;
}

/* Override in a scope */
.dark-theme {
  --bg: #1a1a1a;
  --text: #eee;
}

calc() 与数学函数

calc() 使用任何单位执行数学运算,包括混合 px、%、em、rem、vw。它对响应式布局至关重要。可以嵌套 calc() 但不必要——calc(100% - 2rem) / 3 无需内部 calc 即可工作。min() 返回最小值,max() 返回最大值,clamp() 将值限制在 min 和 max 之间。这些函数使 CSS 无需 JavaScript 或媒体查询即可实现动态效果。

css
/* Mixed unit calculations */
.sidebar {
  width: calc(100% - 250px);
}

/* With variables */
.box {
  padding: calc(var(--space-md) + 10px);
}

/* Nested calc */
.responsive {
  width: calc(calc(100% - 2rem) / 3);
}

/* min(), max(), clamp() */
.fluid {
  width: min(90%, 1200px);
  font-size: clamp(1rem, 2vw + 1rem, 2rem);
  height: max(200px, 50vh);
}

对象适配与定位

object-fit 控制图像/视频如何填充其容器(类似于 <img> 的 background-size)。cover 填充容器并裁剪溢出(非常适合头像/缩略图)。contain 完全适应而不裁剪(可能留有空白)。fill 拉伸(会变形)。object-position 调整对齐(类似于 background-position)。这替代了响应式图像的 background-image hack。

css
/* Cover: fill container, crop overflow */
.avatar {
  width: 100px;
  height: 100px;
  object-fit: cover;
  border-radius: 50%;
}

/* Contain: fit entirely, may letterbox */
.preview {
  width: 200px;
  height: 200px;
  object-fit: contain;
  background: #eee;
}

/* Position the image within the frame */
.image {
  object-fit: cover;
  object-position: top center;
}

背景属性

background 是一个强大的简写。background-size: cover 填充容器(裁剪);contain 适应而不裁剪。background-attachment: fixed 创建视差效果(滚动时图像保持静止)。多个背景用逗号分层(第一个 = 顶层)。使用 linear-gradient 作为背景叠加:background: linear-gradient(rgba(0,0,0,0.5), transparent), url('image.jpg')。

css
.hero {
  /* Shorthand */
  background: url('hero.jpg') center/cover no-repeat fixed;

  /* Individual properties */
  background-image: url('hero.jpg');
  background-size: cover;     /* cover, contain, or px/% */
  background-position: center; /* top, bottom, left, right, or x y */
  background-repeat: no-repeat;
  background-attachment: fixed; /* scroll, fixed, local */

  /* Multiple backgrounds */
  background:
    url('overlay.png') no-repeat center,
    url('hero.jpg') center/cover;
}

CSS 嵌套(现代)

现代 CSS 支持原生嵌套(类似于 Sass/Less)。使用 & 引用父选择器。嵌套提高了可读性并减少了重复。媒体查询可以直接嵌套在规则内。现代浏览器(2023+)支持良好。& 对于伪类(&:hover)和组合器(& > .child)是必需的。避免深度嵌套(3+ 层),因为它增加了优先级并降低了可维护性。

css
/* Native CSS nesting (no preprocessor needed) */
.card {
  background: white;
  border-radius: 8px;

  & .title {
    font-size: 1.5rem;
    font-weight: bold;
  }

  & .body {
    padding: 1rem;

    & p {
      line-height: 1.6;
    }
  }

  &:hover {
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  }

  @media (max-width: 768px) {
    padding: 0.5rem;
  }
}
11

CSS 自定义属性(变量)深入解析

定义与使用变量

CSS 自定义属性(变量)使用 --name 定义,使用 var() 使用。在 :root 中定义全局变量用于主题值。与 Sass 变量不同,CSS 变量是实时的——更改它们会立即更新所有使用处。它们作用于定义它们的元素并被后代继承。var() 接受回退值作为第二个参数,且回退可以链式调用。这使它们在动态主题化方面远比预处理器变量强大。

css
:root {
  --primary: #3498db;
  --spacing: 16px;
  --radius: 8px;
  --max-width: 1200px;
}

.button {
  background: var(--primary);
  padding: var(--spacing);
  border-radius: var(--radius);
  max-width: var(--max-width);
}

/* Fallback values */
color: var(--text-color, #333);
/* Chained fallbacks */
color: var(--text, var(--default, black));

使用 JavaScript 实现动态主题

CSS 变量实现了预处理器无法做到的运行时主题化。在 <html> 上设置 data-theme 并按主题覆盖变量。JavaScript 可以在运行时读取(getComputedStyle)和设置(style.setProperty)变量,实现动态颜色选择器、用户偏好和实时预览。这是深色模式、品牌定制和用户可选主题的标准方法。变量层叠和继承,因此在子元素中覆盖仅影响该子树。

css
/* Define theme variables */
:root {
  --bg: #ffffff;
  --text: #333333;
}

[data-theme="dark"] {
  --bg: #1a1a1a;
  --text: #e0e0e0;
}

body {
  background: var(--bg);
  color: var(--text);
}

/* Toggle theme with JS */
<script>
document.documentElement.setAttribute(
  "data-theme",
  isDark ? "dark" : "light"
);

/* Or set a single variable directly */
document.documentElement.style
  .setProperty("--primary", "#e74c3c");
</script>

作用域变量与继承

CSS 变量像其他属性一样继承。在 :root 上定义的变量随处可用;在 .card 上定义的仅影响 .card 及其后代。这种作用域实现了组件级定制。可以在媒体查询中覆盖变量以创建响应式变量值——变量本身不能在 @media 条件中使用,但可以在媒体查询块内更改其值。此模式对于无需重复属性声明的响应式设计非常强大。

css
:root {
  --padding: 20px;
}

.card {
  --padding: 12px; /* overrides only for .card subtree */
  padding: var(--padding);
}

.card .inner {
  padding: var(--padding); /* inherits 12px from .card */
}

/* Variables in media queries don't work, but... */
.sidebar {
  --width: 250px;
  width: var(--width);
}
@media (max-width: 768px) {
  .sidebar { --width: 100%; }
}

变量与 calc()

将 CSS 变量与 calc() 结合创建强大的设计系统。定义基础尺寸和缩放因子,然后计算派生尺寸。这实现了一致的排版比例和间距系统。calc() 适用于混合单位(px、%、em、vw)和变量。甚至可以使用不带回退的变量(var(--nav-h, 60px) 提供默认值)。此方法是现代设计系统的基础——更改一个变量,整个比例按比例调整。

css
:root {
  --base-size: 16px;
  --scale: 1.25;
}

h1 { font-size: calc(var(--base-size) * var(--scale) * 2); }
h2 { font-size: calc(var(--base-size) * var(--scale) * 1.5); }
p  { font-size: var(--base-size); }

/* Spacing scale */
:root {
  --space: 8px;
}
.margin { margin: calc(var(--space) * 2); }
.padding { padding: calc(var(--space) * 3); }

/* Mixed units */
.header { height: calc(var(--nav-h, 60px) + var(--content-h)); }

注册自定义属性(@property)

@property 注册具有类型(syntax)、初始值和继承标志的自定义属性。这使 CSS 变量能够被动画化和过渡——没有 @property,变量被视为字符串且无法插值。syntax 接受类型如 <angle>、<color>、<length>、<number>、<percentage> 或 '*'。这解锁了由变量驱动的渐变、变换和颜色的平滑动画。Chromium 和 Safari 支持良好,Firefox 正在添加支持。这是 CSS 动画能力的重大进步。

css
/* Type-safe custom properties */
@property --angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@property --color {
  syntax: "<color>";
  initial-value: #3498db;
  inherits: false;
}

/* Now animatable! */
@keyframes spin {
  to { --angle: 360deg; }
}

.loader {
  --angle: 0deg;
  animation: spin 1s linear infinite;
  background: conic-gradient(
    from var(--angle),
    var(--color), transparent
  );
}
12

3D 变换

3D 变换函数

3D 变换为元素添加深度。perspective() 作为变换函数应用于单个元素;父元素上的 perspective 属性统一应用于所有子元素。rotateX/rotateY/rotateZ 绕轴旋转;translateZ 沿 Z 轴移动(朝向/远离观察者)。较低的 perspective 值创建更戏剧性的 3D 效果(更近的视点)。始终在父容器上设置 perspective,以在多个变换子元素之间获得一致的 3D 空间。组合多个变换以实现复杂的 3D 定位。

css
.card {
  transform: perspective(1000px) rotateY(45deg) rotateX(15deg);
}

/* Using the perspective property instead */
.container {
  perspective: 1000px;
}
.container .card {
  transform: rotateY(45deg) rotateX(15deg);
}

/* translateZ moves toward/away from viewer */
.layer {
  transform: translateZ(100px);
}

/* scale3d for 3D scaling */
.box {
  transform: scale3d(1.5, 1.5, 1.5);
}

transform-style 与 backface-visibility

transform-style: preserve-3d 为子元素维护 3D 空间(flat 是默认值,会扁平化子元素)。backface-visibility: hidden 在元素旋转时隐藏其背面——对翻转卡片效果至关重要。经典的翻转卡片使用两个绝对定位的面:正面朝前,背面预旋转 180deg。悬停时,父元素旋转 180deg,交换可见的面。这是最受欢迎的 3D CSS 模式之一。

css
.container {
  perspective: 1000px;
}

.flip-card {
  transform-style: preserve-3d;
  transition: transform 0.6s;
  position: relative;
}

.flip-card:hover {
  transform: rotateY(180deg);
}

.flip-card .front,
.flip-card .back {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}

.flip-card .back {
  transform: rotateY(180deg);
}

3D 立方体

3D 立方体由 6 个面构建,每个面使用 rotate + translateZ 定位。translateZ(100px) 将面沿立方体宽度的一半向外推。每个面在推出之前预旋转到其方向。立方体容器上的 transform-style: preserve-3d 是必需的——没有它,面会扁平化。动画在 X 和 Y 轴上旋转立方体。这展示了 CSS 3D 变换的全部能力。调整 translateZ 以匹配立方体尺寸的一半,获得正确的几何形状。

css
.scene {
  perspective: 800px;
  width: 200px; height: 200px;
}
.cube {
  position: relative;
  width: 100%; height: 100%;
  transform-style: preserve-3d;
  animation: rotate 8s infinite linear;
}
@keyframes rotate {
  from { transform: rotateX(0) rotateY(0); }
  to   { transform: rotateX(360deg) rotateY(360deg); }
}
.face {
  position: absolute;
  width: 200px; height: 200px;
  opacity: 0.85;
}
.front  { transform: translateZ(100px); background: red; }
.back   { transform: rotateY(180deg) translateZ(100px); background: blue; }
.right  { transform: rotateY(90deg) translateZ(100px); background: green; }
.left   { transform: rotateY(-90deg) translateZ(100px); background: yellow; }
.top    { transform: rotateX(90deg) translateZ(100px); background: purple; }
.bottom { transform: rotateX(-90deg) translateZ(100px); background: orange; }

3D 卡片倾斜效果

卡片倾斜效果跟踪鼠标位置,并根据光标距中心的偏移在 3D 中旋转卡片。数学运算将偏移除以一个因子(10)以限制旋转角度。在 mouseleave 时,卡片重置为平面。transition 创建平滑移动。添加跟随鼠标的径向渐变眩光/光泽叠加可增强效果。这是产品卡片和英雄区域流行的交互式 UI 模式。变换字符串中的 perspective 确保即使没有父 perspective 属性也能进行 3D 渲染。

css
.tilt-card {
  transition: transform 0.1s ease-out;
  transform-style: preserve-3d;
}

/* JavaScript-driven tilt */
<script>
const card = document.querySelector(".tilt-card");
card.addEventListener("mousemove", (e) => {
  const rect = card.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
  const centerX = rect.width / 2;
  const centerY = rect.height / 2;
  const rotateX = (y - centerY) / 10;
  const rotateY = (centerX - x) / 10;
  card.style.transform =
    `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
card.addEventListener("mouseleave", () => {
  card.style.transform = "perspective(1000px) rotateX(0) rotateY(0)";
});
</script>

perspective-origin 与 3D 间距

perspective-origin 设置消失点位置(类似于移动头部)。默认为 50% 50%(中心)。移动它创建动态视角。对于视差效果,不同 translateZ 值的元素在容器滚动或旋转时以不同速率移动。更靠后的元素(负 translateZ)需要 scale() 来补偿透视缩小。此技术在 UI 中无需 JavaScript 即可创建深度——纯 CSS 视差。结合滚动驱动动画,可创建沉浸式滚动体验。

css
.stage {
  perspective: 1200px;
  perspective-origin: 50% 30%; /* x y position of vanishing point */
  transform-style: preserve-3d;
}

.layer-1 { transform: translateZ(0); }
.layer-2 { transform: translateZ(50px); }
.layer-3 { transform: translateZ(100px); }

/* Parallax-like depth */
.depth-bg    { transform: translateZ(-200px) scale(1.2); }
.depth-mid   { transform: translateZ(-100px) scale(1.1); }
.depth-fg    { transform: translateZ(0); }
13

CSS 滤镜与背景滤镜

滤镜函数

CSS 滤镜为元素应用视觉效果。grayscale、sepia 和 invert 改变颜色;blur 柔化;brightness/contrast/saturate 调整强度;hue-rotate 偏移颜色。多个滤镜从左到右链式应用。drop-shadow 对于 PNG/SVG 图像优于 box-shadow,因为它遵循 alpha 形状(透明区域不会有阴影)。滤镜是 GPU 加速的,性能良好。常见用途:悬停时灰度化图像画廊、复古照片效果和可访问性(高对比度模式)。

css
img.grayscale { filter: grayscale(100%); }
img.blur { filter: blur(5px); }
img.bright { filter: brightness(1.5); }
img.contrast { filter: contrast(200%); }
img.sepia { filter: sepia(80%); }
img.saturate { filter: saturate(2); }
img.hue { filter: hue-rotate(90deg); }
img.invert { filter: invert(100%); }

/* Combine multiple filters */
img.vintage {
  filter: sepia(50%) contrast(110%) brightness(90%) saturate(120%);
}

/* Drop shadow (follows alpha shape) */
img.png-shadow {
  filter: drop-shadow(2px 4px 6px rgba(0,0,0,0.4));
}

backdrop-filter(毛玻璃效果)

backdrop-filter 对元素后面的区域应用滤镜(而非元素本身),创建毛玻璃效果。元素需要半透明背景才能使效果可见。blur 是最常见的背景滤镜,用于磨砂玻璃。始终包含 -webkit- 前缀以支持 Safari。结合半透明边框和细微的盒阴影,获得精致的玻璃外观。大模糊区域的性能可能成为问题——谨慎使用。这是现代 UI 设计的定义性趋势(iOS、macOS、Windows Acrylic)。

css
.glass {
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px) saturate(180%);
  -webkit-backdrop-filter: blur(10px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 16px;
  padding: 24px;
}

.glass-dark {
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

SVG 滤镜(url 引用)

CSS filter: url(#id) 引用 SVG 滤镜以实现超出内置函数的效果。'gooey' 滤镜创建元素的类似液滴的合并(在加载动画和有机 UI 中很流行)。feGaussianBlur + feColorMatrix 配合高 alpha 乘数通过锐化模糊边缘创建 gooey 效果。feTurbulence + feDisplacementMap 创建波浪/扭曲效果。SVG 滤镜功能强大但可能性能密集。它们实现了 CSS 单独无法实现的效果:液态变形、位移、光照和自定义合成。

css
<!-- Define SVG filter -->
<svg style="display:none">
  <filter id="gooey">
    <feGaussianBlur in="SourceGraphic" stdDeviation="10" />
    <feColorMatrix values="
      1 0 0 0 0
      0 1 0 0 0
      0 0 1 0 0
      0 0 0 20 -10" />
  </filter>
</svg>

<!-- Apply via CSS -->
.gooey-container {
  filter: url(#gooey);
}

<!-- Displacement map for wavy text -->
<filter id="wavy">
  <feTurbulence baseFrequency="0.02" numOctaves="3" />
  <feDisplacementMap in="SourceGraphic" scale="10" />
</filter>

滤镜动画

滤镜可以平滑地动画化和过渡。脉冲发光效果结合 brightness 和 drop-shadow 实现霓虹发光。悬停时灰度到彩色是经典的画廊交互。滤镜过渡是 GPU 加速的,性能优于动画化 box-shadow 或 background-color。然而,动画化 blur 或复杂滤镜可能开销较大——在移动设备上测试。滚动驱动的 hue-rotate 是有趣的效果,但在长页面上可能导致性能问题;使用 will-change: filter 提示浏览器进行优化。

css
@keyframes pulse-glow {
  0%, 100% {
    filter: brightness(1) drop-shadow(0 0 5px #3498db);
  }
  50% {
    filter: brightness(1.3) drop-shadow(0 0 20px #3498db);
  }
}

.glow-button {
  animation: pulse-glow 2s ease-in-out infinite;
}

/* Hover filter transition */
.gallery img {
  filter: grayscale(100%);
  transition: filter 0.3s ease;
}
.gallery img:hover {
  filter: grayscale(0%);
}

/* Color shift on scroll (with JS) */
window.addEventListener("scroll", () => {
  const hue = window.scrollY * 0.5;
  document.body.style.filter = `hue-rotate(${hue}deg)`;
});

mix-blend-mode 与 background-blend-mode

mix-blend-mode 决定元素的像素如何与其后面的内容混合。multiply 变暗(适用于阴影和水印);screen 变亮(适用于发光);difference 创建迷幻效果;overlay 结合 multiply 和 screen 增加对比度。background-blend-mode 在同一元素上混合多个背景层(图像和渐变)。混合模式对于创意合成、双色调效果和文本覆盖图像叠加至关重要。isolation: isolate 创建新的混合上下文以包含混合效果。

css
/* mix-blend-mode: how element blends with backdrop */
.overlay {
  mix-blend-mode: multiply; /* darken */
}
.overlay-screen {
  mix-blend-mode: screen; /* lighten */
}
.overlay-difference {
  mix-blend-mode: difference; /* invert */
}

/* Common blend modes: multiply, screen, overlay,
   darken, lighten, color-dodge, color-burn,
   hard-light, soft-light, difference, exclusion,
   hue, saturation, color, luminosity */

/* background-blend-mode: blend background layers */
.gradient-texture {
  background-image: url(texture.png),
                    linear-gradient(45deg, red, blue);
  background-blend-mode: multiply;
}
14

容器查询

容器查询基础

容器查询允许组件响应其容器的尺寸而非视口。container-type: inline-size 使元素基于其内联(宽度)维度成为查询容器。@container 规则在容器匹配条件时应用样式。这对基于组件的设计是革命性的——卡片组件无论在侧边栏还是全宽主区域都能适应,与屏幕尺寸无关。这解决了媒体查询的基本限制,后者仅响应视口尺寸。

css
/* Define a container */
.card-container {
  container-type: inline-size;
  /* or: container-type: size; (both dimensions) */
}

/* Query the container's size */
@container (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 1fr 2fr;
  }
}

@container (max-width: 399px) {
  .card {
    display: flex;
    flex-direction: column;
  }
}

命名容器

命名容器允许在多个容器嵌套时针对特定容器。container-name 给容器一个标签;@container name (condition) 仅查询该容器。这防止了组件在不同容器上下文中嵌套时的冲突。container 简写结合名称和类型:container: panel / inline-size。命名容器对于多个独立容器查询共存的复杂布局至关重要。没有名称时,@container 查询最近的祖先容器。

css
/* Name a container for specific queries */
.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

.main-content {
  container-type: inline-size;
  container-name: main;
}

/* Query specific container by name */
@container sidebar (min-width: 300px) {
  .widget { display: grid; grid-template-columns: 1fr 1fr; }
}

@container main (min-width: 600px) {
  .article { columns: 2; }
}

/* Shorthand: container: name / type */
.panel {
  container: panel / inline-size;
}

容器查询单位

容器查询单位(cqw、cqh、cqmin、cqmax)类似于视口单位(vw、vh),但相对于查询容器而非视口。1cqw = 容器宽度的 1%。这实现了真正的组件响应式排版和间距——文本随组件宽度缩放,而非屏幕。结合 clamp(),可获得在容器尺寸内自适应且有 min/max 边界的流式排版。这非常适合组件必须在各种布局上下文中工作的设计系统。注意:cqh/cqmin/cqmax 需要 container-type: size(两个维度)。

css
.card {
  container-type: inline-size;
}

.card-title {
  /* cqw: 1% of container width */
  font-size: 5cqw;

  /* cqh: 1% of container height (needs size type) */
  padding: 2cqh;

  /* cqmin: 1% of smaller container dimension */
  margin: 2cqmin;

  /* cqmax: 1% of larger container dimension */
  border-radius: 1cqmax;
}

/* Fluid typography that responds to container */
.headline {
  font-size: clamp(1rem, 8cqw, 3rem);
}

容器样式查询

容器样式查询(实验性,截至 2025 年仅 Chromium 支持)允许查询容器上的自定义属性值,而不仅仅是尺寸。这实现了基于样式的条件渲染:组件可以根据其容器上设置的 --theme 变量更改外观。container-type: style(或样式查询不需要 container-type)启用此功能。这对主题化非常强大——在父元素上设置变量,所有子元素都会适应。完整的浏览器支持仍在进行中;使用渐进增强或 @supports 检查。

css
/* Query custom property values on container */
.card-wrapper {
  container-type: style;
  container-name: card;
}

@container card style(--theme: dark) {
  .card {
    background: #1a1a1a;
    color: #fff;
  }
}

@container card style(--theme: light) {
  .card {
    background: #fff;
    color: #333;
  }
}

/* Set the theme variable */
<div class="card-wrapper" style="--theme: dark">
  <div class="card">...</div>
</div>

响应式组件模式

此模式创建一个真正可重用、适应其放置位置的组件。产品卡片在窄容器中显示垂直布局,中等容器中显示水平布局,宽容器中显示 3 列网格。同一组件在侧边栏(窄)、网格(中)或英雄区域(宽)中工作,无需任何基于 prop 的条件逻辑。这是容器查询的杀手级用例——真正上下文独立的组件。结合容器查询单位用于排版,可获得完全自适应的组件。

css
/* Component that adapts to any container */
.product-card {
  container-type: inline-size;
  container-name: product;
}

.product-card .layout {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Medium container: horizontal layout */
@container product (min-width: 350px) {
  .product-card .layout {
    flex-direction: row;
  }
  .product-card .image {
    width: 40%;
  }
}

/* Large container: full feature layout */
@container product (min-width: 600px) {
  .product-card .layout {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr;
  }
  .product-card .actions {
    display: flex;
    flex-direction: column;
  }
}
15

滚动捕捉与滚动驱动动画

滚动捕捉基础

滚动捕捉创建将元素对齐到捕捉点的磁性滚动。scroll-snap-type: x/y 设置轴;mandatory 强制捕捉(总是落在点上);proximity 仅在接近时捕捉。scroll-snap-align: start/center/end 定义子元素在容器内捕捉的位置。全页滚动部分(如演示幻灯片)使用 y mandatory 配合 100vh 部分。水平轮播使用 x mandatory。始终在触摸设备上测试——如果内容高于视口,mandatory 捕捉可能感觉受限。使用 proximity 获得更宽容的行为。

css
/* Container with scroll snapping */
.gallery {
  scroll-snap-type: x mandatory;
  overflow-x: auto;
  display: flex;
  gap: 1rem;
}

/* Children snap to positions */
.gallery section {
  scroll-snap-align: start;
  flex: 0 0 100%;
  height: 300px;
}

/* Vertical snapping */
.full-page {
  scroll-snap-type: y mandatory;
  height: 100vh;
  overflow-y: scroll;
}
.full-page section {
  scroll-snap-align: start;
  height: 100vh;
}

带内边距的滚动捕捉

scroll-padding 使捕捉点从容器边缘偏移——当有固定页眉或希望在捕捉项周围留边距时很有用。scroll-snap-stop: always 防止快速滚动跳过多个项(强制逐项捕捉)。scroll-snap-align: center 将项捕捉到容器中心,创建封面流效果。这些属性对捕捉行为提供精细控制。对于图像轮播,结合 scroll-behavior: smooth 实现捕捉之间的动画过渡。

css
.carousel {
  scroll-snap-type: x mandatory;
  scroll-padding: 0 20px; /* offset snap points */
  overflow-x: auto;
  display: flex;
  gap: 1rem;
  padding: 0 20px;
}

.carousel .item {
  scroll-snap-align: start;
  scroll-snap-stop: always; /* don't skip items */
  flex: 0 0 80%;
}

/* Center-aligned snapping */
.carousel-center .item {
  scroll-snap-align: center;
  flex: 0 0 60%;
}

滚动驱动动画(animation-timeline)

滚动驱动动画(仅 CSS,无需 JS!)将动画链接到滚动位置。animation-timeline: scroll() 将动画绑定到页面滚动进度(顶部 0%,底部 100%)。animation-timeline: view() 将其绑定到元素进入/离开视口。animation-range 定义动画相对于滚动何时开始/结束(entry、exit、cover、contain)。这实现了无需 JavaScript 或滚动事件监听器的滚动进度条、滚动揭示和视差效果。Chrome 115+ 支持,其他浏览器建议渐进增强。

css
/* Animate as user scrolls */
@keyframes fade-in {
  from { opacity: 0; transform: translateY(50px); }
  to   { opacity: 1; transform: translateY(0); }
}

.reveal {
  animation: fade-in linear;
  animation-timeline: view();
  animation-range: entry 0% cover 40%;
}

/* Progress bar based on scroll position */
.progress-bar {
  position: fixed;
  top: 0; left: 0;
  height: 4px;
  background: #3498db;
  width: 100%;
  transform-origin: left;
  animation: grow linear;
  animation-timeline: scroll();
}

@keyframes grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

视图时间线范围

视图时间线范围精确控制动画何时发生。'entry' 是元素进入视口时;'exit' 是离开时;'cover' 跨越从进入开始到离开结束;'contain' 是元素完全可见时。百分比在每个范围内微调。animation-range: entry 10% entry 90% 表示动画从进入的 10% 运行到进入的 90%。对于粘性页眉,scroll() 配合像素范围(0 200px)基于绝对滚动距离动画。这用声明式 CSS 替代了复杂的 JavaScript 滚动处理程序。

css
/* Element animates as it enters viewport */
@keyframes slide-up {
  from { opacity: 0; transform: translateY(100px); }
  to   { opacity: 1; transform: translateY(0); }
}

.section {
  animation: slide-up linear both;
  animation-timeline: view();
  /* Ranges: entry, exit, cover, contain */
  animation-range: entry 10% entry 90%;
}

/* Sticky header that shrinks on scroll */
.header {
  position: sticky;
  top: 0;
  animation: shrink linear both;
  animation-timeline: scroll();
  animation-range: 0 200px;
}
@keyframes shrink {
  to { padding: 0.5rem 1rem; font-size: 0.9em; }
}

scroll-behavior 与平滑滚动

html(或任何滚动容器)上的 scroll-behavior: smooth 使锚点链接导航和 scrollIntoView() 平滑动画而非跳跃。这是 JavaScript 平滑滚动库的一行替代方案。始终尊重 prefers-reduced-motion——一些用户会感到晕动症,因此为他们禁用平滑滚动。scroll-snap-type: proximity(相对于 mandatory)与平滑滚动配合良好,获得自然感觉。scrollIntoView 配合 block: 'start'/'center'/'end' 控制目标的垂直对齐。

css
/* Smooth scrolling for anchor links */
html {
  scroll-behavior: smooth;
}

/* With scroll snap */
html {
  scroll-behavior: smooth;
  scroll-snap-type: y proximity;
}

/* Target specific elements */
.container {
  scroll-behavior: smooth;
  overflow-y: auto;
}

/* JavaScript: scroll to element */
<script>
document.querySelector(".section-3")
  .scrollIntoView({ behavior: "smooth", block: "start" });

/* Scroll to top */
window.scrollTo({ top: 0, behavior: "smooth" });
</script>

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
16

CSS 计数器

基础计数器

CSS 计数器无需 JavaScript 自动为元素编号。counter-reset 初始化计数器(在父元素或任何祖先上)。counter-increment 递增它(通常在被编号的元素上)。counter(name) 在 content 中显示当前值。计数器自动处理整个文档中的编号。这非常适合为标题、列表项、图形或任何顺序内容编号。计数器作用于重置它们的元素及其后代。

css
/* Initialize counter on parent */
body {
  counter-reset: section;
}

/* Increment and display */
h2::before {
  counter-increment: section;
  content: "Section " counter(section) ": ";
  color: #3498db;
  font-weight: bold;
}

/* Result: Section 1: Introduction, Section 2: Methods... */

嵌套计数器

嵌套计数器创建分层编号(1.1、1.2、2.1 等)。在父标题上重置子计数器(h2 上的 counter-reset: section)。每个 h2 开始新章节并重置 section 计数器。每个 h3 在当前章节内递增 section 计数器。content 属性结合多个 counter() 调用和分隔符。这反映了书籍和技术文档的编号方式。计数器基于 DOM 结构和重置点自然层叠。

css
body {
  counter-reset: chapter;
}

h2 {
  counter-reset: section;
  counter-increment: chapter;
}
h2::before {
  content: "Chapter " counter(chapter) ". ";
}

h3 {
  counter-increment: section;
}
h3::before {
  content: counter(chapter) "." counter(section) " ";
}

/* Result: Chapter 1.  / 1.1 / 1.2 / Chapter 2. / 2.1 ... */

计数器样式

counter() 接受样式参数:decimal(默认)、decimal-leading-zero(01、02)、lower/upper-alpha(a/b 或 A/B)、lower/upper-roman(i/ii 或 I/II)。@counter-style 定义具有循环符号、加法系统或符号表示法的自定义计数器样式。system: cyclic 重复符号;system: additive 创建类似罗马数字的系统。自定义计数器样式对于国际化列表、自定义项目符号或装饰性编号非常强大。@counter-style 在现代浏览器中支持良好。

css
/* Different number styles */
ol {
  counter-reset: item;
  list-style: none;
}
li::before {
  counter-increment: item;
  /* decimal, decimal-leading-zero, lower-alpha,
     upper-alpha, lower-roman, upper-roman */
  content: counter(item, upper-roman) ". ";
}

/* Leading zeros: 01, 02, 03... */
li::before {
  content: counter(item, decimal-leading-zero) ". ";
}

/* Custom @counter-style */
@counter-style thumbs {
  system: cyclic;
  symbols: "👍" "👎";
  suffix: " ";
}
.thumbs-list { list-style-type: thumbs; }

counters() 函数(嵌套)

counters() 函数(复数)返回完整的计数器路径作为字符串,级别由指定分隔符分隔。这自动处理嵌套计数器作用域——每个嵌套的 ol 创建新的计数器作用域。counters(nested, '.') 为深度嵌套的列表生成 1、1.1、1.1.1。这与仅显示当前级别的 counter() 不同。使用 counters() 实现嵌套列表的大纲式编号、目录或分层菜单。分隔符字符串可以是任何字符(. , - > 等)。

css
/* counters() creates full path string */
ol {
  counter-reset: nested;
  list-style: none;
}
li::before {
  counter-increment: nested;
  /* counters() returns all levels separated by a string */
  content: counters(nested, ".") " - ";
  font-weight: bold;
}

/* For nested <ol> elements:
   1 - Top level
   1.1 - Nested
   1.1.1 - Deeper
   2 - Top level again
*/

图形与表格计数器

计数器非常适合在文档中为图形、表格和公式自动编号。按章节重置(h2 上的 counter-reset)使编号每章重新开始。figcaption/caption 上的 ::before 伪元素前置编号。这确保了一致的自动编号,在内容重新排序时更新。对于交叉引用('见图 3'),CSS 计数器无法直接帮助——需要 JS 或 HTML 锚点。但对于显示编号,这是一个干净、免维护的解决方案。

css
body {
  counter-reset: figure table;
}

figure figcaption::before {
  counter-increment: figure;
  content: "Figure " counter(figure) ": ";
  font-weight: bold;
  color: #2c3e50;
}

table caption::before {
  counter-increment: table;
  content: "Table " counter(table) ": ";
  font-weight: bold;
  color: #2c3e50;
}

/* Reset figure counter per chapter */
h2 {
  counter-reset: figure;
}
18

深色模式与配色方案

prefers-color-scheme

prefers-color-scheme: dark 检测用户的操作系统/浏览器深色模式偏好。在 :root 中定义浅色模式的主题变量,然后在深色媒体查询中覆盖它们。使用 CSS 变量意味着只需更改变量值——所有组件自动更新。这是深色模式的标准方法。媒体查询还支持 'light' 和 'no-preference'。通过切换操作系统深色模式或使用 Chrome DevTools 的 Rendering 选项卡(Emulate CSS prefers-color-scheme)测试。

css
/* Light mode (default) */
:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --surface: #f5f5f5;
  --border: #e0e0e0;
  --accent: #3498db;
}

/* Dark mode */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a1a;
    --text: #e0e0e0;
    --surface: #2a2a2a;
    --border: #404040;
    --accent: #5dade2;
  }
}

body {
  background: var(--bg);
  color: var(--text);
}

手动主题切换

对于手动主题切换,在 <html> 上使用 data-theme 属性覆盖系统偏好。将用户选择存储在 localStorage 中以持久化。页面加载时,在渲染前检查 localStorage 以避免错误主题的闪烁(FOUC)。color-scheme: light dark 告诉浏览器以适当的方案渲染原生 UI 元素(滚动条、表单控件)。为获得最佳用户体验,当没有保存的选择时默认为系统偏好:检查 matchMedia('(prefers-color-scheme: dark)') 作为回退。

css
/* Default to system preference, allow override */
:root {
  color-scheme: light dark;
}

/* Manual dark mode via data attribute */
[data-theme="dark"] {
  --bg: #1a1a1a;
  --text: #e0e0e0;
}

[data-theme="light"] {
  --bg: #ffffff;
  --text: #1a1a1a;
}

/* Toggle button */
<button onclick="toggleTheme()">Toggle Theme</button>
<script>
function toggleTheme() {
  const current = document.documentElement.dataset.theme;
  const next = current === "dark" ? "light" : "dark";
  document.documentElement.dataset.theme = next;
  localStorage.setItem("theme", next);
}
// Load saved preference
const saved = localStorage.getItem("theme");
if (saved) document.documentElement.dataset.theme = saved;
</script>

color-scheme 属性

color-scheme 属性告诉浏览器页面支持哪些配色方案,影响原生 UI 元素:滚动条、表单控件(输入、按钮、下拉菜单)、默认背景/画布颜色和 ::placeholder 颜色。没有它,即使在深色模式下表单控件也可能显示为浅色(刺眼的不匹配)。在 :root 上设置 color-scheme: light dark 让原生元素自动适应。这是一行修复,可显著改善深色模式的精致度。它与 CSS 变量主题化分开——它仅影响浏览器原生渲染。

css
:root {
  /* Tell browser this page supports both schemes */
  color-scheme: light dark;
}

/* Force light only */
.light-only {
  color-scheme: light;
}

/* Force dark only */
.dark-only {
  color-scheme: dark;
}

/* This affects native UI: scrollbars, form controls,
   default colors (canvas, text), and form elements */
input, textarea, select {
  /* Will use dark form controls in dark mode */
  color-scheme: dark;
}

深色模式图像与媒体

图像在深色模式中需要特殊处理。白底图表可以用 filter: invert(1) hue-rotate(180deg) 反转——hue-rotate 防止颜色失真。人物照片不应反转。略微降低亮度以减少眼睛疲劳。对于徽标和图标,使用 <picture> 配合媒体查询源以提供深色优化版本。带 currentColor 的 SVG 自动适应。对于背景图像,通过媒体查询提供深色模式替代。始终在两种模式下测试图像的可读性。

css
@media (prefers-color-scheme: dark) {
  /* Invert images that are essentially white-background */
  img[src*="logo"],
  img[src*="diagram"] {
    filter: invert(1) hue-rotate(180deg);
  }

  /* Reduce brightness of photos */
  img.photo {
    filter: brightness(0.85);
  }

  /* Don't invert photos with people */
  img[src*="photo"]:not(.invertable) {
    filter: none;
  }
}

/* Use dark-mode-friendly SVG */
<picture>
  <source srcset="logo-dark.svg"
          media="(prefers-color-scheme: dark)">
  <img src="logo-light.svg" alt="Logo">
</picture>

平滑主题过渡

为所有元素添加颜色过渡可创建平滑的主题切换动画。然而,这可能导致初始页面加载时出现动画颜色闪烁。解决方案:在主题切换和初始加载期间向 <html> 添加 .no-transition 类,然后在一帧后移除它。始终尊重 prefers-reduced-motion 以禁用请求减少动画的用户的过渡。要有选择性——过渡所有属性可能影响性能。仅过渡与颜色相关的属性(background-color、color、border-color、box-shadow)。

css
/* Transition colors when theme changes */
* {
  transition: background-color 0.3s ease,
              color 0.3s ease,
              border-color 0.3s ease;
}

/* But not during initial load (prevent flash) */
.no-transition * {
  transition: none !important;
}

<script>
// Disable transitions during theme switch
function toggleTheme() {
  document.documentElement.classList.add("no-transition");
  document.documentElement.dataset.theme = newTheme;
  // Re-enable after switch
  requestAnimationFrame(() => {
    document.documentElement.classList.remove("no-transition");
  });
}
</script>

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}
19

CSS 函数深入解析

clamp()、min()、max()

clamp(min, preferred, max) 是流式排版和间距的圣杯——它随首选值缩放但永不超过 min/max 边界。min() 选择较小值(非常适合响应式 max-width)。max() 选择较大值(非常适合最小尺寸)。这些通过提供连续的流式缩放消除了许多媒体查询。clamp 中的首选值通常使用视口单位(vw、vh)或容器单位(cqw)。这是无断点响应式设计的现代方法。

css
/* clamp(min, preferred, max) */
h1 {
  font-size: clamp(1.5rem, 5vw, 3rem);
  /* Never smaller than 1.5rem, never larger than 3rem,
     preferred is 5vw */
}

/* min(): use the smaller value */
.container {
  width: min(100% - 2rem, 1200px);
  /* Full width minus padding, but max 1200px */
}

/* max(): use the larger value */
.hero {
  font-size: max(2rem, 4vw);
  /* At least 2rem, grows with viewport */
}

/* Combining for responsive padding */
.card {
  padding: clamp(1rem, 3vw, 2rem);
}

calc() 高级

calc() 使用混合单位(px、%、em、vw 等)执行计算。加法和减法要求运算符周围有空格(calc(100% - 20px),而非 calc(100%-20px))。乘法和除法仅适用于数字,不适用于长度(calc(10px * 2) 有效;calc(10px * 10px) 无效)。calc() 可以嵌套但括号也可工作。结合 CSS 变量,calc() 实现动态、计算的设计系统。它对结合固定和流式尺寸的响应式布局至关重要。

css
/* Mixed units */
.sidebar {
  width: calc(100% - 250px); /* full width minus fixed sidebar */
  height: calc(100vh - 60px); /* viewport minus header */
}

/* Nested calc */
.element {
  margin: calc(calc(100% - 50px) / 2);
  /* Simplified: */
  margin: calc((100% - 50px) / 2);
}

/* With CSS variables */
:root { --gap: 20px; }
.grid {
  gap: calc(var(--gap) * 2);
}

/* Math operations: + - * / */
.padding {
  padding: calc(1rem + 2px);
  width: calc(50% - 10px);
}

attr() 函数

attr() 检索 HTML 属性值,最常用于伪元素的 content 中。它是纯 CSS 工具提示的基础(data-tooltip 属性 → ::after content)。attr() 仅在 content 属性中可靠工作。在其他属性(width、color 等)中使用带类型转换的 attr()(attr(data-size px))是 CSS Values Level 5 的一部分,但浏览器支持极少。目前,使用 CSS 变量从 HTML 获取动态值:设置 style='--size: 100px' 并使用 var(--size)。

css
/* Display attribute values */
a[href]::after {
  content: attr(href);
}

/* data attributes for tooltips */
.tooltip::after {
  content: attr(data-tooltip);
  display: none;
  position: absolute;
}
.tooltip:hover::after {
  display: block;
}

/* HTML: <div class="tooltip" data-tooltip="Help text">?</div> */

/* Note: attr() for non-content properties is experimental */
/* This doesn't work widely yet: */
/* .box { width: attr(data-width px); } */

带回退的 var()

var() 接受回退作为第二个参数,在变量未定义时使用。回退可以链式调用:var(--a, var(--b, var(--c, default)))。这实现了渐进增强和多级主题化。空变量值(--defined: ;)仍然是'已设置'的,因此回退不会触发——这实现了条件 CSS 模式。回退可以包含任何有效的 CSS 值,包括 calc() 和其他函数。为可能未在所有上下文中定义的可选主题变量使用回退。

css
/* Single fallback */
color: var(--text-color, #333);

/* Chained fallbacks */
color: var(--text, var(--default-text, black));

/* Fallback in shorthand */
background: var(--bg, white) url(image.png);

/* Fallback with calc */
width: calc(100% - var(--sidebar, 250px));

/* Check if variable is set */
:root {
  --defined: ; /* empty space = valid value */
}
.conditional {
  --use-default: var(--defined, initial);
  /* If --defined is empty, --use-default = initial */
}

渐变函数

CSS 渐变无需图像即可创建颜色之间的平滑过渡。linear-gradient(方向 + 颜色)、radial-gradient(从中心向外)和 conic-gradient(围绕一点旋转)是三种类型。硬停止(两种颜色相同百分比)创建锐利条带。repeating-linear-gradient 创建条纹等图案。渐变可以与多个背景分层(逗号分隔,第一个 = 顶层)。圆锥渐变实现了纯 CSS 的饼图和色轮。渐变与分辨率无关,性能优于图像文件。

css
/* Linear gradient */
.bg { background: linear-gradient(45deg, #3498db, #e74c3c); }
.bg2 { background: linear-gradient(to right, red, orange, yellow); }

/* Radial gradient */
.radial { background: radial-gradient(circle, white, blue); }
.radial2 { background: radial-gradient(circle at top left, #fff, #000); }

/* Conic gradient */
.pie { background: conic-gradient(red 0% 30%, blue 30% 70%, green 70% 100%); }

/* Repeating gradients */
.stripes { background: repeating-linear-gradient(45deg, #ccc 0 10px, #fff 10px 20px); }

/* Hard color stops (sharp edges) */
.hard { background: linear-gradient(to right, #000 50%, #fff 50%); }

/* Multiple backgrounds */
.multi {
  background:
    linear-gradient(rgba(0,0,0,0.5), transparent),
    url(photo.jpg);
}
20

CSS 变量

定义与使用变量

CSS 自定义属性(变量)使用 --name 定义,使用 var() 使用。在 :root 上声明以全局访问。与 Sass 变量不同,它们是实时的——通过 JavaScript 更改变量会立即更新使用它的每个元素。

css
:root {
  --primary: #3498db;
  --spacing: 16px;
  --radius: 8px;
}

.button {
  background: var(--primary);
  padding: var(--spacing);
  border-radius: var(--radius);
}

回退值

var() 接受第二个参数作为变量未定义时的回退。回退可以嵌套,允许链式默认值。对于不支持自定义属性的浏览器,先声明正常值,然后用 var() 覆盖。

css
.box {
  color: var(--brand, #333);
  background: var(--bg, var(--default-bg, white));
}

/* Provide fallback for older browsers */
.element {
  color: #333;
  color: var(--text-color, #333);
}

JavaScript 交互

JavaScript 通过 getComputedStyle().getPropertyValue() 读取变量,通过 setProperty() 设置变量。这使运行时主题化变得简单——翻转几个变量即可重新设置整个应用的样式。

css
// Read a variable
const color = getComputedStyle(document.documentElement)
  .getPropertyValue('--primary');

// Set a variable on an element
document.documentElement.style.setProperty('--primary', '#e74c3c');

// Toggle a theme
document.documentElement.setAttribute('data-theme', 'dark');

作用域与继承

自定义属性会继承,因此在 :root 上设置的变量层叠到每个元素。在 .card 上重新定义它仅覆盖该子树。这种作用域实现了组件级主题化,无需优先级之争。

css
:root { --size: 16px; }

.card {
  --size: 20px; /* Overrides only within .card */
  font-size: var(--size);
}

.card .text { font-size: var(--size); } /* 20px */
.other { font-size: var(--size); }       /* 16px */

响应式变量

在媒体查询内重新定义变量,使整个布局响应断点而无需重写规则。更改一个变量,使用它的每个元素都会适应——比单独覆盖每个属性干净得多。

css
:root {
  --container-width: 1200px;
  --font-size: 18px;
}

@media (max-width: 768px) {
  :root {
    --container-width: 100%;
    --font-size: 16px;
  }
}

.container { max-width: var(--container-width); }
body { font-size: var(--font-size); }
21

动画与关键帧

@keyframes 与 animation 简写

@keyframes 定义动画的开始(from/0%)和结束(to/100%)状态。animation 简写结合 name、duration、timing-function、delay、iteration-count、direction、fill-mode 和 play-state。forwards 保持最终状态。

css
@keyframes slide-in {
  from { transform: translateX(-100%); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}

.element {
  animation: slide-in 0.5s ease-out forwards;
}

/* Shorthand: name duration timing delay count direction fill-mode */
.bounce {
  animation: bounce 1s cubic-bezier(0.68, -0.55, 0.27, 1.55) 0s infinite alternate;
}

过渡

过渡在属性值变化时平滑插值。指定哪些属性过渡及其持续时间/计时函数。transition: all 方便但可能损害性能——优先列出特定属性。

css
.button {
  background: blue;
  transition: background 0.3s ease, transform 0.2s ease-out;
}

.button:hover {
  background: darkblue;
  transform: scale(1.05);
}

/* Transition all changed properties */
.card { transition: all 0.3s ease; }

计时函数

计时函数控制加速度曲线。ease-out 开始快然后减速(适合入场);ease-in 开始慢然后加速(适合出场)。cubic-bezier 让你制作自定义曲线。steps() 创建离散效果。

css
/* Built-in */
.ease-linear { transition: all 1s linear; }
.ease-out    { transition: all 1s ease-out; }

/* Custom cubic-bezier(x1, y1, x2, y2) */
.custom { transition: all 1s cubic-bezier(0.68, -0.55, 0.27, 1.55); }

/* Steps */
.steps { transition: all 1s steps(5, end); }

动画事件

JavaScript 可以监听 animationstart、animationiteration(每次循环触发)和 animationend。使用 animation-play-state 属性(paused/running)控制播放。结合 animationend 链式动画。

css
const el = document.querySelector('.animate');
el.addEventListener('animationstart', () => console.log('Started'));
el.addEventListener('animationiteration', () => console.log('Looped'));
el.addEventListener('animationend', () => console.log('Finished'));

// Pause and resume
el.style.animationPlayState = 'paused';
el.style.animationPlayState = 'running';

性能:transform 与 opacity

仅动画化 transform 和 opacity 以获得 60fps 性能——它们在 GPU 上运行而不触发布局。动画化 width、height、top 或 margin 会强制每帧重新计算布局。谨慎使用 will-change 提示浏览器。

css
/* GOOD: GPU-accelerated, cheap */
.fade { transition: opacity 0.3s; }
.move { transition: transform 0.3s; }

/* BAD: triggers layout/paint, expensive */
.resize { transition: width 0.3s, height 0.3s; }

/* Hint the browser to optimize */
.card { will-change: transform; }
22

3D 变换

2D 变换

2D 变换移动、旋转、缩放和扭曲元素而不影响周围布局。变换在 GPU 上合成,使其在动画中性能良好。顺序很重要:先旋转再平移会沿旋转后的轴移动。

css
.box { transform: translate(50px, 20px); }
.box { transform: rotate(45deg); }
.box { transform: scale(1.5); }
.box { transform: skew(20deg, 10deg); }

/* Combined — order matters */
.combo { transform: translate(100px, 0) rotate(90deg) scale(1.2); }

3D 变换与透视

3D 变换添加 rotateX、rotateY、rotateZ、translateZ 和 scaleZ。父元素上的 perspective 为所有子元素提供共享消失点——值越低 3D 效果越夸张。transform-style: preserve-3d 保持嵌套元素在 3D 中。

css
.scene { perspective: 1000px; }

.card {
  transform: rotateY(45deg);
  transform-style: preserve-3d;
}

/* Perspective on the element itself */
.self { transform: perspective(800px) rotateX(30deg); }

/* Transform origin */
.pivot { transform-origin: top left; transform: rotate(45deg); }

翻转卡片效果

经典翻转卡片在容器上使用 preserve-3d,正面和背面绝对定位。backface-visibility: hidden 隐藏每个面的背面。背面预旋转 180deg,因此在容器翻转时显示。

css
.card { perspective: 1000px; }
.inner {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.6s;
}
.card:hover .inner { transform: rotateY(180deg); }
.front, .back {
  position: absolute;
  backface-visibility: hidden;
}
.back { transform: rotateY(180deg); }

六面立方体

3D 立方体由六个面构建,每个面沿其轴向外平移 50px(立方体宽度的一半)。preserve-3d 使面在 3D 空间中定位。动画化立方体变换使其旋转。

css
.cube {
  position: relative;
  width: 100px; height: 100px;
  transform-style: preserve-3d;
  transform: rotateX(-20deg) rotateY(30deg);
}
.face { position: absolute; width: 100px; height: 100px; }
.front  { transform: translateZ(50px); }
.back   { transform: rotateY(180deg) translateZ(50px); }
.right  { transform: rotateY(90deg) translateZ(50px); }
.left   { transform: rotateY(-90deg) translateZ(50px); }
.top    { transform: rotateX(90deg) translateZ(50px); }
.bottom { transform: rotateX(-90deg) translateZ(50px); }

矩阵与性能

matrix() 和 matrix3d() 将任何变换表示为单个矩阵——在 JavaScript 中计算变换时很有用。translateZ(0) 或 will-change: transform 强制 GPU 加速,提高动画平滑度。避免过度使用图层。

css
/* matrix(a, b, c, d, e, f) encodes translate, rotate, scale, skew */
.transformed { transform: matrix(1, 0, 0, 1, 100, 50); }

/* 3D matrix */
.cube { transform: matrix3d(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1); }

/* Hardware acceleration hint */
.gpu { transform: translateZ(0); }
23

CSS Grid 高级

Grid 模板区域

grid-template-areas 可视化命名网格单元格,使布局意图明显。每个引号行代表一个网格行;相同名称跨越单元格。空单元格使用点(.)。区域必须形成矩形——L 形无效。

css
.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  gap: 16px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main   { grid-area: main; }
.footer { grid-area: footer; }

minmax 与 auto-fit

repeat(auto-fit, minmax(200px, 1fr)) 创建无需媒体查询的响应式网格:列至少 200px 并拉伸以填充行。auto-fit 折叠空轨道;auto-fill 保留它们。

css
.grid {
  display: grid;
  /* Columns auto-fit, each at least 200px, sharing leftover space */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

/* Fixed number that wraps */
.wrap {
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}

Grid 对齐

Grid 对齐在两个级别工作:容器(justify/align-items 和 justify/align-content)和项目(justify/align-self)。justify-* 控制内联轴,align-* 控制块轴。place-items: center 是两者的简写。

css
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  justify-items: center;
  align-items: center;
  justify-content: space-between;
  align-content: center;
}

.item {
  justify-self: end;
  align-self: start;
}

跨越与行线放置

按网格行号放置项目(1 / 3 表示从第 1 行到第 3 行)或按跨度(span 2)。负行号从末尾计数(-1 是最后一行)。grid-column: 1 / -1 使项目跨越全宽。

css
.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.header { grid-column: 1 / -1; }       /* full width */
.sidebar { grid-column: 1 / 3; }       /* columns 1-2 */
.main { grid-column: span 2; }          /* span 2 columns */
.tall { grid-row: 1 / span 2; }         /* span 2 rows */

子网格

subgrid 让子网格继承父轨道定义,使列或行在嵌套网格之间完美对齐。没有 subgrid,嵌套网格定义自己的轨道并可能错位。自 2023 年起所有现代浏览器支持。

css
.card {
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* Inherit column tracks from parent */
  grid-template-columns: subgrid;
  grid-column: span 3;
}

.parent {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
}
24

CSS 函数

calc()

calc() 对混合单位(px、%、vw、em、rem)执行数学运算。始终在 + 和 - 周围加空格(calc(100%-20px) 失败;calc(100% - 20px) 有效)。乘法和除法需要一侧是无单位数字。

css
.sidebar {
  width: calc(100% - 250px);
  padding: calc(16px + 2vw);
  font-size: calc(14px + 0.5vw);
}

/* Nested calc */
.full { width: calc(calc(100% - 20px) / 2); }

/* With variables */
.box { margin: calc(var(--gap) * 2); }

clamp()

clamp() 将值限制在最小值和最大值之间,中间有首选值。这是构建流式排版和间距的最干净方式——值会缩放但永不低于或高于边界。

css
/* clamp(MIN, PREFERRED, MAX) */
h1 {
  font-size: clamp(1.5rem, 4vw, 3rem);
}

.sidebar {
  width: clamp(200px, 25vw, 400px);
}

.padding {
  padding: clamp(1rem, 2vw + 1rem, 2rem);
}

min() 与 max()

min() 返回最小参数;max() 返回最大。与 clamp(恰好接受三个值)不同,min/max 接受任意数量的参数。使用 min() 限制值上限,max() 限制值下限。

css
/* Picks the smallest/largest of comma-separated values */
.box {
  width: min(100% - 32px, 800px);
  font-size: max(16px, 2vw);
}

/* With multiple units */
.responsive {
  padding: min(5vw, 2rem);
  margin: max(1rem, 3vw);
}

带回退的 var()

var() 的第二个参数仅在自定义属性未定义时使用。对于无效值,属性回退到其继承或初始值。嵌套 var() 调用以链式回退。

css
.button {
  background: var(--btn-bg, #007bff);
  color: var(--text, var(--default-text, black));
  width: var(--width, 100%);
}

color-mix() 与颜色函数

color-mix() 在指定颜色空间(srgb、oklch、lab)中混合两种颜色。这是从品牌色派生色调和阴影的现代方式。相对颜色语法(from 关键字)允许调整各个通道。

css
/* Mix two colors */
.muted { color: color-mix(in srgb, red 30%, blue); }

/* Adjust relative lightness */
.lighter { background: color-mix(in oklch, var(--brand) 70%, white); }
.darker  { background: color-mix(in oklch, var(--brand) 70%, black); }

/* Relative color syntax (newest) */
.tint { background: oklch(from var(--brand) calc(l + 0.1) c h); }
25

滚动驱动动画

animation-timeline 基础

animation-timeline: scroll(root) 将动画绑定到页面滚动位置——用户滚动时动画推进。无需 JavaScript。这比滚动事件监听器平滑得多。

css
@keyframes grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.progress-bar {
  animation: grow linear;
  animation-timeline: scroll(root);
  transform-origin: left;
}

view() 时间线

view() 创建绑定到元素进入和离开视口的时间线。animation-range 控制条目的哪一部分触发动画。非常适合无需 IntersectionObserver 的滚动揭示效果。

css
@keyframes reveal {
  from { opacity: 0; transform: translateY(40px); }
  to   { opacity: 1; transform: translateY(0); }
}

.card {
  animation: reveal linear;
  animation-timeline: view();
  animation-range: entry 0% entry 100%;
}

滚动链接进度条

固定进度条随页面滚动而填充。animation-timeline: scroll(root) 将页面滚动映射到动画 0-100% 范围。transform-origin: 0 50% 使条从左侧增长。

css
body { min-height: 200vh; }
.progress {
  position: fixed;
  top: 0; left: 0;
  height: 4px;
  width: 100%;
  background: linear-gradient(to right, #6366f1, #ec4899);
  transform-origin: 0 50%;
  animation: scale-x linear;
  animation-timeline: scroll(root);
}
@keyframes scale-x {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

命名滚动时间线

当需要将动画绑定到特定可滚动元素(而非根)时,在容器上定义 scroll-timeline-name 并在 animation-timeline 中引用它。scroll-timeline-axis 选择跟踪哪个轴(block/inline/x/y)。

css
.scroll-container {
  scroll-timeline-name: --cards;
  scroll-timeline-axis: block;
  overflow-y: scroll;
  height: 400px;
}

.card {
  animation: fade-in linear;
  animation-timeline: --cards;
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

视图范围调整

animation-range 微调动画相对于元素可见性的运行时间。cover 0% 到 cover 100% 跨越从元素进入直到完全离开。contain 0% 到 100% 仅在完全可见时跨越。

css
.image {
  animation: parallax linear;
  animation-timeline: view();
  animation-range: cover 0% cover 100%;
}

@keyframes parallax {
  from { transform: translateY(-20%); }
  to   { transform: translateY(20%); }
}

/* Only animate while in view */
.pulse {
  animation: pulse 1s infinite;
  animation-timeline: view();
  animation-range: contain 0% contain 100%;
}
26

CSS 层

定义 @layer

@layer 将样式分组到命名的层叠层中。声明行中的顺序设置优先级:后面的层优先于前面的层,无论选择器优先级如何。这为大型样式表带来了可预测的排序。

css
@layer reset, base, components, utilities;

@layer reset {
  * { margin: 0; padding: 0; box-sizing: border-box; }
}

@layer base {
  body { font-family: sans-serif; line-height: 1.6; }
}

@layer utilities {
  .hidden { display: none !important; }
}

层优先级

在层内,正常优先级规则适用。但在层之间,后面的层总是胜出——components 中的单个类胜过 base 中的 ID。未分层的样式优先于所有分层的样式。

css
@layer base, components;

@layer base {
  /* Even though this is more specific, base loses */
  div.button { color: black; }
}

@layer components {
  .button { color: blue; } /* This wins */
}

/* Unlayered styles always beat layered styles */
.button { color: red; }

导入到层中

@import ... layer(name) 将整个样式表放入命名层。这对驯服第三方 CSS 至关重要:将 Bootstrap 放入 vendor 层,你的自定义样式(在后面的层或未分层)将总是胜出。

css
@import url("reset.css") layer(reset);
@import url("bootstrap.css") layer(vendor);

@layer reset, vendor, custom;

@layer custom {
  .btn { background: hotpink; }
}

嵌套层

层可以嵌套,创建层次结构。framework.theme 指 framework 内部的 theme 子层。嵌套层遵循相同的优先级规则:在 framework 内,theme 胜过 base。

css
@layer framework {
  @layer base, theme;

  @layer base {
    .btn { padding: 8px; }
  }
  @layer theme {
    .btn { color: navy; }
  }
}

/* Reference nested layer */
@layer framework.theme {
  .btn { color: hotpink; }
}

层条件逻辑

@layer 块可以嵌套在 @media 和 @supports 内,因此层成员资格适应条件。这使特定功能的样式保持在其层内组织,而非泄漏到未分层空间。

css
@layer base, components;

@media (max-width: 600px) {
  @layer components {
    .nav { flex-direction: column; }
  }
}

@supports (display: grid) {
  @layer components {
    .layout { display: grid; }
  }
}
27

背景滤镜

backdrop-filter 基础

backdrop-filter 对元素后面的内容应用滤镜,创建磨砂玻璃效果。始终包含 -webkit- 前缀以支持 Safari。结合半透明背景使模糊可见。

css
.glass {
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 12px;
}

多个滤镜

链式多个滤镜用空格分隔:blur、brightness、contrast、grayscale、hue-rotate、invert、opacity、saturate、sepia。每个都应用于背景。搭配着色背景引导氛围。

css
.vibrant {
  backdrop-filter: blur(8px) saturate(180%) brightness(1.1);
}

.dark-glass {
  background: rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(12px) grayscale(50%);
}

混合模式

mix-blend-mode 控制元素如何与其下方内容混合(与 backdrop-filter 分开)。multiply 变暗,screen 变亮,difference 反转。注意文本可读性。

css
.overlay {
  background: rgba(255, 0, 100, 0.3);
  backdrop-filter: blur(4px);
  mix-blend-mode: multiply;
}

.difference {
  background: white;
  mix-blend-mode: difference;
  backdrop-filter: invert(1);
}

性能与回退

backdrop-filter 是 GPU 密集型的,尤其是大模糊半径时。为不支持的浏览器提供纯色背景回退,然后用 @supports 增强。避免动画化 backdrop-filter——可能导致严重卡顿。

css
/* Fallback for unsupported browsers */
.glass {
  background: rgba(255, 255, 255, 0.9);
}

/* Progressive enhancement */
@supports (backdrop-filter: blur(10px)) {
  .glass {
    background: rgba(255, 255, 255, 0.2);
    backdrop-filter: blur(10px);
  }
}

毛玻璃卡片

经典毛玻璃卡片结合半透明背景、背景模糊、细微的浅色边框(模拟边缘反射)和柔和阴影。saturate 滤镜增强透过玻璃看到的颜色。

css
.card {
  background: rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

这篇内容对您有帮助吗?

学习路径

从零开始学习

通过结构化课程从头学习这个语言。