CSS Custom Properties for Cascading Variables Module Level 1

该模块介绍了级联变量作为一新的个原始值类型被所有的CSS属性、以及定义他们的自定义属性所接受。

CSS是用于描述在屏幕上,纸上,语音等结构化文档(如HTML和XML)的呈现的语言。

【文档地址】:https://www.w3.org/TR/css-variables/

【备注信息】:这是一个未完成的翻译,需要继续进行!- 2017.7.28

1、介绍

大型的文档或者应用(即使小一点的)都会包含一些CSS。CSS中的会有很多重复的值,例如,站点可能建立在一种颜色模式上,在全站内都在使用三种或四种颜色值。如果要改变这些颜色值则会非常的困难并且容易出错,因为这些颜色值分散在了整个CSS文件中(很有可能分布在不同的文件中),不得不进行查找-替换。

该模块介绍了一系列作者定义的属性,统称为自定义属性,该属性可以让作者指定一个任意值赋给作者创建的属性名,或者var()函数,var()函数能够让作者自定义的值应用在文档中的其他属性中。这让开发者读大文件变的容易,因为看似随意的值现在都被替换成意义丰富的名称,同时编辑该文件也更容易并且减少出错,因为只需要在自定义属性中改变一次值,那么该更改会自动传播到使用该变量的所有地方。

2、定义自定义属性:属性的 --* 家族

该规范定义了一个没有限制的属性,称之为自定义属性,该属性可以是用来作为var()函数的替代值。

使用 --* 来定义自定义属性。试用于所有的元素,可以继承父级。

一个自定义属性的结构是以两个短线开头,比如 --foo,这就定义了一个自定义属性为foo,其中后面的属性名必须是有效的标识符,且前面必须是两个短线。在没有使用定义的自定义属性之前,css不会对其具有任何意义。

例1:

自定义属性用来定义变量,就像var()函数声明,它可以用在很多种情况下,比如:一个页面一直使用一个字体颜色(设计图中的规定),那么就可以把这个颜色存在自定义属性中,然后通过变量来引用它:

:root {
    --main-color: #06c;
    --accent-color: #006;
}
/*在css中使用*/
#foo h1 {
    color: var(--main-color);
}

上面的例子中,给颜色定义了一个方便记忆的名字,这样以后在使用该颜色值的时候直接通过var()方法进行引用即可,以后颜色值发生改变的时候,我们也只更改一处即可,而不是把所有的样式表修改个遍。

不像其他的css属性,自定义属性区分大小写

例2

--foo--FOO都是有效,它们是不同的属性,使用var(--foo)指向的是第一个,使用var(--FOO)指向的是第二个。

自定义属性不会被all属性重写,不过我们可以在将来定义一个属性,这个属性可以重写所有的变量。

2.1 定义属性的书法

自定义属性的语法非常宽松,

除此之外,如果一个自定义属性的值包含一个var()引用,那么这个var()引用必须符合定义的var()的语法,如果不符合的话,这个自定义属性便是无效的,会被忽略掉。

  • 注意:这个定义以及一般的css规则,自定义属性值不包含匹配的引号或括号,所以,不能包含任何影响结构的的语法,不能包括封闭的样式规则。
  • 注意: 自定义属性可以包括!important结尾,但是这会被css解析器自动从属性值中移除,然后再css样式中补充!important
  • 注意:变量的值最少包含一个字符,这个字符也可以是空格,比如--foo: ;是有效的,在var()引用的时候便被当做一个空格,但是--foo:;是无效的。

例3

/* 下面的是有效的自定义属性 */
--foo: if(x > 5) this.width = 10;

这个值作为变量使用是无效的的,但是在JavaScript中可以获取并使用它。

自定义属性的值以及通过var()引入的自定义属性的名称都是区分大小写的。

自定义属性的初始值是一个空值,

例5 继承

<style media="screen">
:root {
 --color: blue;
}
div {
 --color: green;
}
#alert {
 --color: red;
}
* {
 color: var(--color);
}
</style>
<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,
:root:lang(en) {--external-link: "external link";}
:root:lang(de) {--external-link: "externer Link";}

a[href^="http"]::after {content: " (" var(--external-link) ")"}

2.2 解决循环依赖

循坏依赖是指,在同一个属性里面,通过val()互相引用,比如:

// 这是无效的定义方式
:root {
  --one: calc(var(--two) + 20px);
  --two: calc(var(--one) - 20px);
}

// 这是有效的定义方式
:root {
    --main-color: #c06;
    --accent-background: linear-gradient(to top, var(--main-color), white);
}

// 这是有效的定义方式
<one><two><three /></two></one>
one   { --foo: 10px; }
two   { --bar: calc(var(--foo) + 10px); }
three { --foo: calc(var(--bar) + 10px); }

解决循环依赖的方法便是在高级元素树上定义自定义属性,并具有明确的值。

3、使用级联变量:var()

通过var()函数,自定义属性的值可以被其他值替换掉,var()的语法为:

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

var()函数被用来在元素上替换任何属性的值,但是不可以用来替换属性名以及选择器,或者其他在属性值之外的内容。(如果这样做的话一般会产生语法错误,或找不到变量值)。

var()函数的第一个自定义属性的名字,第二个参数是可选的,表示的是fallback。当该自定义属性的值无效的时候便使用该值。(备注:fallback可理解为取不到默认值就取fallback中的值)。

注意:fallback语法和自定义属性的语法类似,可以使用逗号。例如:var(--foo, red, blue),定义了一个fallback为red, blue,从var()函数的第一个逗号,到该函数结尾都是fallback的值。

如果一个属性中包含了一个或者多个var()函数,并且这些函数在句法上都是有效的,那么整个属性的语法在解析时假定是有效的。只有在计算值时进行语法检查,然后var()被替换。

在属性中替换var()中值的过程为:

  • 1、如果自定义属性具有第一个参数,且为animation-tainted,并且var()用在了animation属性里,
  • 2、如果自定义属性不是上面的,则去查找定义的该属性值。

  • 3、如果定义了两个参数,则使用fallback的值进行替换。

  • 4、除此之外的所有var()函数都是无效的。

/*----------------------*/
/*         例1          */
/*----------------------*/
// 此时只设置一个值
div {
    --color: green;
}
.test1 {
    color: var(--color);
}
// 该容器字体颜色为green
<div class="test1">只有一个参数<div>

/*----------------------*/
/*         例2          */
/*----------------------*/
    // 此时只设置一个值
div {
    --color: green;
}
.test1 {
    color: var(--color, blue);
}
// 该容器字体颜色为green,因为其继承了div的颜色值
<div class="test1">只有一个参数<div>

/*----------------------*/
/*         例3          */
/*----------------------*/
// 此时设置两个值
.test1 {
    color: var(--color, blue);
}
// 该容器字体颜色为blue,没有找到定义的值,就取替代值
<div class="test1">两个参数<div>

/*----------------------*/
/*   错误   例4          */
/*----------------------*/
// 此时设置两个值
.test1 {
    color: var(--color, blue, red);
}
// 这是无效的写法,'blue,red'为一个无效的颜色值
<div class="test1">两个参数<div>

以下是错误的用法:

/*----------------------*/
/*   错误   例5          */
/*----------------------*/
// var()不能声明属性名
.test1 {
    --side: margin-top;
    var(--side): 20px;
}

/*----------------------*/
/*   错误   例6          */
/*----------------------*/
// 不能拆分属性
.test1 {
    --side: 20;
    margin-top: var(--side)px;
}
// 这种做法会生成:margin-top: 20 px;数字后面带有逗号,不允许这样的语法。

//上面正确的语法可以这样写:
/*----------------------*/
/*   正确   例7          */
/*----------------------*/
.test1 {
    --side: 20;
    margin-top: calc(var(--gap) * 1px);
}

/*----------------------*/
/*   错误   例8          */
/*----------------------*/
// 属性值无法对应
.test1 {
    --side: 20px;
    background-color: var(--side);
}

四、js操作自定义css自定义属性

设置自定义属性:

element.style.setProperty('--color', 'red');

获取自定义属性:

element.style.getPropertyValue('--color');

与普通的css属性不同,自定义属性只能通过element.style.getPropertyValue来获取,以下对比:

// 普通的css样式的设置与获取
element.style.setProperty('color', 'red');
element.style['color']  // red

// 自定义属性的设置与获取
element.style.setProperty('--color', 'red');
element.style['color']  // undefined
element.style.getPropertyValue('--color');  // red

发表评论

电子邮件地址不会被公开。 必填项已用*标注