Featured image of post CSS 自定义属性:可扩展样式的策略模式Featured image of post CSS 自定义属性:可扩展样式的策略模式

CSS 自定义属性:可扩展样式的策略模式

学习用于设计标记、主题切换、运行时操作、继承和预处理器集成的战略 CSS 自定义属性模式。

CSS 自定义属性(也称为 CSS 变量)从根本上改变了我们编写和维护样式表的方式。与 Sass 或 Less 中的预处理器变量不同,自定义属性是实时的、动态的,并且参与级联和继承。本文探讨了在生产应用程序中使用它们的战略模式——从设计令牌管理到运行时操作。

设计代币管理

自定义属性是设计令牌的理想载体——定义设计系统视觉语言的原子值。组织良好的标记结构按照清晰的命名约定对颜色、间距、版式和阴影进行分组。

:root {
  --color-primary-500: #3b82f6;
  --color-primary-700: #1d4ed8;
  --space-xs: 0.25rem;
  --space-md: 1rem;
  --space-xl: 2rem;
  --font-sans: "Inter", system-ui, sans-serif;
  --text-base: 1rem;
  --text-lg: 1.25rem;
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.05);
}

采用受 BEM 启发的命名空间命名约定:对于组件标记使用 --block__element--modifier,对于全局标记使用 --category-property-variant。这使得令牌树保持可预测和自记录。


主题切换

自定义属性使运行时主题切换变得简单。在 :root 上定义浅色主题,并覆盖深色主题选择器下的特定标记。

:root {
  --bg: #ffffff;
  --text: #111111;
  --border: #e5e7eb;
}
[data-theme="dark"] {
  --bg: #111111;
  --text: #f3f4f6;
  --border: #374151;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #111111;
    --text: #f3f4f6;
  }
}
body {
  background: var(--bg);
  color: var(--text);
}

使用 transition: background-color 0.3s 添加主题之间的平滑过渡,并将用户的首选项保留在 localStorage 中。这种方法可以扩展到多个主题——浅色、深色、高对比度和棕褐色——而无需重复组件样式。


使用 JavaScript 进行运行时操作

自定义属性的最大优点之一是能够在运行时读取和修改它们,而无需任何 CSS-in-JS 库。

const root = document.documentElement;
root.style.setProperty("--spacing", `${userSpacing}px`);
const currentSpacing = getComputedStyle(root).getPropertyValue("--spacing");

这使得用户可以控制字体大小、基于上传图像的动态颜色主题、滚动驱动的动画以及响应容器查询的值。该 API 在所有现代浏览器中都是一致的,并且依赖性开销为零。


继承模式

自定义属性通过 DOM 树级联,无需重复样式即可实现上下文覆盖。

.card {
  --card-padding: 1rem;
  --card-radius: 0.5rem;
}
.card.featured {
  --card-padding: 2rem;
  --card-radius: 1rem;
}
.card__body {
  padding: var(--card-padding);
  border-radius: var(--card-radius);
}

当未定义属性时,使用 var(--custom, fallback) 提供默认值。在 Shadow DOM 中,自定义属性穿透 Shadow 边界,使它们成为主题 Web 组件的标准机制。


预处理器集成

自定义属性和预处理器起到互补作用。预处理器擅长编译时任务,例如数学和混合;自定义属性在运行时动态方面表现出色。

$grid-columns: 12;
$breakpoint-md: 768px;

:root {
  --color-primary: #{$primary-hex};
  --grid-gap: 1rem;
}

.container {
  max-width: $breakpoint-md;
  column-gap: var(--grid-gap);
}
特色预处理器变量CSS 自定义属性
决议时机构建时间运行时
级联没有是的
DOM 继承没有是的
数学运算本地需要 calc()
动画没有是的

性能考虑因素

自定义属性在计算值时解析,而不是在解析期间解析。实际上,在 :root 上定义数百个标记的影响可以忽略不计。但是,请避免在 calc() 内对触发热动画路径中的布局的属性使用自定义属性。在动画较多的部分使用 contain: style paint layout 来限制重新计算范围。


后备策略

对于旧版浏览器支持,请使用带有后备值的渐进增强。

.element {
  color: #333333;
  color: var(--text-color, #333333);
}

使用 @supports (--custom: property) 的功能查询可以控制高级使用,PostCSS 插件可以在构建时编译具有回退功能的自定义属性。到 2024 年,全球支持率将超过 97%,因此主要需要针对利基企业环境进行回退。

CSS 自定义属性不再是新鲜事——它们是构建可扩展、可维护样式表的基本工具。它们策略性地与设计标记、主题切换和运行时操作一起使用,消除了整个类别的样式问题。