写了八年 Sass,每次想复用一段值逻辑都要靠变量硬凑——今天 CSS 自己会了

你一定见过这种代码:Sass 里写一个 $base-color 变量,然后一堆 $primary-dark、$primary-darker、$primary-darkest,全靠手算百分比拼出来。每次加一个新颜色都要复制粘贴一整列。

这事今天被 Chrome 139 里一个叫 @function 的 CSS 规范彻底原生化了——不再需要预处理器,不再需要构建步骤,浏览器自己算。

它是什么

CSS @function 让你在样式表里直接定义带参数、可复用、有逻辑的值函数。语法长这样:

@function --generate-shade(--base-color, --percentage) {
  result: color-mix(in srgb, var(--base-color), black var(--percentage));
}

.themed {
  --primary-color: #3b82f6;
  --primary-color-dark: --generate-shade(var(--primary-color), 20%);
}

@function 定义函数,result 描述符返回计算结果,调用时用 –function-name() 语法——和普通 CSS 自定义属性几乎一样,只是多了括号和参数。

和 Sass/Less 什么关系

先别急着喊「Sass 死了」。@function 目前只处理,不处理声明块。它替代的是 Sass 里的函数(不是 @mixin),比如这样:

// Sass 函数
@function generate-shade($color, $percent) {
  @return mix(black, $color, $percent);
}

.button { background: generate-shade($primary, 20%); }

对应 CSS 原生写法:

@function --generate-shade(--color, --percent) {
  result: color-mix(in srgb, var(--color), black calc(var(--percent) * 1%));
}

.button { background: --generate-shade(var(--primary), 20); }

构建步骤没了,但参数传递、逻辑计算、颜色混算这些能力都在。

那 @mixin 呢?那个用 @apply 应用的规范目前没有任何浏览器支持,连 Chrome 实验都没开。Sass 的 @mixin 体系暂时还动不了。

实战场景

场景一:色值派生

不用再写一整列 darken/lighten 变量了:

@function --shade(--color, --pct) {
  result: color-mix(in srgb, var(--color), black var(--pct));
}

@function --tint(--color, --pct) {
  result: color-mix(in srgb, var(--color), white var(--pct));
}

:root { --brand: #3b82f6; }

.card       { background: var(--brand); }
.card-dark  { background: --shade(var(--brand), 20%); }
.card-light { background: --tint(var(--brand), 80%); }

场景二:流体间距

不再需要 clamp 硬写:

@function --fluid-space(--min, --max, --viewport-min: 320, --viewport-max: 1200) {
  result: clamp(var(--min), calc(var(--min) + (var(--max) - var(--min)) * ((100vw - var(--viewport-min) * 1px) / (var(--viewport-max) - var(--viewport-min)))), var(--max));
}

.section { padding: --fluid-space(16px, 48px); }

场景三:带默认值的参数

默认参数规范还没广泛支持,用函数体内 var() 兜底:

@function --scale(--size) {
  --safe: var(--size, 1rem);
  result: calc(var(--safe) * 1.5);
}

.box-1 { width: --scale();      /* 1.5rem */ }
.box-2 { width: --scale(2rem); /* 3rem   */ }

浏览器支持

  • Chrome 139+ ✅(2025年8月稳定发布)
  • Edge 139+ ✅
  • Opera 123+ ✅
  • Firefox ❌
  • Safari ❌
  • 全球覆盖率:约 73%(Chrome + Edge + Opera 桌面版合计)

三个坑:

坑一:只有值,没有声明块。 很多文章说「Sass 末日到了」,实际上 @mixin/@apply 根本还没进任何浏览器。能用的是 @function,只处理值层面,别期待太高。

坑二:默认参数。 参数表里的默认值语法(–size: 1rem)还没广泛实现,用函数体内的 –safe: var(–size, 1rem) 代替。

坑三:渐进增强必须做。 老浏览器不认识 @function,需要先写兜底值:

.element {
  --border-color: #cc0000;  /* 兜底,老浏览器用这个 */
  --border-color: --generate-shade(crimson, 10%); /* 新浏览器覆盖 */
}

三步下一步

  1. 打开 Chrome 139+ 试跑 — 在 DevTools Elements 面板里直接写一个 @function 测试,–transparent(color, alpha) 那种
  2. 改造一个 Sass 函数 — 选项目里用 @function 或运算拼出来的色值/间距工具,改成 CSS @function,保留 Sass 作为 fallback
  3. 加 @supports 渐进增强 — 用 @supports (background: --generate-shade(red, 20%)) 做显式特性检测,比级联兜底更安全

CSS 正在一点点吃掉预处理器最核心的能力。@function 只是开始,@mixin/@apply 还在规范讨论里。等 Safari 和 Firefox 也跟上来,Sass 的工具函数层可能真的要重新评估了。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 45 阅读