CSS变量的各种玩法!!

CSS很美妙,能够为您的页面穿上衣裳,各种各样五彩斑斓的衣裳,但是对于开发者来说,他又不够灵动,于是乎有了各种各样的预处理器Sass、LESS、Stylus(笔者建议Sass的SCSS语法),这些预处理器可以很大程度的提高CSS的灵活性,增强CSS的代码组织与维护。但是毕竟不是亲生的,然后负责CSS开发的那些大牛们坐不住了,开始给CSS赋予一些新的特性,本文就来探讨下CSS变量的进展与应用。 
W3C的关于CSS变量的最新探索体现在CSS Custom Properties for Cascading Variables Module Level 1中,最新更新在2014年5月6日,目前为工作草案,所以本文章只为研究探索只用,所涉知识点存在修改的风险,W3C修改之后本文会同步更新。

所为何来

我们知道,一个网站或应用往往包含大量的CSS,这些CSS里的一些属性值往往重复使用,比如网站使用的颜色体系,背景色、文字颜色、链接颜色等,这些重复使用的属性值散落在大量的CSS文档中,如果需要修改其中的一些值,例如改版颜色,那简直是个噩梦,我们需要每个文件进行查找、替换,眼花缭乱、机械重复的大量操作难免出错、难免头大,所以CSS代码的组织与维护已经成了困扰CSS使用的重要瓶颈。 
当然,CSS预处理可以有效的解决这些问题,预处理器的使用已经成了事实上的行业标准,Sass正成为越来越多前端er的选择。但是,我们需要部署编译环境、需要让开发工具支持Sass等,需要一些额外的工作。遇事不免畅想,如果有一天,我们可以像使用普通CSS那些使用预处理器? 
于是便有了W3C的CSS Various。

剥茧抽丝

关于变量,不外乎定义和使用,接下来我们分别解析。

定义变量

我们把需要重复使用的值存放到一个自定义的属性中,这个自定义的属性用双虚线开头标识,如下面代码所示。

<code style="padding: 0.5em; border-radius: 0px; color: rgb(0, 0, 0); font-family: 'Source Code Pro', monospace;font-size:undefined; display: block; white-space: pre-wrap; box-sizing: border-box; background-color: transparent !important;" class="language-css hljs "><span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* 变量定义 */</span>
<span class="hljs-pseudo" style="color:#8888ff;box-sizing: border-box;">:root</span> <span style="box-sizing: border-box;" class="hljs-rules">{
  <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--main-color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#06c</span></span></span>;
<span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
<span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* 变量使用 */</span>
<span style="font-weight: bold; box-sizing: border-box;" class="hljs-id">#foo</span> <span style="box-sizing: border-box;" class="hljs-tag">h1</span> <span style="box-sizing: border-box;" class="hljs-rules">{
  <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span style="box-sizing: border-box;" class="hljs-function">var(--main-color)</span></span></span>;
<span style="box-sizing: border-box;" class="hljs-rule">}</span></span></code>
变量名

自定义属性名和变量名遵循CSS标识符的定义规则,可以包含字母数字(a-z,A-Z,0-9)、ISO 10646字符列表的U+00A0及以上字符、下划线(_)、连字符(-)等,不能以数字、连字符+数字、双连字符开始。 
CSS变量语法中,大小写敏感,可以包含字母、数字、下划线、连字符,且最好不以数字、连字符开头。

