跳到主要内容

CSS 属性

CSS 属性控制 HTML 元素的各种外观和行为。本章详细介绍常用属性及其用法。

文本属性

字体 font-family

/* 单个字体 */
body {
font-family: 'Microsoft YaHei';
}

/* 字体列表(依次查找) */
body {
font-family: 'Helvetica Neue', Arial, sans-serif;
}

/* 常用字体栈 */
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-family: Georgia, 'Times New Roman', serif;
font-family: 'SF Mono', Consolas, 'Courier New', monospace;

字体大小 font-size

/* 固定值 */
font-size: 16px;
font-size: 1.2em;
font-size: 1rem;

/* 关键词 */
font-size: small;
font-size: medium;
font-size: large;

/* 百分比(相对于父元素) */
font-size: 120%;

/* 视口单位 */
font-size: 2vw;

字体粗细 font-weight

font-weight: normal;    /* 400 */
font-weight: bold; /* 700 */
font-weight: lighter; /* 相对于父元素 */
font-weight: bolder; /* 相对于父元素 */

font-weight: 100; /* 最细 */
font-weight: 300; /* 细 */
font-weight: 400; /* 正常 */
font-weight: 500; /* 中等 */
font-weight: 600; /* 半粗 */
font-weight: 700; /* 粗 */
font-weight: 900; /* 最粗 */

字体样式 font-style

font-style: normal;   /* 正常 */
font-style: italic; /* 斜体 */
font-style: oblique; /* 倾斜文字 */

行高 line-height

/* 推荐值:1.4 - 1.8 */
line-height: 1.6;
line-height: 24px;
line-height: 150%;
line-height: 1.5em;

效果预览: 不同 line-height 值的对比效果:

  • line-height: 1.2 - 紧凑行高
  • line-height: 1.8 - 舒适行高

文本颜色 color

/* 颜色名称 */
color: red;
color: blue;

/* 十六进制 */
color: #ff0000;
color: #f00; /* 简写 */

/* RGB */
color: rgb(255, 0, 0);
color: rgb(100%, 0%, 0%);

/* RGBA(带透明度) */
color: rgba(255, 0, 0, 0.5);

/* HSL */
color: hsl(0, 100%, 50%);

文本对齐 text-align

text-align: left;    /* 左对齐(默认) */
text-align: right; /* 右对齐 */
text-align: center; /* 居中 */
text-align: justify; /* 两端对齐 */

效果预览: text-align 的三种对齐方式效果:

  • left - 文字靠左对齐
  • center - 文字居中
  • right - 文字靠右对齐

文本装饰 text-decoration

text-decoration: none;                /* 无装饰 */
text-decoration: underline; /* 下划线 */
text-decoration: overline; /* 上划线 */
text-decoration: line-through; /* 删除线 */
text-decoration: underline wavy red; /* 波浪红色下划线 */

其他文本属性

/* 文本缩进 */
text-indent: 2em;

/* 字母间距 */
letter-spacing: 2px;

/* 单词间距 */
word-spacing: 5px;

/* 文本转换 */
text-transform: uppercase; /* 全大写 */
text-transform: lowercase; /* 全小写 */
text-transform: capitalize; /* 首字母大写 */

/* 空白处理 */
white-space: nowrap; /* 不换行 */
white-space: pre; /* 保留空白 */
white-space: pre-wrap; /* 保留空白并换行 */

背景属性

背景颜色 background-color

background-color: #3498db;
background-color: rgba(52, 152, 219, 0.5);
background-color: transparent; /* 透明 */

背景图片 background-image

background-image: url('bg.jpg');
background-image: linear-gradient(to bottom, #fff, #ccc);
background-image: radial-gradient(circle, #fff, #ccc);

/* 多重背景 */
background-image: url('logo.png'), url('pattern.png');

背景重复 background-repeat

background-repeat: repeat;      /* 默认:水平和垂直重复 */
background-repeat: no-repeat; /* 不重复 */
background-repeat: repeat-x; /* 只水平重复 */
background-repeat: repeat-y; /* 只垂直重复 */
background-repeat: space; /* 平铺并留白 */
background-repeat: round; /* 平铺并缩放 */

背景位置 background-position

/* 关键词 */
background-position: top;
background-position: bottom;
background-position: left;
background-position: right;
background-position: center;

/* 具体值 */
background-position: 20px 30px;
background-position: 50% 50%;
background-position: right top;

背景尺寸 background-size

background-size: auto auto;     /* 保持原始尺寸 */
background-size: cover; /* 覆盖整个容器(可能裁剪) */
background-size: contain; /* 完整显示(可能留白) */
background-size: 100% 100%; /* 拉伸填充 */
background-size: 200px 100px; /* 指定尺寸 */

背景固定 background-attachment

background-attachment: scroll; /* 随页面滚动 */
background-attachment: fixed; /* 固定不滚动 */
background-attachment: local; /* 随元素内容滚动 */

background 简写

background: #f5f5f5 url('bg.jpg') no-repeat center top / cover;

边框属性

边框宽度 border-width

border-width: 1px;
border-width: thin medium thick; /* 上 右 下 左 */
border-width: 10px 20px; /* 上下 左右 */

边框样式 border-style

border-style: none;    /* 无边框 */
border-style: hidden; /* 隐藏(表格边框重叠时) */
border-style: dotted; /* 点线 */
border-style: dashed; /* 虚线 */
border-style: solid; /* 实线 */
border-style: double; /* 双线 */
border-style: groove; /* 3D凹槽 */
border-style: ridge; /* 3D凸脊 */
border-style: inset; /* 3D凹入 */
border-style: outset; /* 3D凸出 */

效果预览: 不同 border-style 的效果:

  • dotted - 点线边框
  • dashed - 虚线边框
  • solid - 实线边框
  • double - 双线边框

边框颜色 border-color

border-color: #3498db;
border-color: red blue green yellow; /* 上 右 下 左 */

边框简写 border

border: 1px solid #333;           /* 完整简写 */
border-top: 2px dashed red; /* 只设置上边框 */
border-bottom: 1px solid #ccc; /* 只设置下边框 */

圆角 border-radius

border-radius: 5px;                      /* 所有角 */
border-radius: 50%; /* 圆形 */
border-radius: 10px 20px; /* 左上右下 右上左下 */
border-radius: 5px 10px 15px 20px; /* 左上 右上 右下 左下 */
border-radius: 50% / 10px; /* 椭圆 */

效果预览: 不同 border-radius 值的圆角效果:

  • border-radius: 5px - 小圆角
  • border-radius: 50% - 圆形
  • border-radius: 10px 20px - 椭圆角

盒模型属性

外边距 margin

margin: 10px;                      /* 所有边 */
margin: 10px 20px; /* 上下 左右 */
margin: 5px 10px 15px 20px; /* 上 右 下 左 */

margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;

/* 居中 */
margin: 0 auto;
margin-left: auto;
margin-right: auto;

内边距 padding

padding: 10px;                      /* 所有边 */
padding: 10px 20px; /* 上下 左右 */
padding: 5px 10px 15px 20px; /* 上 右 下 左 */

padding-top: 10px;
padding-right: 20px;
padding-bottom: 10px;
padding-left: 20px;

宽高 width / height

width: 200px;
width: 50%;
width: auto;

height: 100px;
height: auto;
height: 100vh;

尺寸限制

min-width: 300px;
max-width: 1200px;

min-height: 200px;
max-height: 500px;

盒子尺寸计算 box-sizing

/* 默认:content-box,内容盒模型 */
box-sizing: content-box;
元素的 width = 内容宽度

/* 推荐:border-box,边框盒模型 */
box-sizing: border-box;
元素的 width = 内容 + padding + border

显示属性 display

display: block;       /* 块级元素 */
display: inline; /* 行内元素 */
display: inline-block; /* 行内块元素 */
display: flex; /* flex 容器 */
display: grid; /* grid 容器 */
display: none; /* 不显示 */
display: contents; /* 移除容器自身 */

display: block

div, p, h1, ul, article {
display: block;
}

块级元素特点:

  • 独占一行
  • 可以设置宽高
  • 可以设置 margin 和 padding

display: inline

span, a, strong, em {
display: inline;
}

行内元素特点:

  • 不独占一行
  • 不能设置宽高(由内容决定)
  • 水平方向 margin 和 padding 有效,垂直方向无效

display: inline-block

button, input, select {
display: inline-block;
}

行内块元素特点:

  • 不独占一行
  • 可以设置宽高
  • margin 和 padding 四方向都有效

溢出属性 overflow

overflow: visible;  /* 默认:溢出可见 */
overflow: hidden; /* 溢出隐藏 */
overflow: scroll; /* 始终显示滚动条 */
overflow: auto; /* 需要时显示滚动条 */

/* 分方向设置 */
overflow-x: auto;
overflow-y: hidden;

效果预览: 不同 overflow 值的处理方式:

  • overflow: visible - 溢出内容可见(默认)
  • overflow: hidden - 溢出内容被隐藏
  • overflow: auto - 需要时显示滚动条

定位属性

position

position: static;     /* 默认:静态定位 */
position: relative; /* 相对定位(相对于自身) */
position: absolute; /* 绝对定位(相对于最近定位祖先) */
position: fixed; /* 固定定位(相对于视口) */
position: sticky; /* 粘性定位 */

定位偏移

/* 配合 position 使用 */
top: 10px;
bottom: 20px;
left: 30px;
right: 40px;

/* 百分比 */
top: 50%;
left: 50%;

/* 负值 */
top: -10px;

z-index 层级

z-index: auto;   /* 默认:与父元素同层 */
z-index: 1; /* 正整数:数值越大越在上层 */
z-index: -1; /* 负数:在普通内容下方 */

浮动属性 float

float: none;    /* 默认:不浮动 */
float: left; /* 左浮动 */
float: right; /* 右浮动 */

清除浮动:

.clearfix::after {
content: "";
display: block;
clear: both;
}

透明度 opacity

opacity: 1;      /* 完全不透明 */
opacity: 0.5; /* 半透明 */
opacity: 0; /* 完全透明 */

/* 与 rgba 的区别 */
/* opacity 影响整个元素(包括子元素) */
/* rgba 只影响背景颜色 */

鼠标样式 cursor

cursor: default;      /* 默认箭头 */
cursor: pointer; /* 手型 */
cursor: text; /* 文本选择 */
cursor: move; /* 移动 */
cursor: not-allowed; /* 禁止 */
cursor: wait; /* 等待/加载 */
cursor: help; /* 帮助 */
cursor: crosshair; /* 十字 */

阴影属性

盒子阴影 box-shadow

/* 基础用法 */
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);

/* 参数:水平偏移 垂直偏移 模糊距离 颜色 */
box-shadow: h-shadow v-shadow blur spread color inset;

/* 多重阴影 */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1),
0 4px 8px rgba(0, 0, 0, 0.1);

