写了三年 Sass,每次想复用一段样式块都要靠 mixin 加 include——今天 CSS 自己会了

做过设计系统的都知道,组件库里最高频的诉求不是变量,是样式块复用:按钮的基础样式要复用,卡片的交互状态要复用,表单的错误提示也要复用。Sass 的 @mixin 把这件事做到了极致,但代价是你得维护一套编译链。

今天这件事在浏览器里原生化了。

Chrome 和 Edge 已经开始在 Experimental Web Platform Features 标志下实验 CSS 原生 Mixins,语法长这样:

/* 定义一个 mixin */
@mixin --card-base(--bg: white, --radius: 8px) {
  @result {
    background: var(--bg);
    border-radius: var(--radius);
    padding: 1rem;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }
}

/* 在选择器里引用 */
.card-default {
  @apply --card-base();
}

.card-dark {
  @apply --card-base(--bg: #1a1a1a, --radius: 12px);
}

参数、默认值、条件逻辑都有,输出的是直接可用的 CSS 声明块,不再需要任何编译步骤。

对比一下 Sass 的方案:

Sass 原生 CSS
参数支持 ✅(通过 CSS 自定义属性实现)
默认值
构建依赖 需要 Sass 编译器 不需要
调试体验 源码映射复杂 直接对应 CSS 源码
零运行时成本 ❌(仍有编译开销) ✅(纯 CSS,无任何开销)

实际落地最关键的问题是:目前 Chrome/Edge 还需开启实验标志,Firefox 在跟进中。所以生产环境要用,得套一层渐进增强:

/* 基线:不用 mixin,直接写 */
.card {
  background: white;
  border-radius: 8px;
  padding: 1rem;
}

/* 渐进增强:有 mixin 的浏览器会走这条 */
@supports (background: var(--x)) {
  .card {
    @apply --card-base();
  }
}

目前阶段 polyfill 方案已经有社区在做:css-mixin-polyfill 这个包支持构建时转换,可以把 @mixin/@apply 语法在构建阶段转成普通 CSS,生产环境直接用,对 Safari 和不支持的浏览器零影响。

从工程视角看这件事的价值不只是语法:它意味着 CSS 终于有了一个原生的复用原语,设计系统的样式块不再必须依赖预处理器,整个构建链路可以再简化一层。对于已经有 Sass 的团队,这是增量优化;对于新项目,可以直接押注原生方案等待浏览器全面支持。

下一步:本地开 Chrome 标志测一下语法,确认行为符合预期;同时用 css-mixin-polyfill 在构建层做生产兜底,等浏览器稳定支持后平滑迁移。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 11 阅读