Language:Chinese VersionEnglish Version

过去三年,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 没有解决的三个方面:

  1. 设计标记作为实用类: text-smp-4bg-primary 将设计决策编码为可重用的原子。
  2. 就近放置: 样式与标记共存,解决了"这个样式在哪里?"的问题。
  3. 一致性: 受限的实用类集合避免了特例魔法数字。

原生 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() 在复杂选择器上的性能因浏览器而异
  • 容器查询单位(cqwcqh)在 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、更少的复杂性和更好的性能交付更好的前端。

By

Leave a Reply

Your email address will not be published. Required fields are marked *

You missed