/* 内阴影 */
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);

/* 常用效果 */
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12); /* 卡片 */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 浮动元素 */
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15); /* 弹窗 */

效果预览: 不同 box-shadow 效果:

  • 卡片阴影 - 轻柔的投影效果
  • 弹窗阴影 - 更明显的深度效果
  • 内阴影 - 边框内部的阴影效果

文字阴影 text-shadow

/* 参数:水平偏移 垂直偏移 模糊距离 颜色 */
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);

/* 多重阴影 */
text-shadow: 1px 1px 0 white,
2px 2px 0 rgba(0, 0, 0, 0.1);

/* 发光效果 */
text-shadow: 0 0 10px #3498db,
0 0 20px #3498db,
0 0 30px #3498db;

效果预览: 带有 text-shadow 的文字效果,阴影参数为 2px 2px 4px rgba(0,0,0,0.3)

变形属性 transform

transform 属性允许对元素进行旋转、缩放、倾斜或移动等变换操作。它修改元素的坐标空间,而不影响正常的文档流。

变换的核心概念

变换不影响文档流: 变换只影响元素的视觉呈现,元素在文档流中的位置和尺寸保持不变。这意味着变换后的元素不会影响其他元素的布局。

变换顺序很重要: 多个变换函数从左到右依次应用,视觉上相当于从右到左执行。顺序不同,结果也不同:

/* 先旋转再平移 */
.box1 {
transform: rotate(45deg) translateX(100px);
/* 元素沿原始 X 轴平移后旋转 */
}

/* 先平移再旋转 */
.box2 {
transform: translateX(100px) rotate(45deg);
/* 元素旋转后沿新 X 轴平移,效果完全不同 */
}

变换创建层叠上下文: 如果 transform 值不是 none,会创建新的层叠上下文,元素会成为 position: fixed 子元素的包含块。

平移函数

平移函数用于移动元素的位置:

/* translate() - 2D 平移 */
.box {
transform: translate(100px, 50px); /* 水平100px,垂直50px */
transform: translate(100px); /* 水平100px,垂直为0 */
transform: translate(50%); /* 水平移动自身宽度的50% */
}

/* translateX() / translateY() - 单方向平移 */
.box {
transform: translateX(100px); /* 向右移动 */
transform: translateY(-30px); /* 向上移动 */
}

/* 居中定位技巧 */
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

/* translateZ() - 3D 沿 Z 轴移动 */
.box {
transform: perspective(500px) translateZ(100px);
/* 向观察者方向移动,产生放大效果 */
}

/* translate3d() - 完整 3D 平移 */
.box {
transform: translate3d(100px, 50px, 20px);
}

旋转函数

旋转函数用于围绕某个轴旋转元素:

/* rotate() - 2D 旋转 */
.box {
transform: rotate(45deg); /* 顺时针旋转45度 */
transform: rotate(-45deg); /* 逆时针旋转45度 */
transform: rotate(0.5turn); /* 旋转半圈(180度) */
transform: rotate(1turn); /* 旋转一整圈(360度) */
}

/* rotateX() - 绕 X 轴旋转(类似翻书效果) */
.box {
transform: perspective(500px) rotateX(45deg);
/* 元素顶部向后翻转 */
}

/* rotateY() - 绕 Y 轴旋转(类似开门效果) */
.box {
transform: perspective(500px) rotateY(45deg);
/* 元素右侧向后翻转 */
}

/* rotateZ() - 绕 Z 轴旋转(等同于 rotate) */
.box {
transform: rotateZ(45deg);
}

/* rotate3d() - 绕任意轴旋转 */
.box {
/* rotate3d(x, y, z, angle) */
/* x, y, z 定义旋转轴的方向向量 */
transform: rotate3d(1, 1, 0, 45deg); /* 绕对角线轴旋转 */
}

缩放函数

缩放函数用于改变元素的尺寸:

/* scale() - 2D 缩放 */
.box {
transform: scale(1.5); /* 整体放大1.5倍 */
transform: scale(0.5); /* 整体缩小一半 */
transform: scale(2, 0.5); /* 水平2倍,垂直一半 */
}

/* scaleX() / scaleY() - 单方向缩放 */
.box {
transform: scaleX(2); /* 宽度变为2倍 */
transform: scaleY(0.5); /* 高度变为一半 */
}

/* 负值缩放产生镜像翻转 */
.box {
transform: scaleX(-1); /* 水平镜像 */
transform: scale(-1, 1); /* 水平翻转 */
}

/* scaleZ() / scale3d() - 3D 缩放 */
.box {
transform: perspective(500px) scaleZ(2);
transform: scale3d(2, 1.5, 1);
}

倾斜函数

倾斜函数用于扭曲元素的形状:

/* skew() - 2D 倾斜 */
.box {
transform: skew(10deg); /* 沿 X 轴倾斜 */
transform: skew(10deg, 20deg); /* X 和 Y 轴同时倾斜 */
}

/* skewX() / skewY() - 单轴倾斜 */
.box {
transform: skewX(15deg); /* 水平边缘倾斜 */
transform: skewY(10deg); /* 垂直边缘倾斜 */
}

透视函数

透视函数为 3D 变换设置观察距离:

/* perspective() 函数 */
.box {
transform: perspective(500px) rotateY(45deg);
/* 数值越小,透视效果越强烈 */
}

/* 与 perspective 属性的区别 */
.container {
perspective: 500px; /* 为所有子元素设置统一透视 */
}
.child {
transform: rotateY(45deg); /* 使用父元素的透视 */
}

/* perspective() 函数仅对当前元素生效 */
.single-element {
transform: perspective(500px) rotateY(45deg);
}

变换原点 transform-origin

transform-origin 决定变换围绕哪个点进行:

/* 默认值:元素中心 */
.box {
transform-origin: center center; /* 默认 */
transform-origin: 50% 50%; /* 同上 */
}

/* 使用关键词 */
.box {
transform-origin: top left;
transform-origin: bottom right;
transform-origin: center top;
}

/* 使用具体值 */
.box {
transform-origin: 0 0; /* 左上角 */
transform-origin: 100% 100%; /* 右下角 */
transform-origin: 50px 100px; /* 具体像素位置 */
}

/* 3D 变换原点 */
.box {
transform-origin: center center 100px;
}

实用示例

悬停效果:

.card {
transition: transform 0.3s ease;
}

.card:hover {
transform: translateY(-10px) scale(1.02);
/* 上移并轻微放大 */
}

按钮点击效果:

.button {
transition: transform 0.1s;
}

.button:active {
transform: scale(0.95); /* 点击时缩小 */
}

3D 翻转卡片:

.flip-card {
perspective: 1000px;
}

.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
transition: transform 0.6s;
transform-style: preserve-3d;
}

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

.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}

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

性能最佳实践

/* 推荐:只动画 transform 和 opacity */
.good {
transition: transform 0.3s, opacity 0.3s;
}
.good:hover {
transform: translateY(-10px);
opacity: 0.8;
}

/* 避免:动画触发布局的属性 */
.avoid {
transition: top 0.3s, width 0.3s, margin 0.3s;
/* 这些属性会触发布局重排,性能较差 */
}

/* 使用 will-change 提示浏览器 */
.animated {
will-change: transform;
transition: transform 0.3s;
}

过渡属性 transition

/* 完整写法 */
transition: property duration timing-function delay;

/* 常用简写 */
transition: all 0.3s ease;
transition: background-color 0.3s, transform 0.5s ease-in-out;
transition: opacity 0.3s linear 0.1s;

/* 单独设置 */
transition-property: all;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;

/* 常用 timing-function */
transition-timing-function: ease; /* 慢-快-慢 */
transition-timing-function: linear; /* 匀速 */
transition-timing-function: ease-in; /* 慢开始 */
transition-timing-function: ease-out; /* 慢结束 */
transition-timing-function: ease-in-out; /* 慢开始和结束 */

现代 CSS 属性

CSS 在不断发展,新增了许多强大的属性和函数,让布局和样式更加简洁高效。

aspect-ratio 宽高比

aspect-ratio 属性可以轻松维持元素的宽高比,无需使用 padding 技巧。

/* 固定宽高比 */
.video-container {
width: 100%;
aspect-ratio: 16 / 9;
}

/* 正方形 */
.square {
width: 200px;
aspect-ratio: 1;
}

/* 自定义比例 */
.photo {
aspect-ratio: 4 / 3;
}

/* 响应式卡片 */
.card-image {
width: 100%;
aspect-ratio: 3 / 2;
object-fit: cover;
}

传统方法对比:

/* 旧方法:使用 padding 技巧 */
.old-aspect-ratio {
position: relative;
padding-bottom: 56.25%; /* 16:9 = 9/16 = 0.5625 */
}

