We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
如果用过 less\scss\stylus 等预处理 CSS 语言,那么你就不会对使用变量来简化我们的 CSS 开发工作感到陌生。但是你知道吗?CSS 现在也支持原生的变量了: var()。
var()
CSS 原生的变量如何使用?我们来看下:
.selector { --size: 16px; font-size: var(--size) }
这个简单的例子中,.selector 的 fontSize 值就是 16px。但是这么简单的例子凸显不出 CSS 变量的价值,我们来看个更能体现变量价值的例子:
.selector
fontSize
16px
body {--bg: #fff} p {background: var(--bg)} a {color: var(--bg)} span {border: 1px solid var(--bg)}
这个例子中,我们在 body 元素中定义了变量 --bg,并在其他三个标签上应用了变量,而且用于不同的 CSS 属性。变量无疑给我们开发 CSS 带来了便利和更好的维护性,简单修改变量值即可同时在不同 selector 和不同属性上生效。那么我们接下来再仔细看看 CSS 变量的一些特性。
body
--bg
selector
--*
CSS 变量有一个很明显的特点就是必须以 -- 起始,看起来很奇怪。早期的规范是以 var- 作为起始,所以在一些老版本浏览器中可能需要定义 var- 起始(firefox 31 以下 bug 985838)的变量名才能生效。
--
var-
我个人感觉有一个好处就是官方钦定了 CSS 变量名的烤肉串风格(Kebabs Style)写法(人都给你两个 - 了)。
-
和普通的 CSS 属性忽略大小写不同,变量名对大小写是敏感的。
body { --color: #f90; --Color: #f00; background: var(--color); /* #f90 */ }
建议变量名全小写,原因就是上面我们提到的,变量名使用烤肉串风格声明。
不同于预处理语法直接声明变量,CSS 变量必须声明在样式规则中,包括条件化规则 @media 等。
@media
--size: 20px; /* 语法错误 */ body { --size: 20px; /* 正确声明 */ }
但是在 @keyframes 中定义的变量会被作为动画属性。因为规范规定变量是 Animatable: no 的,不可以作为动画属性的。一旦在 @keyframes 中定义了变量,且有动画属性使用了该变量,那么这个属性将会受到影响,导致动画失效。
@keyframes
Animatable: no
@keyframe test { from { --color: #f00; background: var(--color)} to { --color: #fff; background: var(--color)} }
这种方式的写法,背景色不会出现变化哦。那该怎么做呢?一种方式就是多定义几个变量,比如:
@keyframe test { from { background: var(--color-start)} to { background: var(--color-end)} }
变量必须通过将变量名放入 var() 中进行引用,否则会被忽略。
body { --color: #f90; background: --color; /* 语法错误 */ background: var(--color) /* 正确 */ }
CSS 变量也遵循 CSS 的继承规则和级联优先级规则。比如,当一个规则使用了变量,但是自身没有定义该变量时,CSS 解析器会向上查找变量,试图使用父级、祖父级的变量。
.parent {--size: 20px} .parent .current {font-size: var(--size)} /* current 的规则并没有定义 --szie 变量,使用的是继承到的变量 */
当多条规则中有重复定义的变量时,解析器会按样式级联优先级来确定使用哪个值:
.current.more {--size: 20px;} /* 这条规则权重大,所以 --size 变量取值为 20px */ .current {--size: 10px}
注意没有继承关系时,可以存在多个同名变量。
<div class="one"></div> <div class="two"></div> <div class="three"></div>
.one {--size: 10px; font-size: var(--size)} .two {--size: 20px; font-size: var(--size)} .three {--size: 30px; font-size: var(--size)} /*等同于*/ .one {font-size: 10px} .two {font-size: 20px} .three {font-size: 30px}
如果需要默认值,可以在 var 方法中传入哦。
var
body {background: var(--bg, #f00)}
如果没有找到 --bg 变量,那么 #f00 会生效。
需要注意的是,在使用变量时可能出现非法值的情况:
body {--bg: 20px; background: var(--bg, #f00)}
这种情况下,规则会被解析为:
body {background: 20px}
最终 body 的背景色是透明,而不是我们在 var 中设置的默认值。也就是说,CSS 变量的默认值只在变量未声明的情况下生效,不会影响值与属性非法组合情况。
和 JS 中定义变量类似,CSS 变量也拥有变量提升的效果,但是也有差异。
console.log(a) // undefined var a = 1; console.log(a) // 1 //等同于 var a; console.log(a) a = 1; console.log(a)
JS 中变量只有声明会被提升,值还是按照正常的代码流程进行赋值。而 CSS 变量不仅声明被提升,值也会被提升。
body {background: var(--color); --color: #f00} /* 等同于 */ body {--color: #f00; background: var(--color)}
在定义变量之前使用变量,和定义变量之后使用变量效果相同。
上面的例子中我们都在 CSS 属性值的位置使用变量,那么我们可以将变量作为 CSS 属性吗?比如:
--prop : font-size; var(--prop): 12px
答案是:不可以。
虽然CSS 变量不能作为属性名,但是它可以使用另一个变量进行赋值或表达式计算:
body { --size: 10px; --big-size: calc(var(--size) * 2); }
此处,--big-size 变量的值为 20px。
--big-size
20px
赋值的时候我们需要注意给变量带上单位,如果在引用之后加上单位是不能正确解析的,如:
body { --size: 10; font-size: var(--size)px; /* 会被解析成 font-size: 10 px,数字 10 与 px 之间有一个空格 */ }
这种写法等同于给 CSS 属性设置了一个非法值。
规范中有提到可以使用 CSSOM 进行变量的获取与设置:
element.style.setProperty('--foo', '10px') element.style.setProperty('height', 'var(--foo)') // 设置元素 height 为 10px element.style.getPropertyValue('--foo') // 获取变量值,返回 10px
我们可以通过 DOM 对象的 style 属性进行 CSS 变量的取值和设置。 需要注意的事,只有 inline 到 DOM 对象的 CSS 变量能通过这种方式获取,写在 CSS 文件或 style 元素中的 CSS 变量的获取方式尚未找到,有知晓的朋友欢迎留言相告,感谢。
style
目前来看,CSS 变量在 PC 浏览器兼容性比较好,只有 IE 尚未实现。而移动端 IOS safari 已经实现了,安卓需要再等等就可以在生产使用。
当你看到这篇文章的时候可能有所变化,请前往 can i use 查看实时数据。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
了解 CSS 变量
如果用过 less\scss\stylus 等预处理 CSS 语言,那么你就不会对使用变量来简化我们的 CSS 开发工作感到陌生。但是你知道吗?CSS 现在也支持原生的变量了:
var()
。基本用法
CSS 原生的变量如何使用?我们来看下:
这个简单的例子中,
.selector
的fontSize
值就是16px
。但是这么简单的例子凸显不出 CSS 变量的价值,我们来看个更能体现变量价值的例子:这个例子中,我们在
body
元素中定义了变量--bg
,并在其他三个标签上应用了变量,而且用于不同的 CSS 属性。变量无疑给我们开发 CSS 带来了便利和更好的维护性,简单修改变量值即可同时在不同selector
和不同属性上生效。那么我们接下来再仔细看看 CSS 变量的一些特性。变量声明
--*
格式CSS 变量有一个很明显的特点就是必须以
--
起始,看起来很奇怪。早期的规范是以var-
作为起始,所以在一些老版本浏览器中可能需要定义var-
起始(firefox 31 以下 bug 985838)的变量名才能生效。我个人感觉有一个好处就是官方钦定了 CSS 变量名的烤肉串风格(Kebabs Style)写法(人都给你两个
-
了)。大小写敏感
和普通的 CSS 属性忽略大小写不同,变量名对大小写是敏感的。
建议变量名全小写,原因就是上面我们提到的,变量名使用烤肉串风格声明。
变量必须声明在样式规则中
不同于预处理语法直接声明变量,CSS 变量必须声明在样式规则中,包括条件化规则
@media
等。但是在
@keyframes
中定义的变量会被作为动画属性。因为规范规定变量是Animatable: no
的,不可以作为动画属性的。一旦在@keyframes
中定义了变量,且有动画属性使用了该变量,那么这个属性将会受到影响,导致动画失效。这种方式的写法,背景色不会出现变化哦。那该怎么做呢?一种方式就是多定义几个变量,比如:
引用变量
变量必须通过将变量名放入
var()
中进行引用,否则会被忽略。继承与级联优先级
CSS 变量也遵循 CSS 的继承规则和级联优先级规则。比如,当一个规则使用了变量,但是自身没有定义该变量时,CSS 解析器会向上查找变量,试图使用父级、祖父级的变量。
当多条规则中有重复定义的变量时,解析器会按样式级联优先级来确定使用哪个值:
注意没有继承关系时,可以存在多个同名变量。
默认值
如果需要默认值,可以在
var
方法中传入哦。如果没有找到 --bg 变量,那么 #f00 会生效。
需要注意的是,在使用变量时可能出现非法值的情况:
这种情况下,规则会被解析为:
最终 body 的背景色是透明,而不是我们在
var
中设置的默认值。也就是说,CSS 变量的默认值只在变量未声明的情况下生效,不会影响值与属性非法组合情况。变量提升
和 JS 中定义变量类似,CSS 变量也拥有变量提升的效果,但是也有差异。
JS 中变量只有声明会被提升,值还是按照正常的代码流程进行赋值。而 CSS 变量不仅声明被提升,值也会被提升。
在定义变量之前使用变量,和定义变量之后使用变量效果相同。
变量赋值
上面的例子中我们都在 CSS 属性值的位置使用变量,那么我们可以将变量作为 CSS 属性吗?比如:
答案是:不可以。
虽然CSS 变量不能作为属性名,但是它可以使用另一个变量进行赋值或表达式计算:
此处,
--big-size
变量的值为20px
。赋值的时候我们需要注意给变量带上单位,如果在引用之后加上单位是不能正确解析的,如:
这种写法等同于给 CSS 属性设置了一个非法值。
CSSOM 进行动态设置 CSS 变量
规范中有提到可以使用 CSSOM 进行变量的获取与设置:
我们可以通过 DOM 对象的
style
属性进行 CSS 变量的取值和设置。需要注意的事,只有 inline 到 DOM 对象的 CSS 变量能通过这种方式获取,写在 CSS 文件或 style 元素中的 CSS 变量的获取方式尚未找到,有知晓的朋友欢迎留言相告,感谢。
兼容性
目前来看,CSS 变量在 PC 浏览器兼容性比较好,只有 IE 尚未实现。而移动端 IOS safari 已经实现了,安卓需要再等等就可以在生产使用。
当你看到这篇文章的时候可能有所变化,请前往 can i use 查看实时数据。
Thanks
参考文献
The text was updated successfully, but these errors were encountered: