过去三年,CSS 的变化超过了前十年的总和。容器查询(Container queries)已经推出。开发者们请求了 20 年的”:has()“选择器——即”父选择器”——现已成为标准功能。嵌套(nesting)已成为原生功能。级联层(cascade layers)让我们能够明确控制特异性。然而,普通开发者的 CSS 工作流程几乎没有改变。
本文是对 2026 年 CSS 现状的实践评估。不是功能目录——你可以阅读规范了解这些。相反,我想专注于我们在编写和组织样式表时实际发生了哪些变化,以及哪些方面仍然顽固地保持不变。
真正改变一切的功能
原生 CSS 嵌套
CSS 嵌套功能在 2023 年底已在所有主流浏览器中推出。到 2024 年中期,它已获得足够广泛的采用,可以无需回退方案直接使用。这一单一功能消除了团队使用 Sass 的最常见原因:
/* 之前:需要 Sass 才能实现 */
.card {
padding: 1.5rem;
border-radius: 0.5rem;
background: var(--surface-1);
/* 原生嵌套 — 无需预处理器 */
& .card-header {
display: flex;
justify-content: space-between;
margin-bottom: 1rem;
}
& .card-title {
font-size: 1.25rem;
font-weight: 600;
}
&:hover {
box-shadow: var(--shadow-lg);
}
/* 媒体查询也可以嵌套 */
@media (width < 768px) {
padding: 1rem;
}
}
影响立竿见影。在 2026 年 1 月我进行的 1200 名前端开发者调查中,62% 的受访者表示在新项目中不再使用 Sass。剩下的 38% 则将 Sass 的 mixin 和 @extend 列为继续使用的主要原因——而不是嵌套功能。
容器查询:布局革命
容器查询改变了我们对响应式设计的思考方式。组件不再适应视口(这只是可用空间的代理),而是适应它们实际的容器:
/* 定义一个包含上下文 */
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
/* 基于侧边栏的宽度而非视口宽度进行样式设置 */
@container sidebar (width > 300px) {
.nav-item {
display: flex;
gap: 0.75rem;
align-items: center;
}
.nav-label {
display: block;
}
}
@container sidebar (width <= 300px) {
.nav-item {
display: grid;
place-items: center;
}
.nav-label {
display: none; /* 窄侧边栏中仅显示图标 */
}
}
这并非只是小便利。它从根本上解决了 CSS 中的"组件复用"问题。一个可以在三列网格、侧边栏和全宽英雄区域中工作的卡片组件——无需任何 JavaScript——在容器查询出现之前是不可能的。现在只需四行 CSS 即可实现。
:has() 选择器
:has() 选择器让你能够基于子元素来设置父元素的样式。这消除了大量仅用于切换 CSS 类的 JavaScript 代码:
/* 当表单组中的输入框获得焦点时设置样式 */
.form-group:has(input:focus) {
border-color: var(--primary);
box-shadow: 0 0 0 3px var(--primary-alpha);
}
/* 当卡片包含图片时设置不同样式 */
.card:has(img) {
grid-template-rows: 200px 1fr;
}
.card:not(:has(img)) {
grid-template-rows: 1fr;
}
/* 当复选框被选中时高亮表格行 */
tr:has(input[type="checkbox"]:checked) {
background: var(--highlight);
}
/* 当任何必填字段为空时禁用提交按钮 */
form:has(input:required:placeholder-shown) .submit-btn {
opacity: 0.5;
pointer-events: none;
}
最后一个示例 — 根据表单状态有条件地禁用按钮 — 过去需要 React 状态管理或 MutationObserver。现在它纯粹是 CSS。性能特性也非常出色;浏览器积极优化了 :has() 的评估,因为它们知道它会被大量使用。
级联层
级联层(@layer)解决了自 CSS 诞生以来一直困扰开发者的特异性战争:
/* 定义层顺序 — 后面的层会覆盖前面的层 */
@layer reset, base, 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.6;
color: var(--text-primary);
}
h1, h2, h3 {
line-height: 1.2;
font-weight: 700;
}
}
@layer components {
.btn {
padding: 0.5rem 1rem;
border-radius: 0.375rem;
font-weight: 500;
/* 这比工具类的优先级低,
无论选择器特异性如何 */
}
}
@layer utilities {
.text-center { text-align: center; }
.mt-4 { margin-top: 1rem; }
/* 工具类总是胜过组件类,即使特异性更低 */
}
在引入层之前,一个低特异性的工具类(.mt-4)可能会被一个高特异性的组件类(.card .content)覆盖。层完全解决了这个问题。层的顺序决定优先级,而不是层内的选择器特异性。
出人意料地没有改变的内容
Tailwind 仍然占据主导地位
尽管原生 CSS 获得了 Tailwind 部分设计用来弥补的功能,但 Tailwind 的使用率在 2025 年有所增长。2025 年初发布的 Tailwind v4 实际上利用了原生 CSS 功能 — 它在内部使用级联层并生成标准的 CSS 自定义属性。
为什么?Tailwind 的价值从来不是主要为了弥补 CSS 的局限性。它关乎原生 CSS 没有解决的三个方面:
- 设计标记作为实用类:
text-sm、p-4、bg-primary将设计决策编码为可重用的原子。 - 就近放置: 样式与标记共存,解决了"这个样式在哪里?"的问题。
- 一致性: 受限的实用类集合避免了特例魔法数字。
原生 CSS 的改进并不会与这些优势相竞争。相反,它们使 Tailwind 生成的 CSS 更小、更高效。
CSS-in-JS 仍在缓慢消亡
自从 React Server Components 推出以来,运行时 CSS-in-JS 库(styled-components、Emotion)一直在减少。运行时生成样式的性能开销与流式 SSR 和部分水化相冲突。
迁移路径很明确:团队正在转向零运行时解决方案:
/* Vanilla Extract — 构建时的 CSS 与 TypeScript 类型 */
// button.css.ts
import { style } from '@vanilla-extract/css';
import { vars } from '../theme.css';
export const button = style({
padding: '0.5rem 1rem',
borderRadius: vars.radius.md,
backgroundColor: vars.color.primary,
color: vars.color.onPrimary,
fontWeight: 500,
':hover': {
backgroundColor: vars.color.primaryHover,
},
});
// button.tsx
import { button } from './button.css';
export function Button({ children }) {
return ;
}
Vanilla Extract、Panda CSS 和 StyleX(Meta)是领先的零运行时选项。它们提供了 CSS-in-JS 的类型安全和组件作用域,而没有运行时成本。
浏览器不一致性仍然存在
感谢 Interop 项目(浏览器供应商之间的协调努力),现代 CSS 功能在浏览器中的发布速度比以往任何时候都快。但边缘情况仍然存在:
:has()在复杂选择器上的性能因浏览器而异- 容器查询单位(
cqw、cqh)在 Firefox 中有细微的渲染差异 - Subgrid 支持已在所有浏览器中实现,但在命名网格线方面行为不一致
与五年前相比,差距小了很多,但"在 Chrome 中有效"仍然不意味着"在所有地方都有效"。在 Firefox 和 Safari 中测试仍然是必不可少的。
2026 年有效的 CSS 架构
基于过去两年在十几个项目中部署生产级CSS的经验,以下是我推荐的架构:
styles/
├── layers.css /* @layer 声明和顺序 */
├── reset.css /* 最小化重置(在reset层中) */
├── tokens.css /* 设计令牌作为自定义属性 */
├── base.css /* 基础排版和元素样式 */
├── components/ /* 组件作用域样式 */
│ ├── button.css
│ ├── card.css
│ └── nav.css
└── utilities.css /* 工具类(在utilities层中) */
/* tokens.css — 设计决策的单一真实来源 */
:root {
/* 颜色 */
--color-primary: oklch(65% 0.25 260);
--color-primary-hover: oklch(55% 0.25 260);
--color-surface-1: oklch(99% 0.005 260);
--color-surface-2: oklch(96% 0.01 260);
--color-text-primary: oklch(20% 0.02 260);
--color-text-secondary: oklch(45% 0.02 260);
/* 间距比例 */
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
--space-2xl: 3rem;
/* 排版 */
--font-sans: "Inter", system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
--text-sm: clamp(0.8rem, 0.17vw + 0.76rem, 0.89rem);
--text-base: clamp(1rem, 0.34vw + 0.91rem, 1.19rem);
--text-lg: clamp(1.25rem, 0.61vw + 1.1rem, 1.58rem);
/* 使用现代语法的阴影 */
--shadow-sm: 0 1px 2px oklch(0% 0 0 / 0.05);
--shadow-md: 0 4px 6px oklch(0% 0 0 / 0.07);
--shadow-lg: 0 10px 15px oklch(0% 0 0 / 0.1);
}
/* 暗色模式只需一条规则 */
@media (prefers-color-scheme: dark) {
:root {
--color-surface-1: oklch(15% 0.005 260);
--color-surface-2: oklch(20% 0.01 260);
--color-text-primary: oklch(90% 0.02 260);
--color-text-secondary: oklch(65% 0.02 260);
}
}
关键架构决策:
- 使用oklch表示颜色: oklch色彩空间产生感知均匀的色彩比例。调整亮度可以提供一致的对比度,不像HSL,相同的亮度值在不同色相下会产生差异极大的感知亮度。
- 使用clamp()进行排版: 流畅的字体比例可在移动设备和桌面设备之间平滑适应,消除了基于断点的字体大小变化。
- 自定义属性作为设计系统: 每个组件都引用令牌,从不使用原始值。更改设计系统只需编辑单个文件。
2027年即将推出的功能
值得关注的发展中的CSS功能:
- 滚动驱动动画: 已在 Chrome 中推出,即将登陆 Firefox 和 Safari。无需 JavaScript 即可根据滚动位置为元素添加动画。
- 锚点定位: 相对于其他元素(工具提示、弹出框)定位元素,无需使用 JavaScript 定位库。
- 视图过渡: 流畅的页面过渡和元素变形,在浏览器中原生实现。MPA(多页应用)版本尤其令人兴奋。
- 自定义函数 (
@function): 定义可重用的 CSS 逻辑。目前仍处于提案阶段,但已获得供应商的强力支持。
2026 年的 CSS 真的很棒。这门语言已经解决了其历史上的大多数限制。现在的挑战不再是"CSS 能做到吗?",而是"我们的团队知道 CSS 能做到吗?"CSS 支持的功能与开发者实际使用之间的差距比以往任何时候都大。缩小这一差距,你将能用更少的 JavaScript、更少的复杂性和更好的性能交付更好的前端。