.old-aspect-ratio > * {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

/* 新方法:简洁直接 */
.new-aspect-ratio {
aspect-ratio: 16 / 9;
}

calc() 计算函数

calc() 是 CSS 中最常用的数学函数,允许在 CSS 属性值中进行数学计算。它可以在需要 <length><frequency><angle><time><percentage><number><integer> 值的地方使用。

基本语法

/* 语法:calc(表达式) */
property: calc(表达式);

支持的运算符:

运算符说明示例
+加法calc(100px + 20px)
-减法calc(100% - 30px)
*乘法calc(50px * 2)
/除法calc(100px / 2)

使用注意事项

  1. 运算符两侧必须有空格*/ 可选,但建议统一添加)
  2. 可以混合使用不同单位
  3. 可以嵌套使用
  4. 可以与 CSS 变量结合使用
/* 正确:运算符两侧有空格 */
width: calc(100% - 20px);
width: calc(50px + 20px);

/* 错误:运算符两侧没有空格 */
/* width: calc(100%-20px); */

/* 混合单位 */
width: calc(100vw - 2rem);
font-size: calc(1em + 2px);

/* 嵌套使用 */
width: calc(calc(100% / 2) - 10px);
/* 等价于 */
width: calc((100% / 2) - 10px);

/* 与变量结合 */
:root {
--spacing: 20px;
}
.element {
width: calc(100% - var(--spacing));
}

常见使用场景

1. 固定宽度侧边栏 + 自适应内容区

.sidebar {
width: 250px;
float: left;
}

.main-content {
/* 内容区宽度 = 总宽度 - 侧边栏宽度 - 间距 */
width: calc(100% - 250px - 20px);
margin-left: 270px;
}

2. 全屏高度减去固定头部

.content {
/* 内容高度 = 视口高度 - 头部高度 */
height: calc(100vh - 60px);
overflow-y: auto;
}

3. 响应式字体大小

/* 基础大小 + 视口相对增量 */
.title {
font-size: calc(16px + 1vw);
/* 最小 16px,随视口增大而增大 */
}

4. 精确控制网格间距

.grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
}

.grid-item {
/* 每行 3 个,减去间距 */
width: calc((100% - 40px) / 3);
}

5. 居中定位

/* 传统居中方法 */
.centered {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}

/* 使用 calc 居中(适用于已知尺寸元素) */
.centered-known-size {
position: absolute;
width: 300px;
height: 200px;
left: calc(50% - 150px); /* 50% - 宽度/2 */
top: calc(50% - 100px); /* 50% - 高度/2 */
}

6. 表单输入框自适应

.input-group {
display: flex;
}

.input-group input {
/* 输入框宽度 = 容器宽度 - 按钮宽度 */
width: calc(100% - 100px);
}

.input-group button {
width: 100px;
}

calc() 的限制

/* 不能计算 auto、fit-content 等固有尺寸值 */
/* 以下写法无效 */
/* width: calc(auto + 20px); */

/* 乘法时,只有一个值可以带单位 */
/* width: calc(20px * 30px); */ /* 无效:结果是 600px² 无意义 */
width: calc(20px * 30); /* 有效:结果是 600px */

/* 除法时,右边的值不能带单位(除非你想得到无单位数值) */
width: calc(100px / 2); /* 有效:结果是 50px */
width: calc(100px / 2px); /* 有效:结果是 50(无单位数字) */

interpolate-size 和 calc-size() 动画到 auto

CSS 长期以来无法将元素的高度从固定值动画到 auto(或 min-contentmax-content 等关键字)。CSS 2024 新增的 interpolate-size 属性和 calc-size() 函数解决了这个问题。

interpolate-size 属性

interpolate-size 允许在全局启用对尺寸关键字的动画支持:

/* 全局启用尺寸关键字动画 */
html {
interpolate-size: allow-keywords;
}

/* 现在可以动画到 auto */
.expandable {
height: 0;
overflow: hidden;
transition: height 0.3s ease;
}

.expandable.open {
height: auto; /* 可以从 0 平滑过渡到 auto */
}

属性值:

说明
allow-keywords允许动画到尺寸关键字(如 auto、min-content)
numeric-only默认值,只允许数值之间的动画

calc-size() 函数

calc-size() 函数提供了一种更精细的方式来处理尺寸计算和动画:

/* 语法 */
calc-size(<basis>, <calculation>)

/* <basis>: auto、min-content、max-content、fit-content 或具体值 */
/* <calculation>: 基于 size 关键字的计算表达式 */

基本示例:

/* 折叠面板动画 */
.accordion-content {
height: 0;
overflow: hidden;
transition: height 0.3s ease;
}

.accordion-content.expanded {
height: calc-size(auto, size); /* 动画到内容高度 */
}

/* 带额外间距 */
.accordion-content.expanded {
height: calc-size(auto, size + 20px);
}

实际应用示例:

/* 可展开卡片 */
.card-content {
height: 0;
overflow: hidden;
transition: height 0.4s ease;
}

.card.expanded .card-content {
height: calc-size(auto, size);
}

/* 下拉菜单 */
.dropdown-menu {
height: 0;
overflow: hidden;
transition: height 0.3s ease;
}

.dropdown.open .dropdown-menu {
height: calc-size(fit-content, size);
}

/* 响应式间距 */
.section {
padding-block: calc-size(min-content, size + 2rem);
}

完整示例:可折叠面板

<details class="accordion">
<summary>点击展开</summary>
<div class="accordion-content">
<p>这是折叠面板的内容。可以使用 calc-size() 实现平滑的高度动画。</p>
<p>内容可以是任意高度,动画会自动适应。</p>
</div>
</details>

<style>
/* 全局启用 */
html {
interpolate-size: allow-keywords;
}

.accordion-content {
height: 0;
overflow: hidden;
transition: height 0.3s ease;
}

.accordion[open] .accordion-content {
height: auto;
}

/* 或使用 calc-size() 方式(无需 interpolate-size) */
.accordion-content-alt {
height: 0;
overflow: hidden;
transition: height 0.3s ease;
}

.accordion[open] .accordion-content-alt {
height: calc-size(auto, size);
}
</style>

浏览器支持

interpolate-sizecalc-size() 是较新的 CSS 特性:

/* 渐进增强 */
.accordion-content {
height: 0;
overflow: hidden;
transition: height 0.3s ease;
}

/* 传统回退:使用 max-height */
.accordion-content.fallback {
max-height: 0;
transition: max-height 0.3s ease;
}

.accordion[open] .accordion-content.fallback {
max-height: 500px; /* 需要预估最大高度 */
}

/* 现代浏览器:使用 calc-size */
@supports (height: calc-size(auto, size)) {
.accordion[open] .accordion-content {
height: calc-size(auto, size);
}
}

clamp() 函数

clamp() 函数可以在最小值和最大值之间选择一个中间值,非常适合响应式设计。

语法

/* 语法:clamp(最小值, 首选值, 最大值) */
font-size: clamp(最小值, 首选值, 最大值);

参数说明:

参数说明
最小值允许的最小值,当首选值小于此值时使用
首选值优先使用的值,只要结果在最小值和最大值之间就使用此值
最大值允许的最大值,当首选值大于此值时使用

clamp(min, val, max) 等价于 max(min, min(val, max))

响应式字体大小

/* 字号最小 1rem,最大 2rem,优先使用 2.5vw */
font-size: clamp(1rem, 2.5vw, 2rem);

/* 响应式标题 */
h1 {
font-size: clamp(1.5rem, 5vw, 3rem);
}

h2 {
font-size: clamp(1.2rem, 3vw, 2rem);
}

工作原理: 假设视口宽度为 1440px,则 2.5vw = 36px = 2.25rem。由于 2.25rem 在 1rem 和 2rem 之间,所以使用 2.25rem。当视口变窄到 640px 时,2.5vw = 16px = 1rem,达到最小值。当视口变宽到 1280px 时,2.5vw = 32px = 2rem,达到最大值。

响应式容器宽度

.container {
/* 宽度在 300px 到 1200px 之间,优先使用 80% */
width: clamp(300px, 80%, 1200px);
margin: 0 auto;
}

响应式间距

.section {
/* 间距在 1rem 到 3rem 之间,优先使用 5vw */
padding: clamp(1rem, 5vw, 3rem);
}

clamp() 的优势

相比媒体查询,clamp() 有以下优势:

  1. 代码更简洁:一个声明替代多个媒体查询
  2. 过渡更流畅:尺寸变化是连续的,而非离散的断点
  3. 更易维护:修改范围只需改一处
/* 使用媒体查询实现类似效果(冗长) */
.title {
font-size: 1.5rem;
}

@media (min-width: 768px) {
.title { font-size: 2rem; }
}

@media (min-width: 1024px) {
.title { font-size: 2.5rem; }
}

@media (min-width: 1440px) {
.title { font-size: 3rem; }
}

/* 使用 clamp() 实现(简洁) */
.title {
font-size: clamp(1.5rem, 2.5vw, 3rem);
}

min() 和 max() 函数

min()max() 函数分别从一组值中选择最小值或最大值,非常适合设置响应式的边界约束。

min() 函数

min() 函数返回参数列表中的最小值:

/* 语法:min(值1, 值2, ...) */
.element {
width: min(50%, 400px);
/* 宽度取 50% 和 400px 中较小的那个 */
/* 当视口宽度小于 800px 时,50% < 400px,使用 50% */
/* 当视口宽度大于 800px 时,50% > 400px,使用 400px */
}

min() 的典型应用场景:

/* 1. 限制最大宽度 */
.sidebar {
width: min(300px, 25%);
/* 侧边栏宽度不超过 300px,在小屏幕上自适应 */
}

/* 2. 响应式字体大小(设置上限) */
.title {
font-size: min(5vw, 48px);
/* 字体随视口增大,但最大不超过 48px */
}

