CSS 变量 - 为何应关注?

CSS 变量,更准确地称为 CSS 自定义属性, 都已登陆 Chrome 49它们对于减少 CSS 中的重复非常有用,并且 也可以实现强大的运行时效果,例如主题切换, 扩展/填充未来的 CSS 功能。

CSS 杂乱

在设计应用时,通常的做法是预留一组品牌 颜色。 遗憾的是,在您的 CSS 中反复使用这些颜色值会导致 这不仅是家务琐事,而且也容易出错。如果在某个时间点 因此您可以谨慎对待风吹和“查找和替换” 但对于规模足够大的项目,很容易就有危险了。

最近,许多开发者转向了 CSS 预处理器,如 SASS 或 通过使用预处理器变量解决此问题。虽然 这些工具极大地提高了开发者的工作效率, 使用的应用存在一个主要缺点,那就是它们是静态的,不能 会在运行时更改不仅添加了在运行时更改变量的功能, 推动了动态应用主题设置等新技术的发展, 对自适应设计的影响,以及对未来 CSS 进行 polyfill 的潜力 功能。随着 Chrome 49 的发布,这些功能现已在 CSS 自定义属性的形式

自定义属性简述

自定义属性为我们的 CSS 工具箱添加了两个新功能:

  • 作者能够为具有 作者选择的姓名。
  • var() 函数,允许作者在其他应用中使用这些值 属性。

下面这个简单示例演示了

:root {
    --main-color: #06c;
}

#foo h1 {
    color: var(--main-color);
}

--main-color 是作者定义的自定义属性,值为 #06c。注意事项 所有自定义属性都以两个短划线开头

var() 函数会检索自定义属性并将其自身替换为自定义属性 值,从而得出 color: #06c; 只要自定义属性已定义, 它应该可供 var 函数使用。

乍一看,语法可能有点奇怪。许多开发者问:“为什么不 只对变量名称使用 $foo 吗?”这种方法是专门用来 尽可能灵活,并且将来可能支持 $foo 宏。 如需了解背景信息,您可以参阅这篇博文 来自规范作者 Tab Atkins

自定义属性语法

自定义属性的语法非常简单。

--header-color: #06c;

请注意,自定义属性区分大小写,因此 --header-color--Header-Color 是不同的自定义属性。虽然它们可能看起来很简单, 允许使用的自定义属性的语法实际上 宽容模式。例如,以下是有效的自定义属性:

--foo: if(x > 5) this.width = 10;

虽然它作为变量并没有用,因为在任何情况下,它都是无效的。 普通属性,则有可能在 运行时。这意味着自定义属性有望解锁 有趣的技术,是当今 CSS 预处理器所无法实现的。因此 如果您在想“打哈欠,我有 SASS,谁在乎...”?那就再好好想想吧! 这些变量并不是您习惯使用的变量。

瀑布

自定义属性遵循标准级联规则,因此您可以定义相同的 属性。

:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
    While I got red set directly on me!
    <p>I’m red too, because of inheritance!</p>
</div>

这意味着,您可以利用媒体查询中的自定义属性来帮助 采用自适应设计一种使用情形是,将外边距扩大 主要版块元素:

:root {
    --gutter: 4px;
}

section {
    margin: var(--gutter);
}

@media (min-width: 600px) {
    :root {
    --gutter: 16px;
    }
}

需要注意的是,使用 目前的 CSS 预处理器,它们无法定义媒体内部的变量 查询。拥有这项技能可以释放巨大的潜力!

您也可以将自定义属性设置为从其他来源派生而来 自定义属性。这对于主题设置非常有用:

:root {
    --primary-color: red;
    --logo-text: var(--primary-color);
}

var() 函数

要检索和使用自定义属性的值,您需要使用 var() 函数。var() 函数的语法如下所示:

var(<custom-property-name> [, <declaration-value> ]? )

其中 <custom-property-name> 是作者定义的自定义属性的名称, 例如 --foo,而 <declaration-value> 是在 引用的自定义属性无效。后备值可以以英文逗号分隔 该列表将合并为一个值。例如,var(--font-stack, "Roboto", "Helvetica"); 定义了 "Roboto", "Helvetica" 的回退机制。保留 请注意,类似于外边距和内边距的简写值 因此内边距可能如下所示。

p {
    padding: var(--pad, 10px 15px 20px);
}

组件作者可以使用这些后备值编写 其元素:

/* In the component’s style: */
.component .header {
    color: var(--header-color, blue);
}
.component .text {
    color: var(--text-color, black);
}

/* In the larger application’s style: */
.component {
    --text-color: #080;
    /* header-color isn’t set,
        and so remains blue,
        the fallback value */
}

此方法对于使用阴影的 Web 组件的主题特别有用 DOM,因为自定义属性可以遍历阴影边界。网络组件作者 可以使用后备值创建初始设计,并公开主题“钩子” 自定义属性的形式

<!-- In the web component's definition: -->
<x-foo>
    #shadow
    <style>
        p {
        background-color: var(--text-background, blue);
        }
    </style>
    <p>
        This text has a yellow background because the document styled me! Otherwise it
        would be blue.
    </p>
</x-foo>
/* In the larger application's style: */
x-foo {
    --text-background: yellow;
}

使用 var() 时,需要注意一些问题。变量不能是 属性名称中。例如:

.foo {
    --side: margin-top;
    var(--side): 20px;
}

不过,这并不等同于设置 margin-top: 20px;。相反, 第二个声明无效,并作为错误抛出。

同样,您也不能(简单地)构建某个值,它的部分值由 变量:

.foo {
    --gap: 20;
    margin-top: var(--gap)px;
}

同样,这并不等同于设置 margin-top: 20px;。为了构建 值,您需要别的东西:calc() 函数。

使用 calc() 构建值

如果您以前从未使用过 calc() 函数,那么该函数稍微有点小 可让您执行计算来确定 CSS 值的工具。所有新型浏览器均支持此 API,并且可以组合使用 以构建新值。例如:

.foo {
    --gap: 20;
    margin-top: calc(var(--gap) * 1px); /* niiiiice */
}

在 JavaScript 中使用自定义属性

如需在运行时获取自定义属性的值,请使用 getPropertyValue() 所计算的 CSSStyleDeclaration 对象的方法。

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>I’m a red paragraph!</p>
/* JS */
var styles = getComputedStyle(document.documentElement);
var value = String(styles.getPropertyValue('--primary-color')).trim();
// value = 'red'

同样,要在运行时设置自定义属性的值,请使用 CSSStyleDeclaration 对象的 setProperty() 方法。

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>Now I’m a green paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'green');

您还可以将自定义属性的值设置为引用其他自定义 使用 var() 函数,在运行时调用 setProperty()

/* CSS */
:root {
    --primary-color: red;
    --secondary-color: blue;
}
<!-- HTML -->
<p>Sweet! I’m a blue paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'var(--secondary-color)');

由于自定义属性可以引用 就可以想象如何将这带来各种有趣的 运行时效应

浏览器支持

目前,Chrome 49、Firefox 42、Safari 9.1 和 iOS Safari 9.3 支持自定义 属性。

演示

试用 示例 让您快速了解现在可以利用哪些有趣的技术 自定义属性

深入阅读

如果您想详细了解自定义属性, Google Analytics 团队撰写了一本有关为什么他对自定义媒体资源感到兴奋的入门指南。 并且您可以通过其他浏览器随时查看 chromestatus.com.