本文首发于个人博客javascript
一直以来,CSS做为一种申明式的样式标记语言,很难像如javascript
等命令式编程语言同样经过定义和使用变量的方式来维护和追踪某些状态。后来随着scss
,less
等CSS预处理器的出现,咱们能够像优秀的开源框架bootstrap
那样,经过维护一个_variables.scss
变量文件的方式来维护一个庞大的项目。但预处理须要编译,并不是CSS原生支持。而如今,咱们能够在原生CSS中使用变量了!css
先来两个在线demo感觉一下:html
CSS变量,也称为CSS自定义属性。经过以--
开头的自定义属性来设置变量名,存储一些特定值,在须要的地方使用var()
来访问。如:
p { --primary-color: #6bc30d; color: var(--primary-color); }
能够像定义任何css属性同样来申明变量,不一样的是,变量名必须以--
开头。如 --primary-color: #6bc30d
java
而要使用一个变量的值,须要使用 var() 函数,并将变量的名称做为参数传入。 如 color: var(--primary-color);
git
var()
函数var()函数能够代替元素中任何属性中的值的任何部分。
var()
函数接受两个参数,参数一是要替换的自定义属性的名称,参数二是可选的,做为参数一无效时候的回退值(若是第一个参数引用的自定义属性无效,则该函数将使用第二个值)。github
var( <custom-property-name> [, <declaration-value> ]? ) /*<custom-property-name> 自定义属性名*/ /*<declaration-value> 声明值(回退值)*/
--
开头/*这样是错误的*/ p { --primary-color: color; var(--primary-color) : #6bc30d }
calc
函数:/*这样是错误的*/ p { --font-size : 20px * 2; font-size: var(--font-size); } /*这样是正确的*/ p { --font-size : calc(20px * 2); font-size: var(--font-size); /*40px*/ } /*这样拼接也是无效的*/ p { --font-size: 20; font-size: var(--font-size)px; /*无效*/ } /*这样是有效的:*/ p { --font-size: 20; font-size: calc(var(--font-size) * 1px); /*20px*/ }
/*这是两个不一样的变量*/ :root { --color: blue; --COLOR: red; }
scss
等CSS预处理中变量的区别虽然能够在css的任何地方定义变量,可是css变量也是有做用域的。CSS的变量做用域分为全局做用域和局部做用域。所以在申明一个变量以前,首先要肯定这个变量要用在哪里?编程
经过在:root
中申明变量,就能够申明一个全局变量,能够在整个文档结构中使用这个变量,由于CSS变量是可继承的。bootstrap
:root{ --primay-color: #6bc30d; } /* 在任何地方均可以使用`:root`中定义的全局变量 */ p, div , a { color : var(--primay-color); } #myDiv, .myDiv { color : var(--primay-color); }
能够在除:root
外的任何地方申明局部变量。可是局部变量只可以在被申明的元素及其子元素中使用。局部变量更多的应用在值覆盖上。浏览器
.modal { --modal-padding-top: 30px; } /*当前元素及其子元素中使用*/ .modal, .modal-content { padding-top: var(--modal-padding-top); /*30px*/; } /*在其余元素上无效*/ body { padding-top: var(--modal-padding-top); /*无效设置,使用默认值*/ }
与其余CSS属性同样,CSS中的变量也是能够继承的。框架
:root{ --color: red; } P { --pColor: green; color: var(--color); /*red*/ } p > span{ color : var(-pColor); /*green*/ }
同名变量能够重复申明,这样变量就会有了优先级的问题,以下例子:
:root { --color: red; } div { --color: green; } #myDiv { --color: yellow; --color: blue; } * { color: var(--color); }
<p>我正常显示红色</p> <div>我显示绿色</div> <div id="myDiv"> 我显示蓝色 <p>那么我呢?</p> </div>
如图,div
中的局部变量覆盖了:root
中设置的值,而特定ID的div元素#myDiv
又覆盖了div
中的值,最后做为#myDiv
的子元素p
继承了其父级的值,而不是使用root
中申明的值
对于变量来说,CSS属性的有效性并不适用。对于变量这种自定义属性,即使在上下文环境中这个值是无心义的,可是都可以经过var()
函数调用。无心义的变量值会致使无效的CSS申明。经过var()
函数调用后会被解析为初始值。
:root { --color: 20px; } p { --font-size: green; background-color: var(--color); /* background-color: 20px; 无效,将回退为transparent */ }
就像其余CSS属性同样,在html中能够经过内联变量
来设置变量的值,而且也可以正常工做
<style> p { color: var(--color); } </style> <body> <p style="--color:red; --font-size: 50px; font-size:var(--font-size);"> 我使用内联变量值得方式来设置样式 <!-- 将显示为字号50px,颜色红色 --> </p> </body>
能够根据屏幕宽度的变化来改变变量的值,从而更容易的实现响应式布局。
:root { --font-size: 30px; --color: red; } html{ color: var(--color); font-size: var(--font-size); } @media screen and (min-width: 480px) { :root { --font-size: 50px; --color: green; } } @media screen and (min-width: 760px) { :root { --font-size: 100px; --color: blue; } }
css变量是DOM的一部分,这意味着咱们能够经过javascript
来访问/修改css变量的值,这是scss
等css预处理器所作不到的。
要用JavaScript来更新CSS变量,须要调用已声明变量元素上的style
对象上的 setProperty
方法。
//语法 element.style.setProperty(propertyName, value, priority); //propertyName 是一个 DOMString 被更改的CSS属性. //value <可选> 是一个 DOMString 新的属性值. 若是没有指定, 则看成空字符.不能包含 "!important" //priority <可选> 是一个 DOMString。容许 "important" CSS 优先被设置. 若是没有指定, 则看成空字符. //在根元素(html)上更新变量值 document.documentElement.style.setProperty(propertyName, value)
:root { --font-size: 20px; --background: red; } body { font-size: var(--font-size); background-color: var(--background); color: #fff; }
<h1>使用JavaScript来改变背景色</h1> <button data-value="red">红色</button> <button data-value="green">绿色</button> <button data-value="blue">蓝色</button> <button data-value="yellow">黄色</button> <script> let $buttons = document.querySelectorAll('button') $buttons.forEach(button => { button.addEventListener('click', () => { let value = button.dataset.value document.documentElement.style.setProperty('--background', value) }) }) </script>
本文首发于个人博客