/* 3. 响应式间距 */
.section {
padding: min(10vw, 80px);
/* 间距随视口增大,但最大不超过 80px */
}

/* 4. 响应式容器 */
.container {
width: min(90%, 1200px);
margin: 0 auto;
/* 容器宽度最大 1200px,小屏幕上为 90% */
}

max() 函数

max() 函数返回参数列表中的最大值:

/* 语法:max(值1, 值2, ...) */
.element {
width: max(300px, 50%);
/* 宽度取 300px 和 50% 中较大的那个 */
/* 当视口宽度小于 600px 时,50% < 300px,使用 300px */
/* 当视口宽度大于 600px 时,50% > 300px,使用 50% */
}

max() 的典型应用场景:

/* 1. 设置最小值 */
.content {
padding: max(1rem, 5vw);
/* 间距至少 1rem,在大屏幕上为 5vw */
}

/* 2. 最小字体大小(无障碍考虑) */
.text {
font-size: max(16px, 1.2vw);
/* 字体最小 16px,保证可读性 */
}

/* 3. 最小高度 */
.hero {
min-height: max(400px, 50vh);
/* 最小高度至少 400px */
}

min() 与 max() 组合使用

/* 同时设置最小和最大边界 */
.element {
width: max(300px, min(50%, 600px));
/* 等价于 clamp(300px, 50%, 600px) */
}

/* 或者分开写 */
.element {
min-width: 300px;
width: min(50%, 600px);
}

min()、max() 与 clamp() 对比

函数作用典型场景
min()选择最小值设置最大边界(不超过某值)
max()选择最大值设置最小边界(至少某值)
clamp()限制在范围内同时设置最小、首选、最大值
/* 三者等价关系 */
/* clamp(min, val, max) 等价于 max(min, min(val, max)) */

/* 使用 clamp(推荐,更直观) */
font-size: clamp(1rem, 2.5vw, 2rem);

/* 使用 min/max 组合 */
font-size: max(1rem, min(2.5vw, 2rem));

gap 属性

gap 属性统一了 Flexbox、Grid 和多列布局的间距设置。

/* Flexbox 中的 gap */
.flex-container {
display: flex;
gap: 20px; /* 行和列间距相同 */
gap: 20px 10px; /* 行间距 列间距 */
row-gap: 20px;
column-gap: 10px;
}

/* Grid 中的 gap */
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}

/* 多列布局中的 gap */
.multi-column {
column-count: 3;
column-gap: 30px;
}

gap 替代 margin 的优势:

/* 旧方法:使用 margin */
.old-grid {
display: flex;
flex-wrap: wrap;
margin: -10px; /* 负 margin 抵消 */
}
.old-grid > * {
margin: 10px;
}

/* 新方法:使用 gap */
.new-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
/* 无需负 margin,无需处理边缘 */
}

container queries 容器查询

容器查询允许元素根据其容器(而非视口)的大小来调整样式,这是响应式设计的一大进步。传统的媒体查询基于视口大小,而容器查询基于容器大小,使组件更加独立和可复用。

创建包含上下文

要使用容器查询,首先需要在容器元素上声明包含上下文:

/* 定义容器 */
.card-container {
container-type: inline-size; /* 基于内联尺寸(宽度)查询 */
}

/* 或使用简写语法 */
.card-container {
container: card / inline-size; /* 名称 / 类型 */
}

container-type 值:

说明
size基于容器的行内和块尺寸查询
inline-size基于容器的行内尺寸查询(最常用)
normal默认值,不作为尺寸查询容器

基本用法

/* 定义容器 */
.sidebar {
container-type: inline-size;
}

/* 根据容器宽度应用样式 */
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}

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

命名容器

当页面有多个容器时,可以为容器命名以便精确查询:

/* 定义命名容器 */
.sidebar {
container: sidebar / inline-size;
}

.main-content {
container: main / inline-size;
}

/* 查询特定容器 */
@container sidebar (min-width: 300px) {
.widget { /* 样式 */ }
}

@container main (min-width: 600px) {
.article { /* 样式 */ }
}

完整示例

<div class="sidebar">
<article class="card">
<img src="photo.jpg" alt="">
<div class="card-content">
<h3>标题</h3>
<p>内容描述...</p>
</div>
</article>
</div>

<style>
.sidebar {
container: card-wrapper / inline-size;
}

.card {
display: flex;
flex-direction: column;
padding: 1rem;
}

.card img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}

/* 容器宽度大于 400px 时切换为水平布局 */
@container card-wrapper (min-width: 400px) {
.card {
flex-direction: row;
gap: 1rem;
}

.card img {
width: 200px;
aspect-ratio: 1;
}
}
</style>

容器查询单位

容器查询提供了专门的长度单位,相对于容器尺寸计算:

单位说明
cqw容器宽度的 1%
cqh容器高度的 1%
cqi容器行内尺寸的 1%
cqb容器块尺寸的 1%
cqmincqicqb 中较小的值
cqmaxcqicqb 中较大的值
.card-title {
/* 字体大小根据容器宽度变化 */
font-size: clamp(1rem, 5cqi, 2rem);
}

容器查询 vs 媒体查询

/* 媒体查询:基于视口宽度 */
@media (min-width: 768px) {
.card { /* 侧边栏和主内容区的卡片同时变化 */ }
}

/* 容器查询:基于各自容器宽度 */
@container (min-width: 400px) {
.card { /* 每个容器内的卡片独立响应 */ }
}

优势: 容器查询让组件可以在不同上下文中自适应,而无需关心它被放在页面的哪个位置。

:where() 和 :is() 在属性中的应用

虽然这是选择器,但在样式重置和基础样式中非常有用:

/* 基础样式重置 - 优先级为 0 */
:where(h1, h2, h3, h4, h5, h6) {
margin: 0;
}

/* 容易被覆盖 */
h1 {
margin: 1rem 0; /* 生效,因为优先级更高 */
}

scroll-behavior 平滑滚动

/* 全局平滑滚动 */
html {
scroll-behavior: smooth;
}

/* 特定容器平滑滚动 */
.scroll-container {
scroll-behavior: smooth;
overflow-y: auto;
}

scroll-snap 滚动捕捉

滚动捕捉(Scroll Snap)让容器在滚动结束时自动停靠在指定的捕捉点上,常用于轮播图、全屏滚动等场景。

容器属性

scroll-snap-type 定义容器的捕捉类型:

.snap-container {
/* 语法:scroll-snap-type: [轴] [严格程度] */
scroll-snap-type: x mandatory; /* 水平滚动,强制捕捉 */
scroll-snap-type: y proximity; /* 垂直滚动,就近捕捉 */
scroll-snap-type: both mandatory; /* 两个方向都捕捉 */
}
轴值说明
x水平方向捕捉
y垂直方向捕捉
both两个方向都捕捉
block块轴方向捕捉
inline行内轴方向捕捉
严格程度说明
mandatory强制捕捉,滚动必须停在捕捉点
proximity就近捕捉,只有接近捕捉点时才停靠

scroll-padding 定义捕捉容器的内边距:

.snap-container {
scroll-padding: 20px; /* 四边 */
scroll-padding-top: 60px; /* 顶部(避开固定头部) */
scroll-padding-inline: 30px; /* 行内方向 */
}

子元素属性

scroll-snap-align 定义子元素的捕捉对齐方式:

.snap-item {
scroll-snap-align: start; /* 对齐到起始边缘 */
scroll-snap-align: center; /* 居中对齐 */
scroll-snap-align: end; /* 对齐到结束边缘 */
}

scroll-snap-stop 控制是否必须停靠:

.snap-item {
scroll-snap-stop: normal; /* 默认,可以跳过 */
scroll-snap-stop: always; /* 必须停靠,不能跳过 */
}

实际应用示例

图片轮播:

.gallery {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-padding: 20px;
gap: 10px;
}

.gallery img {
scroll-snap-align: center;
scroll-snap-stop: always; /* 每张图片都必须停靠 */
flex-shrink: 0;
width: 300px;
height: 200px;
object-fit: cover;
border-radius: 8px;
}

全屏滚动页面:

.fullscreen-sections {
height: 100vh;
overflow-y: auto;
scroll-snap-type: y mandatory;
}

.section {
height: 100vh;
scroll-snap-align: start;
scroll-snap-stop: always;
}

/* 避开固定头部 */
.section:first-child {
scroll-margin-top: 60px;
}

卡片滑动选择:

.card-slider {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-padding: 16px;
gap: 16px;
padding: 16px;
}

.card {
scroll-snap-align: start;
flex-shrink: 0;
width: 280px;
padding: 20px;
border-radius: 12px;
background: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

overscroll-behavior 过度滚动

控制滚动到边界时的行为:

/* 禁止过度滚动 */
.modal {
overscroll-behavior: contain;
}

/* 禁止弹性滚动 */
.no-bounce {
overscroll-behavior: none;
}

CSS 逻辑属性

CSS 逻辑属性是一组基于文本流方向而非物理方向的属性,使用抽象的 blockinline 概念来描述方向,使样式能够自动适应不同的书写模式。

为什么需要逻辑属性?

不同的语言有不同的书写方向:

书写模式示例语言特点
水平从左到右英语、中文新行在下方
水平从右到左阿拉伯语、希伯来语新行在下方
垂直从上到下繁体中文、日文新行在左侧

使用逻辑属性可以让同一套样式在不同书写模式下自动适配,无需为 RTL(从右到左)语言单独编写样式。

核心概念

  • Block(块方向):垂直于文本流动的方向。在水平书写模式中是垂直方向;在垂直书写模式中是水平方向。
  • Inline(行内方向):平行于文本流动的方向。在水平书写模式中是水平方向;在垂直书写模式中是垂直方向。
  • Start/End:起始和结束位置,根据文本方向自动调整。

物理属性与逻辑属性对照

尺寸属性:

物理属性逻辑属性说明
widthinline-size行内尺寸
heightblock-size块尺寸
min-widthmin-inline-size最小行内尺寸
min-heightmin-block-size最小块尺寸
max-widthmax-inline-size最大行内尺寸
max-heightmax-block-size最大块尺寸

外边距属性:

物理属性逻辑属性说明
margin-topmargin-block-start块起始边距
margin-bottommargin-block-end块结束边距
margin-leftmargin-inline-start行内起始边距
margin-rightmargin-inline-end行内结束边距
-margin-block块方向边距简写
-margin-inline行内方向边距简写

内边距属性:

物理属性逻辑属性说明
padding-toppadding-block-start块起始内边距
padding-bottompadding-block-end块结束内边距
padding-leftpadding-inline-start行内起始内边距
padding-rightpadding-inline-end行内结束内边距
-padding-block块方向内边距简写
-padding-inline行内方向内边距简写

定位属性:

物理属性逻辑属性说明
topinset-block-start块起始偏移
bottominset-block-end块结束偏移
leftinset-inline-start行内起始偏移
rightinset-inline-end行内结束偏移
-inset-block块方向偏移简写
-inset-inline行内方向偏移简写
-inset四方向偏移简写

使用示例

1. 水平居中(推荐方式):

/* 传统方式 */
.center-traditional {
margin-left: auto;
margin-right: auto;
/* 或 */
margin: 0 auto;
}

/* 逻辑属性方式(推荐) */
.center-logical {
margin-inline: auto;
}

2. RTL 友好的侧边栏:

/* 传统方式:需要为 RTL 单独处理 */
.sidebar {
float: left;
margin-right: 20px;
border-right: 1px solid #ddd;
}

/* RTL 模式需要覆盖 */
[dir="rtl"] .sidebar {
float: right;
margin-right: 0;
margin-left: 20px;
border-right: none;
border-left: 1px solid #ddd;
}

/* 逻辑属性方式:自动适配 RTL */
.sidebar-logical {
float: inline-start;
margin-inline-end: 20px;
border-inline-end: 1px solid #ddd;
}

3. 文字两侧图标:

/* 传统方式 */
.icon-text {
padding-left: 30px;
background: url(icon.svg) no-repeat left center;
}

/* RTL 需要单独处理 */
[dir="rtl"] .icon-text {
padding-left: 0;
padding-right: 30px;
background-position: right center;
}

/* 逻辑属性方式 */
.icon-text-logical {
padding-inline-start: 30px;
background: url(icon.svg) no-repeat inline-start center;
}

4. 完整布局示例:

/* 使用逻辑属性的响应式布局 */
.page {
padding-inline: 20px; /* 水平内边距 */
padding-block: 40px; /* 垂直内边距 */
}

.container {
margin-inline: auto; /* 水平居中 */
max-inline-size: 1200px; /* 最大宽度 */
}

.sidebar {
inline-size: 280px; /* 代替 width */
padding-inline: 20px; /* 水平内边距 */
border-inline-end: 1px solid; /* 右边框(RTL自动左边框) */
}

.main {
padding-block: 20px; /* 垂直内边距 */
padding-inline: 30px; /* 水平内边距 */
}

/* 对齐方式 */
.text-start {
text-align: start; /* 自动适应方向 */
}

.text-end {
text-align: end; /* 自动适应方向 */
}

逻辑属性的优势

  1. 国际化友好:无需为 RTL 语言单独编写样式
  2. 代码简洁:用更少的代码实现相同功能
  3. 维护方便:修改一处即可适配所有书写模式
  4. 未来兼容:适应更多书写模式

书写模式和方向设置

逻辑属性的行为取决于 writing-modedirection 属性:

/* 水平从左到右(默认) */
.horizontal-ltr {
writing-mode: horizontal-tb;
direction: ltr;
}

/* 水平从右到左(阿拉伯语、希伯来语) */
.horizontal-rtl {
writing-mode: horizontal-tb;
direction: rtl;
}

/* 垂直从右到左(繁体中文、日文) */
.vertical-rl {
writing-mode: vertical-rl;
}

/* 垂直从左到右(蒙古文) */
.vertical-lr {
writing-mode: vertical-lr;
}

新的颜色函数

CSS 新增了更直观的颜色函数:

/* oklab 和 oklch - 更符合人眼感知的颜色空间 */
.accent {
color: oklab(0.7 0.1 0.1);
background: oklch(70% 0.2 150);
}

/* color-mix() 混合颜色 */
.mixed {
background: color-mix(in srgb, red 30%, blue);
}

/* light-dark() 自动主题适配 */
:root {
color-scheme: light dark;
}

.text {
color: light-dark(#333, #ccc);
/* 浅色模式用 #333,深色模式用 #ccc */
}

accent-color 强调色

统一表单控件的主题色:

:root {
accent-color: #3498db;
}

/* 所有表单控件自动使用主题色 */
input[type="checkbox"] { }
input[type="radio"] { }
input[type="range"] { }
progress { }

text-wrap 文本换行优化

text-wrap 是 2024 年新增的重要属性,用于控制文本的换行方式,提升排版质量。

基本语法

text-wrap: wrap | nowrap | balance | pretty | stable;

属性值说明

说明
wrap默认值,在适当位置换行
nowrap不换行,内容可能溢出
balance平衡换行,使每行字符数尽量相等(适合标题)
pretty优化排版,减少孤立词(适合正文)
stable编辑时保持前面的行不变(适合可编辑内容)

使用示例

/* 标题使用 balance,让文字分布更均衡 */
h1, h2, h3 {
text-wrap: balance;
}

/* 正文使用 pretty,优化排版减少孤立词 */
article p {
text-wrap: pretty;
}

/* 可编辑区域使用 stable,编辑时前面行不跳动 */
[contenteditable] {
text-wrap: stable;
}

/* 不换行 */
.nowrap {
text-wrap: nowrap;
}

balance 与 pretty 的区别

/* balance:平衡每行字符数(适合短文本、标题) */
.headline {
text-wrap: balance;
/* 效果:如果标题分两行,两行长度会尽量接近 */
}

/* pretty:优化整体排版(适合长文本、正文) */
.article-content {
text-wrap: pretty;
/* 效果:减少孤立词、优化断词位置 */
}
性能提示
  • balance 只对 6-10 行以内的文本生效(浏览器限制)
  • pretty 会增加计算开销,仅在对排版要求高的场景使用

View Transitions 视图过渡

View Transitions API 是 2024-2025 年新增的强大特性,允许创建流畅的页面过渡动画,无需复杂的 JavaScript 代码。

基本概念

视图过渡通过捕获旧状态的快照和新状态的快照,然后在两者之间创建动画来实现平滑过渡。

基本用法

/* 为元素指定过渡名称 */
.card {
view-transition-name: card-item;
}

/* 自定义过渡动画 */
::view-transition-old(card-item) {
animation: fade-out 0.3s ease-out;
}

::view-transition-new(card-item) {
animation: fade-in 0.3s ease-in;
}

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

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

JavaScript 触发过渡

// 简单的视图过渡
function updateContent() {
if (!document.startViewTransition) {
// 不支持时直接更新
doUpdate();
return;
}

document.startViewTransition(() => {
doUpdate();
});
}

自动分配过渡名称

/* 为列表项自动分配唯一名称 */
.list-item {
view-transition-name: match-element;
/* 浏览器自动为每个元素分配唯一的内部名称 */
}

完整示例:卡片过渡

<div class="card" id="card1">
<img src="photo.jpg" alt="">
<h3>标题</h3>
</div>

<style>
.card {
view-transition-name: card;
}

/* 过渡时的动画 */
::view-transition-group(card) {
animation-duration: 0.4s;
}

::view-transition-old(card) {
animation: fade-scale-out 0.3s;
}

::view-transition-new(card) {
animation: fade-scale-in 0.3s;
}

@keyframes fade-scale-out {
from {
opacity: 1;
transform: scale(1);
}
to {
opacity: 0;
transform: scale(0.95);
}
}

@keyframes fade-scale-in {
from {
opacity: 0;
transform: scale(1.05);
}
to {
opacity: 1;
transform: scale(1);
}
}
</style>
浏览器支持

View Transitions 是较新的特性,使用前请检查浏览器支持情况:

if ('startViewTransition' in document) {
// 支持视图过渡
}

field-sizing 自动尺寸

field-sizing 属性可以让表单控件根据内容自动调整大小:

/* 文本框自动调整高度 */
textarea {
field-sizing: content;
/* 输入内容增加时自动变高 */
}

/* 固定尺寸 */
.fixed-input {
field-sizing: fixed;
}

CSS 嵌套

CSS 嵌套是现代浏览器原生支持的特性,允许在一个选择器内部嵌套另一个选择器,使样式表更易读、更模块化。这与 Sass、Less 等预处理器不同,CSS 嵌套由浏览器直接解析,无需编译。

基本语法

/* 传统写法 */
.card {
background: white;
}
.card .title {
font-size: 20px;
}
.card .content {
padding: 16px;
}
.card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

/* 嵌套写法 */
.card {
background: white;

.title {
font-size: 20px;
}

.content {
padding: 16px;
}

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

& 嵌套选择器

& 是嵌套选择器,代表父选择器:

.button {
background: #3498db;

/* 等价于 .button:hover */
&:hover {
background: #2980b9;
}

/* 等价于 .button:active */
&:active {
background: #1f6dad;
}

/* 等价于 .button.primary */
&.primary {
background: #2ecc71;
}

/* 等价于 .button .icon */
.icon {
margin-right: 8px;
}
}

复合选择器嵌套

当需要创建复合选择器(如 .a.b)时,必须使用 &

.notice {
padding: 16px;

/* 必须使用 &,否则会变成 .notice .warning(后代选择器) */
&.warning {
background: #fff3cd;
border-left: 4px solid #ffc107;
}

&.success {
background: #d4edda;
border-left: 4px solid #28a745;
}

&.error {
background: #f8d7da;
border-left: 4px solid #dc3545;
}
}

组合选择器嵌套

可以使用各种组合选择器(+~>):

.article {
/* 相邻兄弟选择器:h2 后的第一个段落 */
h2 + p {
font-size: 1.1em;
color: #666;
}

/* 通用兄弟选择器:h2 后的所有段落 */
h2 ~ p {
line-height: 1.8;
}

/* 子选择器:直接子元素 */
> p {
margin-bottom: 1em;
}
}

追加嵌套选择器

& 可以放在选择器的末尾,用于反转上下文:

.card {
border: 1px solid #ddd;

h2 {
color: #333;

/* .featured .card h2 - 当卡片在 .featured 容器内时 */
.featured & {
color: #e74c3c;
}
}
}

嵌套 @ 规则

可以在选择器内嵌套 @media@supports 等规则:

.container {
width: 100%;
padding: 16px;

@media (min-width: 768px) {
width: 750px;
margin: 0 auto;
}

@media (min-width: 1024px) {
width: 970px;
}
}

.button {
padding: 10px 20px;

@supports (backdrop-filter: blur(10px)) {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.8);
}
}

优先级规则

嵌套选择器 & 的优先级类似于 :is() 函数,使用参数中最高的优先级:

#header, .nav {
& .item {
/* 优先级等于 #header .item 或 .nav .item 中较高的那个 */
/* 即 1-0-1(来自 #header .item) */
color: blue;
}
}

嵌套的注意事项

1. 不能用于字符串拼接

/* Sass 中可以这样写,但 CSS 嵌套不支持 */
.component {
/* 错误:不能拼接字符串 */
/* &__title { } */
}

/* 正确写法 */
.component .title { }

2. 类型选择器必须在前

.item {
/* 错误:类型选择器必须在前 */
/* &Element { } */

/* 正确 */
Element& { }
}

3. 无效规则会被忽略

.parent {
color: blue;

/* 无效选择器,这整个规则块会被忽略 */
%invalid {
color: red;
}

/* 这个有效规则仍然生效 */
.valid {
color: green;
}
}

实际应用示例

/* 完整的组件样式 */
.card {
background: white;
border-radius: 8px;
overflow: hidden;
transition: transform 0.3s, box-shadow 0.3s;

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

&.featured {
border: 2px solid #3498db;
}

.card-image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}

.card-content {
padding: 20px;

.title {
font-size: 1.25rem;
margin-bottom: 8px;
}

.description {
color: #666;
line-height: 1.6;
}
}

.card-footer {
padding: 16px 20px;
border-top: 1px solid #eee;
display: flex;
justify-content: space-between;

.button {
padding: 8px 16px;

&:hover {
background: #2980b9;
}
}
}

@media (max-width: 575px) {
.card-content {
padding: 16px;
}
}
}