<code style="padding: 0.5em; border-radius: 0px; color: rgb(0, 0, 0); font-family: 'Source Code Pro', monospace;font-size:undefined; display: block; white-space: pre-wrap; box-sizing: border-box; background-color: transparent !important;" class="language-css hljs "><span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* 正确的变量名 */</span>
<span class="hljs-pseudo" style="color:#8888ff;box-sizing: border-box;">:root</span><span style="box-sizing: border-box;" class="hljs-rules">{
    <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--link-color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#06c</span></span></span>;
    <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--_hover-color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#f6c</span></span></span>;
    <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--toolTip_color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#ff0</span></span></span>;
    <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--main_background_color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#333</span></span></span>;
<span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
<span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* 下面两个变量都有效,表示两个变量 */</span>
<span class="hljs-pseudo" style="color:#8888ff;box-sizing: border-box;">:element</span><span style="box-sizing: border-box;" class="hljs-rules">{
    <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--link-color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"><span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#06c</span></span></span>;
    <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--Link-color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"><span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#66c</span></span></span>;
<span style="box-sizing: border-box;" class="hljs-rule">}</span></span></code>

变量值可以接受任何符合语法的值,它的默认值为” “,但是不能为”“,否则会报错。

变量的继承和覆盖

变量的声明和使用遵循CSS的层叠特性,类似于普通编程语言里面的变量作用域。请看下面的代码。

<code style="padding: 0.5em; border-radius: 0px; color: rgb(0, 0, 0); font-family: 'Source Code Pro', monospace;font-size:undefined; display: block; white-space: pre-wrap; box-sizing: border-box; background-color: transparent !important;" class="language-css hljs "><span class="hljs-pseudo" style="color:#8888ff;box-sizing: border-box;">:root</span> <span style="box-sizing: border-box;" class="hljs-rules">{ <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> blue</span></span>; <span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
<span style="box-sizing: border-box;" class="hljs-tag">div</span> <span style="box-sizing: border-box;" class="hljs-rules">{ <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> green</span></span>; <span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
<span style="font-weight: bold; box-sizing: border-box;" class="hljs-id">#alert</span> <span style="box-sizing: border-box;" class="hljs-rules">{ <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> red</span></span>; <span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
* <span style="box-sizing: border-box;" class="hljs-rules">{ <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span style="box-sizing: border-box;" class="hljs-function">var(--color)</span></span></span>; <span style="box-sizing: border-box;" class="hljs-rule">}</span></span>

<<span style="box-sizing: border-box;" class="hljs-tag">p</span>><span style="box-sizing: border-box;" class="hljs-tag">I</span> <span style="box-sizing: border-box;" class="hljs-tag">inherited</span> <span style="box-sizing: border-box;" class="hljs-tag">blue</span> <span style="box-sizing: border-box;" class="hljs-tag">from</span> <span style="box-sizing: border-box;" class="hljs-tag">the</span> <span style="box-sizing: border-box;" class="hljs-tag">root</span> <span style="box-sizing: border-box;" class="hljs-tag">element</span>!</<span style="box-sizing: border-box;" class="hljs-tag">p</span>>
<<span style="box-sizing: border-box;" class="hljs-tag">div</span>><span style="box-sizing: border-box;" class="hljs-tag">I</span> <span style="box-sizing: border-box;" class="hljs-tag">got</span> <span style="box-sizing: border-box;" class="hljs-tag">green</span> <span style="box-sizing: border-box;" class="hljs-tag">set</span> <span style="box-sizing: border-box;" class="hljs-tag">directly</span> <span style="box-sizing: border-box;" class="hljs-tag">on</span> <span style="box-sizing: border-box;" class="hljs-tag">me</span>!</<span style="box-sizing: border-box;" class="hljs-tag">div</span>>
<<span style="box-sizing: border-box;" class="hljs-tag">div</span> <span style="box-sizing: border-box;" class="hljs-tag">id</span>='<span style="box-sizing: border-box;" class="hljs-tag">alert</span>'>
  <span style="box-sizing: border-box;" class="hljs-tag">While</span> <span style="box-sizing: border-box;" class="hljs-tag">I</span> <span style="box-sizing: border-box;" class="hljs-tag">got</span> <span style="box-sizing: border-box;" class="hljs-tag">red</span> <span style="box-sizing: border-box;" class="hljs-tag">set</span> <span style="box-sizing: border-box;" class="hljs-tag">directly</span> <span style="box-sizing: border-box;" class="hljs-tag">on</span> <span style="box-sizing: border-box;" class="hljs-tag">me</span>!
  <<span style="box-sizing: border-box;" class="hljs-tag">p</span>><span style="box-sizing: border-box;" class="hljs-tag">I</span>’<span style="box-sizing: border-box;" class="hljs-tag">m</span> <span style="box-sizing: border-box;" class="hljs-tag">red</span> <span style="box-sizing: border-box;" class="hljs-tag">too</span>, <span style="box-sizing: border-box;" class="hljs-tag">because</span> <span style="box-sizing: border-box;" class="hljs-tag">of</span> <span style="box-sizing: border-box;" class="hljs-tag">inheritance</span>!</<span style="box-sizing: border-box;" class="hljs-tag">p</span>>
</<span style="box-sizing: border-box;" class="hljs-tag">div</span>></code>

使用变量

我们可以通过var()的方式使用变量,但是不能在属性名、选择器中使用变量,只能在属性值中使用变量,使用变量的语法如下所示。

<code style="padding: 0.5em; border-radius: 0px; color: rgb(0, 0, 0); font-family: 'Source Code Pro', monospace;font-size:undefined; display: block; white-space: pre-wrap; box-sizing: border-box; background-color: transparent !important;" class="language-css hljs "><span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* 
 * var()接受两个参数,自定义属性名(变量名)、缺省值
 * 第一个参数custom-property-name调用变量
 * 第二参数可选,指定自定义变量无效时的缺省值。
 */</span>
<span style="box-sizing: border-box;" class="hljs-tag">var</span>() = <span style="box-sizing: border-box;" class="hljs-tag">var</span>( <<span style="box-sizing: border-box;" class="hljs-tag">custom-property-name</span>> <span class="hljs-attr_selector" style="color:#8888ff;box-sizing: border-box;">[, <any-value> ]</span>? )

<span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* for example */</span>
<span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* In the component’s style: */</span>
<span style="box-sizing: border-box;" class="hljs-class">.component</span> <span style="box-sizing: border-box;" class="hljs-class">.header</span> <span style="box-sizing: border-box;" class="hljs-rules">{
  <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span style="box-sizing: border-box;" class="hljs-function">var(--header-color, blue)</span></span></span>;
<span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
<span style="box-sizing: border-box;" class="hljs-class">.component</span> <span style="box-sizing: border-box;" class="hljs-class">.text</span> <span style="box-sizing: border-box;" class="hljs-rules">{
  <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span style="box-sizing: border-box;" class="hljs-function">var(--text-color, black)</span></span></span>;
<span style="box-sizing: border-box;" class="hljs-rule">}</span></span>

<span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* In the larger application’s style: */</span>
<span style="box-sizing: border-box;" class="hljs-class">.component</span> <span style="box-sizing: border-box;" class="hljs-rules">{
  <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--text-color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#080</span></span></span>;
  <span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/* header-color isn’t set,
     and so remains blue,
     the fallback value */</span>
<span style="box-sizing: border-box;" class="hljs-rule">}</span></span></code>

我们可以嵌套调用CSS变量。

<code style="padding: 0.5em; border-radius: 0px; color: rgb(0, 0, 0); font-family: 'Source Code Pro', monospace;font-size:undefined; display: block; white-space: pre-wrap; box-sizing: border-box; background-color: transparent !important;" class="language-css hljs "><span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/*one example */</span>
<span class="hljs-pseudo" style="color:#8888ff;box-sizing: border-box;">:root</span> <span style="box-sizing: border-box;" class="hljs-rules">{
  <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--main-color</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span class="hljs-hexcolor" style="color:#0880;box-sizing: border-box;">#c06</span></span></span>;
  <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--accent-background</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span style="box-sizing: border-box;" class="hljs-function">linear-gradient(to top, <span style="box-sizing: border-box;" class="hljs-function">var(--main-color)</span>, white)</span></span></span>;
<span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
<span class="hljs-comment" style="color:#888888;box-sizing: border-box;">/*another example */</span>
<<span style="box-sizing: border-box;" class="hljs-tag">one</span>><<span style="box-sizing: border-box;" class="hljs-tag">two</span>><<span style="box-sizing: border-box;" class="hljs-tag">three</span> /></<span style="box-sizing: border-box;" class="hljs-tag">two</span>></<span style="box-sizing: border-box;" class="hljs-tag">one</span>>
<span style="box-sizing: border-box;" class="hljs-tag">one</span>   <span style="box-sizing: border-box;" class="hljs-rules">{ <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--foo</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span class="hljs-number" style="color:#8800;box-sizing: border-box;">10</span>px</span></span>; <span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
<span style="box-sizing: border-box;" class="hljs-tag">two</span>   <span style="box-sizing: border-box;" class="hljs-rules">{ <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--bar</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span style="box-sizing: border-box;" class="hljs-function">calc(<span style="box-sizing: border-box;" class="hljs-function">var(--foo)</span> + <span class="hljs-number" style="color:#8800;box-sizing: border-box;">10</span>px)</span></span></span>; <span style="box-sizing: border-box;" class="hljs-rule">}</span></span>
<span style="box-sizing: border-box;" class="hljs-tag">three</span> <span style="box-sizing: border-box;" class="hljs-rules">{ <span style="box-sizing: border-box;" class="hljs-rule"><span style="box-sizing: border-box;" class="hljs-attribute">--foo</span>:<span class="hljs-value" style="color:#8800;box-sizing: border-box;"> <span style="box-sizing: border-box;" class="hljs-function">calc(<span style="box-sizing: border-box;" class="hljs-function">var(--bar)</span> + <span class="hljs-number" style="color:#8800;box-sizing: border-box;">10</span>px)</span></span></span>; <span style="box-sizing: border-box;" class="hljs-rule">}</span></span></code>

兼容并包

对于前端开发者来说,兼容并包永远是一个难以企及的痛,作为一个具有“极客思维”的前端er,我们还是要努力。 
首先来看看,CSS变量目前的惨不忍睹的兼容性,如下图所示,数据来自caniuse。 
这里写图片描述
全线飘红有木有,只有firefox认识,还怎么玩。 
有兄弟说,我就要任性,就要玩怎么办?老外写了个补丁(polyfill),大家不妨一试。

只求甚解

综上所述,CSS变量处于草案阶段,浏览器兼容一般,今天写这篇文章仅为开阔视野,储备知识之用。商用还请大家使用Sass或LESS等预处理器。 
如欲了解更多详情,使用下面的列表乃求甚解。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值