12k
All articles

探索 CSS random() 函数

CSS random() 函数可在样式表中原生生成数值,借助语法、缓存键和回退机制实现视觉变化,无需依赖 JavaScript。

OpenReplay Team
OpenReplay Team
探索 CSS random() 函数

当需要随机性时,CSS 一直依赖 JavaScript——分散的位置、变化的动画延迟、不可预测的颜色变化。这种依赖可能很快会减少。CSS random() 函数是 CSS Values and Units Module Level 5 规范的一部分,它允许样式表直接生成随机数值,无需脚本。

它是实验性的。浏览器支持有限。但现在值得了解。

核心要点

  • CSS random() 函数在样式表中原生生成随机数值,在许多视觉随机性场景中消除了对 JavaScript 的需求。
  • 语法接受最小值、最大值和可选的步进值——所有参数必须共享相同的单位类型。
  • 缓存系统控制随机值是在匹配元素之间共享、按元素分配还是跨特定属性共享,让你能够精细控制随机性的分布。
  • 浏览器支持目前有限,Safari 26.2 现已提供稳定支持。始终使用 @supports 提供降级方案。

CSS random() 函数实际做什么

核心思想很简单:你定义一个最小值、一个最大值,以及可选的步进增量。CSS 从该范围中选择一个数字并应用它。

.card {
  top: random(5rem, 20rem);        /* 5rem 到 20rem 之间的任意值 */
  rotate: random(0deg, 360deg);    /* 随机旋转 */
  animation-delay: random(0s, 3s); /* 交错的动画时间 */
}

就是这样。不需要 Math.random(),不需要内联样式,不需要 JavaScript 循环生成数百个 :nth-child() 规则。

一个重要的约束:所有参数必须共享相同的单位类型。 你不能混合 rempx,或者 %em。选择一个单位并保持一致。

语法

random(<caching-options>?, <min>, <max>, [by <step>]?)

当前的草案规范更正式地定义了这个函数,但这种简化形式是在实践中理解它的最简单方式。

by 参数控制步进。没有它,你可能会得到像 13.47px 这样的小数值。有了它,你可以将输出限制为可预测的序列:

/* 可能的值:10px, 20px, 30px, 40px, 50px */
padding: random(10px, 50px, by 10px);

注意:使用步进时,最大值并不总是可达的。random(100px, 200px, by 30px) 只能产生 100px130px160px190px——永远不会是 200px

控制随机性的共享方式

这是 CSS random() 函数真正有趣的地方。默认情况下,样式表中的每个 random() 实例都会解析为一个单一的缓存值,由所有使用该样式的元素共享。

要让每个元素获得自己的唯一值,请使用 per-element 关键字或破折号标识符:

/* 每个元素获得自己的随机值 */
.item {
  top: random(per-element, 2rem, 15rem);
}

/* 两个属性在一个元素内共享相同的值 */
.box {
  width: random(--size, 100px, 200px);
  height: random(--size, 100px, 200px); /* 匹配 width */
}

/* 所有匹配的元素全局共享相同的命名值 */
.badge {
  width: random(--element-shared, 50px, 150px);
}

per-element 关键字是一个内置的缓存选项,告诉浏览器为每个匹配选择器的元素解析一个不同的随机值。像 --size 这样的破折号标识符将多个 random() 调用绑定在一起,使它们在给定元素内解析为相同的值——当你想要一个具有随机但一致的宽度和高度的正方形时很有用。像 --element-shared 这样的破折号标识符也可以作为跨匹配元素的命名缓存键。

这个缓存系统是经过深思熟虑且设计良好的——但这也是容易产生混淆的地方。尽早理解它可以节省后续的调试时间。

CSS random() vs. SCSS random()

如果你在 Sass 中使用过 random(),其行为在几个关键方面有所不同:

特性CSS random()SCSS random()
何时运行页面加载时编译时
最小/最大范围都需定义仅最大值(从 1 开始)
步进支持是(by)
重新加载时刷新

CSS random() 在每次页面加载时生成新值。SCSS 在构建时锁定值。它们服务于不同的目的。

浏览器支持

截至 2026 年初,CSS 中的 random() 已在 Safari 26.2 中发布。更广泛的跨浏览器支持尚未得到保证,因此你仍应将其视为实验性功能,并使用 @supports 进行渐进增强,提供合理的降级方案:

.element {
  top: 10rem; /* 降级方案 */
}

@supports (top: random(1rem, 5rem)) {
  .element {
    top: random(5rem, 20rem);
  }
}

CSS 工作组在 2022 年采纳了该函数,规范仍在不断演进。仍存在未解决的问题,最终语法在广泛实现之前可能还会发生变化。

结论

CSS random() 函数不会取代 JavaScript 用于逻辑驱动的随机性或任何需要加密不可预测性的场景。但对于纯粹的视觉变化——分散的布局、有机的动画时间、生成式背景——它是一个简洁、声明式的解决方案,属于样式表的范畴。

在 Safari 26.2 中尝试它,保留降级方案,并关注规范的进展。实验性和广泛可用之间的差距正在缩小。

常见问题

我今天可以在生产环境中使用 CSS random() 吗?

不能可靠地全面使用。截至 2026 年初,Safari 26.2 已发布该功能,但更广泛的跨浏览器支持仍然有限。你现在可以尝试它,但任何生产环境使用都应包含可靠的降级值和 @supports 检查,以避免在不支持的浏览器中出现布局错误。

如果我在 random() 中混合不同的单位会发生什么?

该函数将无效,浏览器将忽略该声明。传递给 random() 的所有参数,包括最小值、最大值和可选的步进值,必须使用相同的单位类型。你不能将 rem 与 px 或百分比与 em 组合。选择一个单位并在所有参数中一致使用它。

random() 中的缓存行为是如何工作的?

默认情况下,一个 random() 实例会解析为一个缓存值,由所有使用该样式的元素共享。要为每个元素获取唯一值,请使用 per-element 关键字。要在特定属性之间共享值,请使用像 --size 这样的破折号标识符。理解缓存对于获得你期望的视觉变化至关重要。

CSS random() 是否在每次页面重新加载时生成新值?

是的。与 SCSS random() 不同,后者在编译时锁定值并将其嵌入到输出的 CSS 中,原生 CSS random() 函数在每次页面加载时解析一个新值。这使其适合创建在访问之间变化的视觉多样性,而无需任何 JavaScript 参与。

Open-source session replay

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.