@layer 层叠层

@layer 是 CSS 的层叠层规则,用于更精确地控制样式的优先级。它提供了一种结构化的方式来组织和管理来自不同来源的样式,避免优先级冲突。

为什么需要层叠层?

在大型项目中,样式可能来自多个来源:基础样式、组件库、主题、第三方插件等。传统方式下,所有样式都在同一个优先级层级中竞争,容易导致:

  1. 选择器优先级不断升级
  2. 滥用 !important
  3. 样式覆盖困难

层叠层提供了"子来源"级别的优先级控制,让不同团队的样式可以和平共处。

声明层叠层

1. 语句规则声明

使用 @layer 后跟层名来声明层的顺序:

/* 声明三个层的顺序 */
@layer base, components, utilities;

/* 层的顺序决定了优先级:
- base 层优先级最低
- utilities 层优先级最高
- 未分层样式优先级高于所有层
*/
最佳实践

建议在 CSS 文件开头声明所有层,这样可以明确控制层的顺序。

2. 块规则定义

使用带花括号的 @layer 来定义层的内容:

/* 定义命名层 */
@layer base {
h1 {
font-size: 2rem;
}

p {
line-height: 1.6;
}
}

/* 定义匿名层(无法引用) */
@layer {
.temp {
display: none;
}
}

3. 导入样式到层

使用 @import 将外部样式导入到指定层:

/* 将 normalize.css 导入到 base 层 */
@import "normalize.css" layer(base);

/* 将组件库导入到 components 层 */
@import "components.css" layer(components);

/* 导入并创建嵌套层 */
@import "theme.css" layer(theme.dark);

层的优先级规则

正常样式的优先级

对于正常样式(不带 !important):

层的优先级:先声明的层 < 后声明的层 < 未分层样式
@layer base, components, utilities;

@layer base {
.button {
color: black; /* 优先级最低 */
}
}

@layer components {
.button {
color: blue; /* 优先级中等 */
}
}

@layer utilities {
.button {
color: red; /* 优先级最高(在分层样式中) */
}
}

.button {
color: green; /* 优先级高于所有层 */
}

!important 样式的优先级

对于 !important 样式,优先级顺序反转

!important 优先级:未分层 < 后声明的层 < 先声明的层
@layer base, components;

@layer base {
.item {
color: red !important; /* !important 优先级最高 */
}
}

@layer components {
.item {
color: blue !important; /* !important 优先级中等 */
}
}

.item {
color: green !important; /* !important 优先级最低 */
}

嵌套层叠层

层可以嵌套,形成层级结构:

/* 声明嵌套层 */
@layer framework, override;

@layer framework {
@layer base, theme;

@layer base {
.button {
padding: 10px;
}
}

@layer theme {
.button {
padding: 12px;
}
}
}

/* 向嵌套层添加样式 */
@layer framework.theme {
.button {
background: #3498db;
}
}

实际应用场景

1. 组织项目样式

/* 在文件开头声明层顺序 */
@layer reset, base, layout, components, utilities, overrides;

/* 重置样式 */
@layer reset {
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
}

/* 基础样式 */
@layer base {
body {
font-family: system-ui, sans-serif;
line-height: 1.5;
}

h1, h2, h3 {
line-height: 1.2;
}
}

/* 布局样式 */
@layer layout {
.container {
max-width: 1200px;
margin: 0 auto;
}

.grid {
display: grid;
gap: 20px;
}
}

/* 组件样式 */
@layer components {
.button {
padding: 10px 20px;
border-radius: 4px;
}

.card {
background: white;
border-radius: 8px;
}
}

/* 工具类 */
@layer utilities {
.text-center { text-align: center; }
.mt-4 { margin-top: 1rem; }
.hidden { display: none; }
}

2. 管理第三方样式

/* 第三方库放入低优先级层 */
@import "normalize.css" layer(vendor.reset);
@import "bootstrap.css" layer(vendor.bootstrap);

/* 自定义样式在高优先级层 */
@layer custom;

@layer custom {
/* 可以轻松覆盖第三方样式,无需提高选择器优先级 */
.btn {
border-radius: 999px;
}
}

3. 主题切换

@layer theme;

@layer theme {
:root {
--bg: white;
--text: black;
}

@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: white;
}
}

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

层叠层的优势

  1. 避免优先级战争:不同层的样式可以独立管理,无需过度提高选择器优先级
  2. 减少 !important 使用:通过层来控制优先级,而不是依赖 !important
  3. 更好的代码组织:按功能或来源分组样式
  4. 易于覆盖:第三方库的样式可以轻松覆盖
  5. 团队协作友好:不同团队可以在不同层中工作,减少冲突

与预处理器嵌套的区别

CSS 原生嵌套与 Sass/Less 等预处理器的嵌套有以下区别:

特性CSS 原生嵌套预处理器嵌套
运行方式浏览器直接解析编译为普通 CSS
& 优先级类似 :is()直接替换
字符拼接不支持支持 &__element
兼容性需要现代浏览器编译后兼容所有浏览器

滤镜效果 filter

CSS 滤镜可以对元素应用图形效果,如模糊、亮度调整、颜色变化等,是实现视觉效果的重要工具。

基本语法

/* 单个滤镜 */
filter: blur(5px);

/* 多个滤镜组合 */
filter: blur(2px) brightness(1.2) contrast(1.1);

/* 无滤镜 */
filter: none;

滤镜函数详解

blur() 模糊

/* 高斯模糊,值越大越模糊 */
.image-blur {
filter: blur(5px);
}

/* 轻微模糊效果 */
.subtle-blur {
filter: blur(1px);
}

/* 严重模糊 */
.heavy-blur {
filter: blur(20px);
}

brightness() 亮度

/* 值范围:0(全黑)到 1(原始)到更高(更亮) */
.original {
filter: brightness(1); /* 原始亮度 */
}

.darker {
filter: brightness(0.5); /* 变暗50% */
}

.brighter {
filter: brightness(1.5); /* 变亮50% */
}

contrast() 对比度

/* 值范围:0(灰色)到 1(原始)到更高(高对比) */
.high-contrast {
filter: contrast(1.5);
}

.low-contrast {
filter: contrast(0.7);
}

grayscale() 灰度

/* 值范围:0(原始)到 1(完全灰度) */
.grayscale-full {
filter: grayscale(1); /* 完全黑白 */
}

.grayscale-partial {
filter: grayscale(0.5); /* 50% 灰度 */
}

/* 常用:悬停时恢复彩色 */
.image {
filter: grayscale(1);
transition: filter 0.3s;
}

.image:hover {
filter: grayscale(0);
}

saturate() 饱和度

/* 值范围:0(完全不饱和)到 1(原始)到更高(超饱和) */
.vibrant {
filter: saturate(2); /* 双倍饱和度 */
}

.desaturated {
filter: saturate(0.5); /* 降低饱和度 */
}

hue-rotate() 色相旋转

