选择器
基础选择器
CSS 选择器用于定位 HTML 元素以应用样式。类型选择器匹配元素名称(p、div)。类选择器(.)匹配 class 属性且可重复使用。ID 选择器(#)匹配单个元素且应唯一。通配选择器(*)匹配所有元素。使用逗号分组选择器以共享样式。
/* 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; }组合器
组合器定义元素之间的关系。后代组合器(空格)匹配任意嵌套元素。子代组合器(>)仅匹配直接子元素。相邻兄弟组合器(+)匹配紧随其后的元素。通用兄弟组合器(~)匹配之后的所有兄弟元素。理解组合器对于无需额外类即可精确设置样式至关重要。
/* 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 属性的元素设置样式时非常强大,无需添加额外类。
/* 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 个元素。这些减少了额外类的需求。
/* 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 以获得块级行为。
/* 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——应避免使用。
/* 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; }盒模型
外边距与内边距
每个元素都是一个盒子,包含内容、内边距、边框和外边距。内边距在边框内部(影响背景),外边距在外部(透明)。简写:1 个值 = 所有边,2 个值 = 上/下 左/右,3 个 = 上 左/右 下,4 个 = 上 右 下 左(顺时针)。margin: 0 auto 使具有定义宽度的块级元素水平居中。
.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 在边框和轮廓之间添加间距。始终为可访问性提供可见的焦点样式。
.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 重置之一。
/* 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 创建自然融合的半透明阴影。阴影非常适合营造深度,但过度使用会损害性能——优先使用细微的阴影。
/* 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 切换内容。
/* 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; }颜色与单位
颜色格式
CSS 支持多种颜色格式。Hex(#rrggbb)最常见。RGB/RGBA 添加 alpha 透明度。HSL(色相 0-360,饱和度%,亮度%)很直观——改变色相切换颜色,改变亮度调整明暗。currentColor 继承元素的 color 属性。现代 CSS 还支持 oklch() 和 color() 以获得更宽的色域。使用 rgba/hsla 实现透明度。
/* 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 用于边框/精细细节。
/* 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 无需媒体查询即可实现动态效果。
/* 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 的地方使用。
/* 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 对元素后面的区域应用滤镜(非常适合毛玻璃效果)。滤镜可能影响性能——谨慎使用。
/* 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;
}排版
字体属性
font-family 接受回退列表——浏览器使用第一个可用的字体。始终以通用字体系列结尾(serif、sans-serif、monospace)。font-weight 范围从 100(细)到 900(粗)。line-height: 1.5 表示 1.5 倍字体大小——1.4-1.6 最适合正文可读性。font 简写必须至少包含 size 和 family。
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 对齐(块级)。
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 才能使截断生效。
/* 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> 提供托管字体。预加载关键字体以提高性能。
@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。这确保了链接状态的正确层叠。
/* 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; }Flexbox 布局
Flex 容器
display: flex 创建一个 flex 容器。justify-content 沿主轴对齐项目(row 中为水平方向)。align-items 沿交叉轴对齐(垂直方向)。flex-direction 改变主轴方向。flex-wrap 允许项目换行到新行。gap 设置项目之间的间距(替代外 边距 hack)。Flexbox 非常适合一维布局(行或列)。
.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 的情况下视觉重排项目。
.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 出现之前难以处理的常见布局问题。
/* 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 时有效)。此模式创建响应式卡片网格。
/* 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 对齐的关键。
.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 */
}CSS Grid 布局
Grid 容器
display: grid 创建二维布局。grid-template-columns 定义列大小:fr 单位按比例分配可用空间。repeat(3, 1fr) 创建 3 个等宽列。repeat(auto-fit, minmax(250px, 1fr)) 创建自动调整列数的响应式网格——这是响应式网格的'圣杯'。gap 替代外边距用于间距。
.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 允许精确的二维放置——项目可以同时跨越行和列。
.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 设置为匹配的名称来放置项目。这是创建复杂布局最易读的方式。使用 '.' 表示空单元格。相同的名称可以跨越多个单元格。在媒体查询中更改区域以实现响应式布局。
.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 组合两种内容对齐。
.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 可获得最佳效果。
/* 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 */定位
定位类型
static 是默认值(正常文档流)。relative 相对于其正常位置偏移且不影响其他元素(创建定位上下文)。absolute 从文档流中移除并相对于最近的已定位祖先定位。fixed 相对于视口定位(滚动时保持)。sticky 在 relative 和 fixed 之间切换——正常滚动然后在阈值处固定。
/* 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%)。绝对定位将元素从正常文档流中移除。
/* 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 以防止重叠问题。
/* 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 的兄弟元素之上。这是常见的混淆来源。
/* 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。
/* 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 */响应式设计
媒体查询
媒体查询根据条件应用样式。min-width(移动优先)是首选——基础样式针对移动设备,然后为更大屏幕增强。max-width(桌面优先)则相反。其他条件:prefers-color-scheme(深色/浅色)、print、orientation(纵向/横向)、prefers-reduced-motion。始终在 HTML 中设置 viewport meta 标签,媒体查询才能在移动设备上工作。
/* 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 以保证可读性。
/* 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 在容器满足条件时应用样式。这比媒体查询更模块化——组件适应其容器而非屏幕。非常适合在不同布局上下文中可重用的组件。
/* 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 在固定尺寸内裁剪图像。
/* 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。
/* 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 */过渡与动画
过渡
transition 在属性值之间创建平滑变化。语法:transition: property duration timing-function delay。计时函数:ease(默认)、linear、ease-in、ease-out、ease-in-out、cubic-bezier()。只有可动画属性才能过渡。避免 transition: all(性能问题)。过渡在伪类变化(:hover、:focus)或通过 JavaScript 更改类时触发。
.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 改变旋转中心点。
.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 保持最终状态。动画自动运行,不同于过渡。
@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;。
.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——一些用户会感到晕动症或有前庭障碍。为这些用户提供即时过渡或禁用动画。
/* 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;
}
}变量与高级函数
自定义属性(变量)
自定义属性(CSS 变量)存储可重用的值。在 :root 中定义以全局访问。使用 var(--name) 引用。它们层叠并可在任何作用域中被覆盖——非常适合主题化(深色/浅色模式)。与预处理器变量不同,它们是动态的(在运行时更改)且可以用 JavaScript 操作。始终提供回退值:var(--primary, #007bff)。这是管理设计令牌的现代方式。
: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 或媒体查询即可实现动态效果。
/* 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。
/* 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')。
.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+ 层),因为它增加了优先级并降低了可维护性。
/* 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;
}
}CSS 自定义属性(变量)深入解析
定义与使用变量
CSS 自定义属性(变量)使用 --name 定义,使用 var() 使用。在 :root 中定义全局变量用于主题值。与 Sass 变量不同,CSS 变量是实时的——更改它们会立即更新所有使用处。它们作用于定义它们的元素并被后代继承。var() 接受回退值作为第二个参数,且回退可以链式调用。这使它们在动态主题化方面远比预处理器变量强大。
: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)变量,实现动态颜色选择器、用户偏好和实时预览。这是深色模式、品牌定制和用户可选主题的标准方法。变量层叠和继承,因此在子元素中覆盖仅影响该子树。
/* 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 条件中使用,但可以在媒体查询块内更改其值。此模式对于无需重复属性声明的响应式设计非常强大。
: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) 提供默认值)。此方法是现代设计系统的基础——更改一个变量,整个比例按比例调整。
: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 动画能力的重大进步。
/* 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
);
}3D 变换
3D 变换函数
3D 变换为元素添加深度。perspective() 作为变换函数应用于单个元素;父元素上的 perspective 属性统一应用于所有子元素。rotateX/rotateY/rotateZ 绕轴旋转;translateZ 沿 Z 轴移动(朝向/远离观察者)。较低的 perspective 值创建更戏剧性的 3D 效果(更近的视点)。始终在父容器上设置 perspective,以在多个变换子元素之间获得一致的 3D 空间。组合多个变换以实现复杂的 3D 定位。
.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 模式之一。
.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 以匹配立方体尺寸的一半,获得正确的几何形状。
.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 渲染。
.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 视差。结合滚动驱动动画,可创建沉浸式滚动体验。
.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); }CSS 滤镜与背景滤镜
滤镜函数
CSS 滤镜为元素应用视觉效果。grayscale、sepia 和 invert 改变颜色;blur 柔化;brightness/contrast/saturate 调整强度;hue-rotate 偏移颜色。多个滤镜从左到右链式应用。drop-shadow 对于 PNG/SVG 图像优于 box-shadow,因为它遵循 alpha 形状(透明区域不会有阴影)。滤镜是 GPU 加速的,性能良好。常见用途:悬停时灰度化图像画廊、复古照片效果和可访问性(高对比度模式)。
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)。
.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 单独无法实现的效果:液态变形、位移、光照和自定义合成。
<!-- 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 提示浏览器进行优化。
@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 创建新的混合上下文以包含混合效果。
/* 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;
}容器查询
容器查询基础
容器查询允许组件响应其容器的尺寸而非视口。container-type: inline-size 使元素基于其内联(宽度)维度成为查询容器。@container 规则在容器匹配条件时应用样式。这对基于组件的设计是革命性的——卡片组件无论在侧边栏还是全宽主区域都能适应,与屏幕尺寸无关。这解决了媒体查询的基本限制,后者仅响应视口尺寸。
/* 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 查询最近的祖先容器。
/* 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(两个维度)。
.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 检查。
/* 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 的条件逻辑。这是容器查询的杀手级用例——真正上下文独立的组件。结合容器查询单位用于排版,可获得完全自适应的组件。
/* 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;
}
}滚动捕捉与滚动驱动动画
滚动捕捉基础
滚动捕捉创建将元素对齐到捕捉点的磁性滚动。scroll-snap-type: x/y 设置轴;mandatory 强制捕捉(总是落在点上);proximity 仅在接近时捕捉。scroll-snap-align: start/center/end 定义子元素在容器内捕捉的位置。全页滚动部分(如演示幻灯片)使用 y mandatory 配合 100vh 部分。水平轮播使用 x mandatory。始终在触摸设备上测试——如果内容高于视口,mandatory 捕捉可能感觉受限。使用 proximity 获得更宽容的行为。
/* 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 实现捕捉之间的动画过渡。
.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+ 支持,其他浏览器建议渐进增强。
/* 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 滚动处理程序。
/* 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' 控制目标的垂直对齐。
/* 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; }
}CSS 计数器
基础计数器
CSS 计数器无需 JavaScript 自动为元素编号。counter-reset 初始化计数器(在父元素或任何祖先上)。counter-increment 递增它(通常在被编号的元素上)。counter(name) 在 content 中显示当前值。计数器自动处理整个文档中的编号。这非常适合为标题、列表项、图形或任何顺序内容编号。计数器作用于重置它们的元素及其后代。
/* 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 结构和重置点自然层叠。
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 在现代浏览器中支持良好。
/* 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() 实现嵌套列表的大纲式编号、目录或分层菜单。分隔符字符串可以是任何字符(. , - > 等)。
/* 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 锚点。但对于显示编号,这是一个干净、免维护的解决方案。
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;
}打印样式
@media print 基础
@media print 仅在打印时应用样式。隐藏导航、广告、侧边栏和在纸上无意义的交互元素。使用 !important 覆盖内联样式。print-color-adjust: exact 强制浏览器打印背景颜色和图像(否则会被剥离以节省墨水)。使用 pt(磅)作为打印字体大小,而非 px 或 rem。设置 width 为 100% 并移除外边距/内边距以获得最大可打印区域。始终使用打印预览(Ctrl+P)测试。
@media print {
/* Hide non-essential elements */
nav, footer, .sidebar, .ads, .no-print {
display: none !important;
}
/* Ensure colors print */
* {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
/* Set base font for print */
body {
font-size: 12pt;
color: #000;
background: #fff;
}
/* Expand content to full width */
.content {
width: 100%;
margin: 0;
padding: 0;
}
}分页符
分页符属性控制内容在页面之间分割的位置。break-before: page 在元素之前强制新页(用于章节)。break-inside: avoid 防止表格、图形或代码块跨页分割。break-after: avoid-page 使标题与后续内容保持在一起。orphans 和 widows 控制页面边界的最小行数(orphans = 底部,widows = 顶部)。break-* 属性是现代标准;page-break-* 是传统别名。并非所有浏览器都同等支持所有属性——彻底测试。
@media print {
/* Force page break before */
h1, h2 {
page-break-before: always;
break-before: page; /* modern syntax */
}
/* Avoid breaking inside */
table, figure, pre, blockquote {
page-break-inside: avoid;
break-inside: avoid;
}
/* Keep with next (heading stays with content) */
h2, h3, h4 {
page-break-after: avoid;
break-after: avoid-page;
}
/* Avoid orphan/widow lines */
p {
orphans: 3; /* min lines at bottom of page */
widows: 3; /* min lines at top of page */
}
}@page 规则
@page 配置打印页面本身:size(A4、letter、landscape 或自定义尺寸)和 margins。:first、:left、:right 伪类为特定页面设置样式——对于具有不同装订边距的书籍打印至关重要。命名页面(@page cover)让不同部分有不同的页面设置;通过元素上的 page 属性分配。页面边距创建可打印区域。注意:@page 支持因浏览器而异——Chrome 对 size 和 margins 支持良好;Firefox 支持有限。对于专业打印,考虑使用 Prince XML 等专用工具。
/* Set page size and margins */
@page {
size: A4; /* or: letter, landscape, 8.5in 11in */
margin: 2cm;
}
/* First page different */
@page :first {
margin-top: 5cm; /* extra space for letterhead */
}
/* Left and right pages (for binding) */
@page :left { margin-left: 3cm; margin-right: 1.5cm; }
@page :right { margin-left: 1.5cm; margin-right: 3cm; }
/* Named pages for different sections */
@page cover {
margin: 0;
}
.cover-page {
page: cover;
}打印友好链接
在纸上,没有 URL 的链接无用。content 中的 attr(href) 函数在每个链接文本后显示 URL。排除内部锚点链接(#)和 javascript: 链接。类似地,abbr[title]::after 显示缩写的完整展开。这确保打印文档保留超链接在屏幕上提供的信息。使用较小、柔和的字体显示 URL,以与正文区分。对于长 URL,考虑 word-break: break-all 以防止溢出。
@media print {
/* Show URL after links */
a[href]::after {
content: " (" attr(href) ")";
font-size: 0.9em;
color: #555;
}
/* Don't show URL for internal links */
a[href^="#"]::after,
a[href^="javascript:"]::after {
content: "";
}
/* Abbreviations: show full title */
abbr[title]::after {
content: " (" attr(title) ")";
}
}打印页眉与页脚
@page 边距框(@top-center、@bottom-center 等)在页面边距中放置内容——非常适合页码、页眉和页脚。counter(page) 是当前页码;counter(pages) 是总页数。然而,浏览器支持非常有限(主要是 Prince XML 和 WeasyPrint;Chrome/Firefox 不支持边距框)。回退使用 position: fixed 元素,在某些浏览器中在每个打印页面上重复。对于跨浏览器的可靠打印页眉/页脚,服务器端 PDF 生成(Puppeteer、wkhtmltopdf)通常比 CSS @page 更可靠。
@page {
margin: 2cm 3cm;
/* Page counter in footer */
@bottom-center {
content: "Page " counter(page) " of " counter(pages);
font-size: 10pt;
color: #666;
}
/* Document title in header */
@top-center {
content: "My Document Title";
font-size: 10pt;
color: #666;
}
}
/* Note: @page margin boxes have limited browser
support. Chrome doesn't support them.
Use fixed-position elements as fallback: */
@media print {
.print-footer {
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
font-size: 10pt;
}
}深色模式与配色方案
prefers-color-scheme
prefers-color-scheme: dark 检测用户的操作系统/浏览器深色模式偏好。在 :root 中定义浅色模式的主题变量,然后在深色媒体查询中覆盖它们。使用 CSS 变量意味着只需更改变量值——所有组件自动更新。这是深色模式的标准方法。媒体查询还支持 'light' 和 'no-preference'。通过切换操作系统深色模式或使用 Chrome DevTools 的 Rendering 选项卡(Emulate CSS prefers-color-scheme)测试。
/* 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)') 作为回退。
/* 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 变量主题化分开——它仅影响浏览器原生渲染。
: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 自动适应。对于背景图像,通过媒体查询提供深色模式替代。始终在两种模式下测试图像的可读性。
@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)。
/* 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; }
}CSS 函数深入解析
clamp()、min()、max()
clamp(min, preferred, max) 是流式排版和间距的圣杯——它随首选值缩放但永不超过 min/max 边界。min() 选择较小值(非常适合响应式 max-width)。max() 选择较大值(非常适合最小尺寸)。这些通过提供连续的流式缩放消除了许多媒体查询。clamp 中的首选值通常使用视口单位(vw、vh)或容器单位(cqw)。这是无断点响应式设计的现代方法。
/* 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() 实现动态、计算的设计系统。它对结合固定和流式尺寸的响应式布局至关重要。
/* 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)。
/* 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() 和其他函数。为可能未在所有上下文中定义的可选主题变量使用回退。
/* 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 的饼图和色轮。渐变与分辨率无关,性能优于图像文件。
/* 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);
}CSS 变量
定义与使用变量
CSS 自定义属性(变量)使用 --name 定义,使用 var() 使用。在 :root 上声明以全局访问。与 Sass 变量不同,它们是实时的——通过 JavaScript 更改变量会立即更新使用它的每个元素。
:root {
--primary: #3498db;
--spacing: 16px;
--radius: 8px;
}
.button {
background: var(--primary);
padding: var(--spacing);
border-radius: var(--radius);
}回退值
var() 接受第二个参数作为变量未定义时的回退。回退可以嵌套,允许链式默认值。对于不支持自定义属性的浏览器,先声明正常值,然后用 var() 覆盖。
.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() 设置变量。这使运行时主题化变得简单——翻转几个变量即可重新设置整个应用的样式。
// 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 上重新定义它仅覆盖该子树。这种作用域实现了组件级主题化,无需优先级之争。
: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 */响应式变量
在媒体查询内重新定义变量,使整个布局响应断点而无需重写规则。更改一个变量,使用它的每个元素都会适应——比单独覆盖每个属性干净得多。
: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); }动画与关键帧
@keyframes 与 animation 简写
@keyframes 定义动画的开始(from/0%)和结束(to/100%)状态。animation 简写结合 name、duration、timing-function、delay、iteration-count、direction、fill-mode 和 play-state。forwards 保持最终状态。
@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 方便但可能损害性能——优先列出特定属性。
.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() 创建离散效果。
/* 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 链式动画。
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 提示浏览器。
/* 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; }3D 变换
2D 变换
2D 变换移动、旋转、缩放和扭曲元素而不影响周围布局。变换在 GPU 上合成,使其在动画中性能良好。顺序很重要:先旋转再平移会沿旋转后的轴移动。
.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 中。
.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,因此在容器翻转时显示。
.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 空间中定位。动画化立方体变换使其旋转。
.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 加速,提高动画平滑度。避免过度使用图层。
/* 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); }CSS Grid 高级
Grid 模板区域
grid-template-areas 可视化命名网格单元格,使布局意图明显。每个引号行代表一个网格行;相同名称跨越单元格。空单元格使用点(.)。区域必须形成矩形——L 形无效。
.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 保留它们。
.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 是两者的简写。
.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 使项目跨越全宽。
.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 年起所有现代浏览器支持。
.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);
}CSS 函数
calc()
calc() 对混合单位(px、%、vw、em、rem)执行数学运算。始终在 + 和 - 周围加空格(calc(100%-20px) 失败;calc(100% - 20px) 有效)。乘法和除法需要一侧是无单位数字。
.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() 将值限制在最小值和最大值之间,中间有首选值。这是构建流式排版和间距的最干净方式——值会缩放但永不低于或高于边界。
/* 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() 限制值下限。
/* 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() 调用以链式回退。
.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 关键字)允许调整各个通道。
/* 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); }滚动驱动动画
animation-timeline 基础
animation-timeline: scroll(root) 将动画绑定到页面滚动位置——用户滚动时动画推进。无需 JavaScript。这比滚动事件监听器平滑得多。
@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 的滚动揭示效果。
@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% 使条从左侧增长。
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)。
.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% 仅在完全可见时跨越。
.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%;
}CSS 层
定义 @layer
@layer 将样式分组到命名的层叠层中。声明行中的顺序设置优先级:后面的层优先于前面的层,无论选择器优先级如何。这为大型样式表带来了可预测的排序。
@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。未分层的样式优先于所有分层的样式。
@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 层,你的自定义样式(在后面的层或未分层)将总是胜出。
@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。
@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 内,因此层成员资格适应条件。这使特定功能的样式保持在其层内组织,而非泄漏到未分层空间。
@layer base, components;
@media (max-width: 600px) {
@layer components {
.nav { flex-direction: column; }
}
}
@supports (display: grid) {
@layer components {
.layout { display: grid; }
}
}背景滤镜
backdrop-filter 基础
backdrop-filter 对元素后面的内容应用滤镜,创建磨砂玻璃效果。始终包含 -webkit- 前缀以支持 Safari。结合半透明背景使模糊可见。
.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。每个都应用于背景。搭配着色背景引导氛围。
.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 反转。注意文本可读性。
.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——可能导致严重卡顿。
/* 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 滤镜增强透过玻璃看到的颜色。
.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);
}相关 CSS 代码片段
Copy-paste ready code for common tasks.
这篇内容对您有帮助吗?