Kodokon kodokon.com

CSS 变量与 calc/clamp 函数

掌握自定义属性、它们如何在层叠中于运行时求值,以及用于流式界面的 calc() 和 clamp() 函数。

10 分钟 · 3 题

在 Kodokon 中打开本课

自定义属性不是预处理器变量。Sass 变量在编译时被替换;而 --brand 属性是在运行时求值的,它参与层叠、像其他属性一样继承,并且可以被媒体查询、类,或 JavaScript 通过 setProperty() 改变。正是这一点使得动态主题、无需重新编译的深色模式,以及不触发重渲染的 CSS/JS 通信成为可能。

CSS
:root {
  --brand: #6c5ce7;
  --spacing: 8px;
}

.card {
  color: var(--brand);
  padding: calc(var(--spacing) * 2);
  border-color: var(--accent, currentColor);
}
声明、读取与回退值

var() 的第二个参数是回退值,仅当该属性未定义时才会使用。经典陷阱:如果 --accent12px,而你把它注入到 color 里,回退值并不会被使用。该声明会在计算值求值阶段变为无效:属性会回退到其继承值或初始值,而不是像普通语法错误那样回退到前一条声明。

@property 规则修正了两大局限:它赋予变量一个类型(因而具备校验),并使其可动画化,因为引擎现在知道如何在两个有类型的值之间插值,而不再把变量当作一个不透明的字符串。

CSS
@property --progress {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}

.gauge {
  background: conic-gradient(
    var(--brand) var(--progress),
    #e5e7eb 0
  );
  transition: --progress 0.4s ease-out;
}

.gauge.is-full {
  --progress: 100%;
}
用 @property 定义有类型、可动画的变量

在数学方面,calc() 允许你混合单位(calc(100% - 2rem)),这在预处理器中是不可能的,因为其求解依赖于渲染上下文。clamp(min, ideal, max)max(min, min(ideal, max)) 的语法糖,在流式排版上胜过一大堆断点:理想值(常以 vwcqi 表示)会在两个边界之间自由滑动。

CSS
:root {
  --fluid-title: clamp(
    1.5rem,
    1rem + 2.5vw,
    3rem
  );
}

h1 {
  font-size: var(--fluid-title);
  max-width: clamp(20ch, 60%, 65ch);
}
无需媒体查询的流式排版

知识检测

确认你已牢记本课的重点内容。

  1. 如果在 --gap12px 时对 color: var(--gap) 求值,会发生什么?
    • 该声明被忽略,前一条 color 规则生效
    • 该声明在计算值求值阶段变为无效,color 求值为 unset
    • 浏览器把 12px 转换成一个接近黑色的颜色
    • 控制台抛出错误,样式表被拒绝
  2. clamp(1rem, 2.5vw, 2rem) 严格等价于什么?
    • max(1rem, min(2.5vw, 2rem))
    • min(1rem, max(2.5vw, 2rem))
    • calc(1rem + 2.5vw + 2rem)
  3. 相比普通的自定义属性,@property 的主要好处是什么?
    • 它使变量可以从 JavaScript 访问
    • 它允许变量在 calc() 内部使用
    • 它赋予变量一个类型,尤其使其在动画中可插值
    • 它强制变量在整个文档中继承