/* 旋转色相环,值:角度(0-360deg) */
.hue-shift {
filter: hue-rotate(90deg);
}

.hue-full {
filter: hue-rotate(180deg); /* 相反色相 */
}

invert() 反转

/* 值范围:0(原始)到 1(完全反转) */
.inverted {
filter: invert(1); /* 颜色完全反转 */
}

.partial-invert {
filter: invert(0.5); /* 部分反转 */
}

sepia() 棕褐色

/* 复古效果,值范围:0(原始)到 1(完全棕褐色) */
.vintage {
filter: sepia(0.8);
}

.old-photo {
filter: sepia(1) contrast(0.9) brightness(1.1);
}

opacity() 透明度

/* 与 opacity 属性类似,但可以通过滤镜组合使用 */
.semi-transparent {
filter: opacity(0.5);
}

drop-shadow() 投影

/* 类似 box-shadow,但遵循元素的实际形状(包括透明部分) */
/* 语法:drop-shadow(水平偏移 垂直偏移 模糊半径 颜色) */
.text-shadow {
filter: drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.5));
}

/* 对不规则形状特别有用 */
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid #3498db;
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
}

/* SVG 图标的阴影 */
.icon {
filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
}

drop-shadow vs box-shadow:

特性drop-shadowbox-shadow
形状遵循元素实际形状矩形盒子
透明内容不对透明区域投影对整个盒子投影
性能相对较低相对较高
内阴影不支持支持 inset

组合滤镜效果

/* 复古照片效果 */
.vintage-photo {
filter:
sepia(0.4)
contrast(1.1)
brightness(1.1)
saturate(0.8);
}

/* 电影效果 */
.cinematic {
filter:
contrast(1.2)
saturate(0.8)
brightness(0.9);
}

/* 清晰锐化效果 */
.sharp {
filter:
contrast(1.2)
brightness(1.05)
saturate(1.1);
}

/* 梦幻效果 */
.dreamy {
filter:
blur(1px)
brightness(1.1)
contrast(0.9)
saturate(1.2);
}

滤镜动画

.image {
filter: grayscale(1);
transition: filter 0.5s ease;
}

.image:hover {
filter: grayscale(0) brightness(1.1);
}

/* 点击效果 */
.button {
transition: filter 0.1s;
}

.button:active {
filter: brightness(0.9);
}

背景滤镜 backdrop-filter

backdrop-filter 可以对元素背后的内容应用滤镜效果,常用于毛玻璃效果。

基本语法

.element {
backdrop-filter: blur(10px);
/* 必须有半透明背景才能看到效果 */
background: rgba(255, 255, 255, 0.5);
}

常见应用:毛玻璃效果

/* 经典毛玻璃 */
.glass {
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px); /* Safari 支持 */
border-radius: 8px;
padding: 20px;
}

/* 深色毛玻璃 */
.glass-dark {
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
color: white;
}

/* 半透明导航栏 */
.navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 60px;
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

/* 模态框遮罩 */
.modal-overlay {
background: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
}

backdrop-filter 支持的函数

filter 相同,常用的包括:

backdrop-filter: blur(10px);
backdrop-filter: brightness(1.2);
backdrop-filter: contrast(0.8);
backdrop-filter: grayscale(0.5);
backdrop-filter: saturate(1.5);
backdrop-filter: blur(10px) saturate(1.2);
浏览器支持

backdrop-filter 需要添加 -webkit- 前缀以支持 Safari。同时,元素必须有半透明或透明的背景才能看到效果。

混合模式

CSS 混合模式控制元素如何与其背景混合,包括 mix-blend-modebackground-blend-mode

mix-blend-mode 元素混合

控制整个元素与其下方内容的混合方式:

/* 常用混合模式 */
.element {
mix-blend-mode: normal; /* 默认,不混合 */
mix-blend-mode: multiply; /* 正片叠底 - 变暗 */
mix-blend-mode: screen; /* 滤色 - 变亮 */
mix-blend-mode: overlay; /* 叠加 */
mix-blend-mode: darken; /* 变暗 */
mix-blend-mode: lighten; /* 变亮 */
mix-blend-mode: color-dodge; /* 颜色减淡 */
mix-blend-mode: color-burn; /* 颜色加深 */
mix-blend-mode: difference; /* 差值 */
mix-blend-mode: exclusion; /* 排除 */
mix-blend-mode: hue; /* 色相 */
mix-blend-mode: saturation; /* 饱和度 */
mix-blend-mode: color; /* 颜色 */
mix-blend-mode: luminosity; /* 亮度 */
}

实用示例

/* 文字穿透效果 */
.hero {
position: relative;
background: url('hero-bg.jpg') center/cover;
}

.hero h1 {
font-size: 8vw;
font-weight: 900;
color: white;
mix-blend-mode: difference;
/* 文字颜色会根据背景自动反转 */
}

/* 图片叠加效果 */
.overlay-text {
position: absolute;
background: #3498db;
color: white;
mix-blend-mode: multiply;
}

/* 颜色滤镜效果 */
.color-overlay {
position: absolute;
inset: 0;
background: #3498db;
mix-blend-mode: color;
opacity: 0.5;
}

background-blend-mode 背景混合

控制元素的多个背景层之间的混合:

