一直以来,CSS 作为一种申明式的样式标记语言,很难像如 javascript 等命令式编程语言一样通过定义和使用变量的方式来维护和追踪某些状态。后来随着 scss,less等 CSS 预处理器的出现,我们可以像优秀的开源框架 bootstrap 那样,通过维护一个 variables.scss 变量文件的方式来维护一个庞大的项目。但预处理需要编译,并非 CSS原生支持。而现在,我们可以在原生 CSS 中使用变量了!
先来两个在线demo感受一下:
CSS 变量,也称为 CSS 自定义属性。通过以--开头的自定义属性来设置变量名,存储一些特定值,在需要的地方使用 var() 来访问。如:
p {
--primary-color: #6bc30d;
color: var(--primary-color);
}
可以像定义任何css属性一样来申明变量,不同的是,变量名必须以--开头。如 --primary-color: #6bc30d
而要使用一个变量的值,需要使用 var() 函数,并将变量的名称作为参数传入。 如 color: var(--primary-color);
var() 函数可以代替元素中任何属性中的值的任何部分。
var() 函数接受两个参数,参数一是要替换的自定义属性的名称,参数二是可选的,作为参数一无效时候的回退值(如果第一个参数引用的自定义属性无效,则该函数将使用第二个值)。
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
}
CSS变量是区分大小写的
// 这是两个不同的变量
:root {
--color: blue;
--COLOR: red;
}
虽然可以在 css 的任何地方定义变量,但是css变量也是有作用域的。CSS的变量作用域分为全局作用域和局部作用域。因此在申明一个变量之前,首先要确定这个变量要用在哪里?
通过在 :root 中申明变量,就可以申明一个全局变量,可以在整个文档结构中使用这个变量,因为 CSS 变量是可继承的。
: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><divid="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><pstyle="--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>
<buttondata-value="red">红色</button>
<buttondata-value="green">绿色</button>
<buttondata-value="blue">蓝色</button>
<buttondata-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>