/* 单一混合模式 */
.element {
background:
url('texture.png'),
linear-gradient(to right, #3498db, #e74c3c);
background-blend-mode: overlay;
}

/* 多个混合模式 */
.multi-blend {
background:
url('texture.png'),
url('pattern.png'),
linear-gradient(to bottom, #f39c12, #9b59b6);
background-blend-mode: multiply, screen;
}

/* 彩色图片效果 */
.tinted-image {
background:
linear-gradient(to right, #3498db, #e74c3c),
url('photo.jpg');
background-blend-mode: overlay;
background-size: cover;
}

/* 双色调效果 */
.duotone {
background:
linear-gradient(to bottom, #3498db, #2ecc71),
url('photo.jpg') center/cover;
background-blend-mode: luminosity;
}

混合模式效果对比

模式效果典型用途
multiply正片叠底,变暗阴影效果、叠加深色
screen滤色,变亮发光效果、叠加浅色
overlay叠加增加对比度、纹理叠加
difference差值反色效果、艺术风格
color颜色单色调效果、着色
luminosity亮度保留亮度、改变颜色

图片适配 object-fit 和 object-position

object-fitobject-position 控制替换元素(如 <img><video>)内容如何适应其容器。

object-fit 属性

/* 填充整个容器,可能变形(默认) */
.image-fill {
object-fit: fill;
}

/* 保持比例,填满容器,可能裁剪 */
.image-cover {
object-fit: cover; /* 最常用 */
}

/* 保持比例,完整显示,可能留白 */
.image-contain {
object-fit: contain;
}

/* 保持原始尺寸 */
.image-none {
object-fit: none;
}

/* 按比例缩小以适应,不放大 */
.image-scale-down {
object-fit: scale-down;
}

效果对比:

<style>
.image-container {
width: 200px;
height: 150px;
border: 2px solid #ddd;
overflow: hidden;
}

.image-container img {
width: 100%;
height: 100%;
}
</style>

<!-- 填充(可能变形) -->
<div class="image-container">
<img src="photo.jpg" style="object-fit: fill;">
</div>

<!-- 覆盖(可能裁剪,最常用) -->
<div class="image-container">
<img src="photo.jpg" style="object-fit: cover;">
</div>

<!-- 包含(可能留白) -->
<div class="image-container">
<img src="photo.jpg" style="object-fit: contain;">
</div>

object-position 属性

控制内容在容器内的对齐位置:

/* 默认居中 */
.image {
object-fit: cover;
object-position: center center;
}

/* 顶部对齐 */
.image-top {
object-fit: cover;
object-position: center top;
}

/* 自定义位置 */
.image-custom {
object-fit: cover;
object-position: 25% 75%; /* 水平25%,垂直75% */
}

/* 聚焦人脸(假设人脸在图片上部) */
.avatar {
object-fit: cover;
object-position: center 20%;
}

实用示例

/* 固定比例图片卡片 */
.card-image {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
object-position: center;
}

/* 头像裁剪 */
.avatar {
width: 100px;
height: 100px;
border-radius: 50%;
object-fit: cover;
object-position: center top; /* 聚焦人脸区域 */
}

/* 产品图展示 */
.product-image {
width: 300px;
height: 300px;
background: #f5f5f5;
object-fit: contain; /* 完整显示产品 */
padding: 20px;
}

裁剪路径 clip-path

clip-path 属性可以创建元素的可见区域,隐藏区域外的内容。

基本形状函数

/* 矩形裁剪 */
.rect-clip {
clip-path: rect(10px 20px 30px 40px);
/* 上 右 下 左 */
}

/* 圆形裁剪 */
.circle-clip {
clip-path: circle(50%); /* 以中心为圆心,50%为半径 */
}

.circle-positioned {
clip-path: circle(30% at 70% 30%); /* 半径 at 圆心位置 */
}

/* 椭圆裁剪 */
.ellipse-clip {
clip-path: ellipse(50% 30% at center);
}

/* 多边形裁剪 */
.triangle {
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

.diamond {
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}

.hexagon {
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}

.star {
clip-path: polygon(
50% 0%, 61% 35%, 98% 35%, 68% 57%,
79% 91%, 50% 70%, 21% 91%, 32% 57%,
2% 35%, 39% 35%
);
}

/* 八边形 */
.octagon {
clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%);
}

实用示例

/* 圆形头像 */
.avatar-circle {
clip-path: circle(50%);
}

/* 对角裁剪 */
.diagonal-clip {
clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);
}

/* 箭头形状 */
.arrow-right {
clip-path: polygon(0 0, 80% 0, 100% 50%, 80% 100%, 0 100%);
}

/* 消息气泡 */
.message-bubble {
clip-path: polygon(0 0, 100% 0, 100% 80%, 80% 80%, 70% 100%, 60% 80%, 0 80%);
}

/* 悬停放大效果 */
.hover-clip {
clip-path: circle(0% at 50% 50%);
transition: clip-path 0.4s ease;
}

.hover-clip:hover {
clip-path: circle(100% at 50% 50%);
}

/* 从角落展开 */
.corner-reveal {
clip-path: circle(0% at 0% 0%);
transition: clip-path 0.5s ease;
}

.corner-reveal:hover {
clip-path: circle(150% at 0% 0%);
}

使用 SVG 路径裁剪

/* 使用 SVG 定义复杂形状 */
.svg-clip {
clip-path: url('#my-clip-path');
}
<svg width="0" height="0">
<defs>
<clipPath id="my-clip-path">
<path d="M10,10 L100,10 L100,100 L10,100 Z"/>
</clipPath>
</defs>
</svg>

<div class="svg-clip">
<img src="image.jpg" alt="SVG裁剪的图片">
</div>

CSS 计数器

CSS 计数器可以自动为元素编号,无需手动编号,常用于列表、章节标题等场景。

基本用法

CSS 计数器涉及三个属性:

  • counter-reset:创建或重置计数器
  • counter-increment:递增计数器
  • counter() / counters():显示计数器值
/* 创建计数器 */
body {
counter-reset: section; /* 创建名为 section 的计数器,初始值为 0 */
}

/* 递增计数器 */
h2 {
counter-increment: section; /* 每遇到 h2,计数器加 1 */
}

/* 显示计数器值 */
h2::before {
content: "第 " counter(section) " 章 ";
}

嵌套计数器

/* 多级编号 */
body {
counter-reset: chapter; /* 章计数器 */
}

h2 {
counter-reset: section; /* 每章重置节计数器 */
counter-increment: chapter;
}

h2::before {
content: "第 " counter(chapter) " 章 ";
}

h3 {
counter-increment: section;
}

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

counters() 函数

counters() 函数用于嵌套列表的编号:

ol {
counter-reset: item;
list-style-type: none;
}

li {
counter-increment: item;
}

li::before {
content: counters(item, ".") " ";
/* 输出:1, 1.1, 1.2, 2, 2.1, 2.1.1... */
}

实用示例

/* 自动编号列表 */
.numbered-list {
counter-reset: list-item;
list-style: none;
padding-left: 0;
}

.numbered-list li {
counter-increment: list-item;
position: relative;
padding-left: 40px;
margin-bottom: 10px;
}

.numbered-list li::before {
content: counter(list-item);
position: absolute;
left: 0;
width: 28px;
height: 28px;
background: #3498db;
color: white;
border-radius: 50%;
text-align: center;
line-height: 28px;
font-weight: bold;
}

/* 步骤指示器 */
.steps {
counter-reset: step;
}

.step {
counter-increment: step;
}

.step::before {
content: "步骤 " counter(step) ":";
font-weight: bold;
color: #3498db;
}

/* 图片自动编号 */
figure {
counter-increment: figure;
}

figure figcaption::before {
content: "图 " counter(figure) ":";
font-weight: bold;
}

多列布局 columns

CSS 多列布局可以将内容自动分成多列,类似于报纸的排版效果。

基本属性

/* 指定列数 */
.columns {
column-count: 3;
}

/* 指定列宽(自动计算列数) */
.columns-auto {
column-width: 200px;
}

/* 简写属性 */
.columns-short {
columns: 3; /* 3列 */
columns: 200px; /* 每列200px */
columns: 3 200px; /* 3列,每列至少200px */
}

列间距和规则

.multi-column {
column-count: 3;

/* 列间距 */
column-gap: 30px;

/* 列分隔线 */
column-rule: 1px solid #ddd; /* 宽度 样式 颜色 */

/* 或分别设置 */
column-rule-width: 1px;
column-rule-style: solid;
column-rule-color: #ddd;
}

跨列元素

/* 标题跨所有列 */
.column-title {
column-span: all;
}

/* 不跨列(默认) */
.column-item {
column-span: none;
}

内容填充

.columns-balance {
column-fill: balance; /* 平衡列高(默认) */
}

.columns-auto-fill {
column-fill: auto; /* 顺序填充 */
}

实用示例

/* 新闻排版 */
.news-article {
column-count: 3;
column-gap: 30px;
column-rule: 1px solid #e0e0e0;
text-align: justify;
}

.news-article h2 {
column-span: all;
text-align: center;
margin-bottom: 20px;
}

/* 图片画廊 */
.gallery-text {
column-width: 250px;
column-gap: 20px;
}

.gallery-text img {
width: 100%;
break-inside: avoid; /* 防止图片被分割 */
margin-bottom: 10px;
}

/* 瀑布流效果 */
.masonry {
column-count: 4;
column-gap: 15px;
}

.masonry-item {
break-inside: avoid;
margin-bottom: 15px;
}

/* 响应式多列 */
.responsive-columns {
column-width: 250px;
column-gap: 20px;
}

@media (max-width: 768px) {
.responsive-columns {
column-count: 2;
}
}

@media (max-width: 480px) {
.responsive-columns {
column-count: 1;
}
}

防止内容分割

/* 防止元素在列间分割 */
.no-break {
break-inside: avoid;
}

/* 强制在元素前分列 */
.break-before {
break-before: column;
}

/* 强制在元素后分列 */
.break-after {
break-after: column;
}

性能优化属性

will-change 性能提示

will-change 提示浏览器元素将发生的变化,让浏览器提前优化:

/* 提示即将变化的属性 */
.animated-element {
will-change: transform, opacity;
}

/* 悬停时提示 */
.card {
transition: transform 0.3s;
}

.card:hover {
will-change: transform;
}

/* 过度使用警告 */
/*
* 不推荐:对所有元素使用
* * { will-change: transform; }
*
* 推荐:只在需要时启用
* .modal.show { will-change: opacity, transform; }
*/
注意事项
  • 只在需要时启用 will-change
  • 不要过度使用,会增加内存消耗
  • 动画结束后移除(通过 JavaScript 或自动)

content-visibility 内容可见性

content-visibility 可以跳过不在视口内的内容渲染,显著提升页面性能:

/* 自动跳过不在视口内的内容 */
.lazy-content {
content-visibility: auto;
contain-intrinsic-size: 500px; /* 预估高度,防止布局跳动 */
}

/* 总是渲染(默认) */
.visible-content {
content-visibility: visible;
}

/* 总是隐藏 */
.hidden-content {
content-visibility: hidden;
}

contain-intrinsic-size 搭配使用:

/* 长列表优化 */
.list-item {
content-visibility: auto;
contain-intrinsic-size: 100px; /* 预估每个列表项高度 */
}

/* 文章卡片 */
.article-card {
content-visibility: auto;
contain-intrinsic-size: 400px;
}

contain 包含

contain 属性指示元素的某些方面独立于文档树的其余部分:

/* 布局包含 - 元素内部布局不影响外部 */
.layout-contained {
contain: layout;
}

/* 绘制包含 - 元素内部绘制不影响外部 */
.paint-contained {
contain: paint;
}

/* 样式包含 */
.style-contained {
contain: style;
}

/* 尺寸包含 */
.size-contained {
contain: size;
}

/* 严格包含(所有类型) */
.strict-contained {
contain: strict;
}

/* 内容包含(布局+绘制+样式) */
.content-contained {
contain: content;
}

实用示例:

/* 固定尺寸的组件 */
.widget {
contain: layout paint;
width: 300px;
height: 200px;
}

/* 第三方组件隔离 */
.third-party {
contain: strict;
}

小结

本章学习了:

  1. 文本属性:字体、大小、粗细、对齐、颜色等
  2. 背景属性:颜色、图片、重复、位置、尺寸
  3. 边框属性:宽度、样式、颜色、圆角
  4. 盒模型属性:margin、padding、width、height、box-sizing
  5. 显示属性:display 的各种值
  6. 定位属性:position 和 z-index
  7. 其他属性:overflow、opacity、cursor、shadow、transform、transition
  8. CSS 数学函数:calc()、min()、max()、clamp() 的详细用法
  9. 现代 CSS 属性:aspect-ratio、gap、container queries、scroll-snap 等
  10. CSS 逻辑属性:基于文本流方向的属性,实现国际化友好的布局
  11. CSS 嵌套:原生嵌套语法,使样式表更易读、更模块化
  12. @layer 层叠层:控制样式优先级的结构化方式
  13. 滤镜效果:filter 和 backdrop-filter 实现各种视觉效果
  14. 混合模式:mix-blend-mode 和 background-blend-mode 控制元素混合
  15. 图片适配:object-fit 和 object-position 控制替换元素内容适配
  16. 裁剪路径:clip-path 创建自定义形状的可见区域
  17. CSS 计数器:自动编号功能
  18. 多列布局:报纸式的多列排版效果
  19. 性能优化:will-change、content-visibility、contain 属性

练习

  1. 设置一个段落的完整文字样式
  2. 创建一个带渐变背景的卡片
  3. 实现不同边框样式的效果
  4. 理解 content-box 和 border-box 的区别
  5. 使用 calc() 实现固定宽度侧边栏 + 自适应内容区的布局
  6. 使用 clamp() 实现响应式字体大小
  7. 使用 min()max() 实现响应式容器宽度
  8. 使用 aspect-ratio 创建一个固定宽高比的图片容器
  9. 使用容器查询创建一个响应式卡片组件
  10. 使用逻辑属性实现一个 RTL 友好的导航栏
  11. 创建一个带 hover 动画效果的按钮
  12. 使用 filter 实现图片的黑白悬停效果
  13. 使用 backdrop-filter 实现毛玻璃导航栏
  14. 使用 clip-path 创建一个三角形元素
  15. 使用 CSS 计数器为列表项自动编号