aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/css/using_css_custom_properties/index.html
blob: 5699003a1ee5edafe3d9e5e2c29c9b94e3be3879 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
---
title: 使用CSS自定义属性(变量)
slug: Web/CSS/Using_CSS_custom_properties
tags:
  - ':root'
  - CSS
  - Using CSS variables
  - variable
translation_of: Web/CSS/Using_CSS_custom_properties
---
<div><strong>自定义属性</strong>(有时候也被称作<strong>CSS变量</strong>或者<strong>级联变量</strong>)是由CSS作者定义的,它包含的值可以在整个文档中重复使用。由自定义属性标记设定值(比如: <strong><code>--main-color: black;</code></strong>),由<a href="/zh-CN/docs/Web/CSS/var">var() </a>函数来获取值(比如: <code>color: <strong>var(--main-color)</strong>;</code></div>



<div>复杂的网站都会有大量的CSS代码,通常也会有许多重复的值。举个例子,同样一个颜色值可能在成千上百个地方被使用到,如果这个值发生了变化,需要全局搜索并且一个一个替换(很麻烦哎~)。自定义属性在某个地方存储一个值,然后在其他许多地方引用它。另一个好处是语义化的标识。比如,<code>--main-text-color</code> 会比 <code>#00ff00</code> 更易理解,尤其是这个颜色值在其他上下文中也被使用到。</div>



<div>自定义属性受级联的约束,并从其父级继承其值。</div>

<h2 id="基本用法">基本用法</h2>

<p>声明一个自定义属性,属性名需要以两个减号(<code>--</code>)开始,属性值则可以是任何有效的CSS值。和其他属性一样,自定义属性也是写在规则集之内的,如下:</p>

<pre class="brush:css; highlight:[2]  language-css notranslate">element {
  --main-bg-color: brown;
}
</pre>

<p>注意,规则集所指定的选择器定义了自定义属性的可见作用域。通常的最佳实践是定义在根伪类 {{cssxref(":root")}} 下,这样就可以在HTML文档的任何地方访问到它了:</p>

<pre class="brush: css notranslate">:root {
  --main-bg-color: brown;
}</pre>

<p>然而这条规则不是绝对的,如果有理由去限制你的自定义属性,那么就应该限制。</p>

<div class="blockIndicator note">
<p><strong>注意:</strong>自定义属性名是大小写敏感的,<code>--my-color</code><code>--My-color</code> 会被认为是两个不同的自定义属性。</p>
</div>

<p>如前所述,使用一个局部变量时用 {{cssxref("var()")}} 函数包裹以表示一个合法的属性值:</p>

<pre class="brush:css; highlight:[2]  language-css notranslate">element {
  background-color: var(--main-bg-color);
}
</pre>

<h2 id="使用自定义属性的第一步">使用自定义属性的第一步</h2>

<p>我们从这个简单的CSS代码开始,它将相同的颜色应用在了不同class的元素上:</p>

<pre class="brush: css notranslate"><code>.one {
  color: white;
  background-color: brown;
  margin: 10px;
  width: 50px;
  height: 50px;
  display: inline-block;
}

.two {
  color: white;
  background-color: black;
  margin: 10px;
  width: 150px;
  height: 70px;
  display: inline-block;
}
.three {
  color: white;
  background-color: brown;
  margin: 10px;
  width: 75px;
}
.four {
  color: white;
  background-color: brown;
  margin: 10px;
  width: 100px;
}

.five {
  background-color: brown;
}</code>
</pre>

<p>应用在如下HTML上:</p>

<pre class="brush: html notranslate"><code>&lt;div&gt;
  &lt;div class="one"&gt;1:&lt;/div&gt;
  &lt;div class="two"&gt;2: Text &lt;span class="five"&gt;5 - more text&lt;/span&gt;&lt;/div&gt;
  &lt;input class="three"&gt;
  &lt;textarea class="four"&gt;4: Lorem Ipsum&lt;/textarea&gt;
&lt;/div&gt;</code>
</pre>

<p>其呈现是:</p>

<p>{{EmbedLiveSample("First_steps_with_custom_properties",600,180)}}</p>

<p>注意到在CSS代码中的重复:背景色 <code>brown</code> 被多处设置。对于一些CSS声明,是可以在级联关系更高的位置设置,通过CSS继承自然地解决这个重复的问题。但在一般项目中,是不可能通过这样的方式去解决。通过在 {{cssxref(":root")}} 伪类上设置自定义属性,然后在整个文档需要的地方使用,可以减少这样的重复性:</p>

<pre class="brush: css notranslate"><code>:root {
  --main-bg-color: brown;
}

.one {
  color: white;
  background-color: var(--main-bg-color);
  margin: 10px;
  width: 50px;
  height: 50px;
  display: inline-block;
}

.two {
  color: white;
  background-color: black;
  margin: 10px;
  width: 150px;
  height: 70px;
  display: inline-block;
}
.three {
  color: white;
  background-color: var(--main-bg-color);
  margin: 10px;
  width: 75px;
}
.four {
  color: white;
  background-color: var(--main-bg-color);
  margin: 10px;
  width: 100px;
}

.five {
  background-color: var(--main-bg-color);
}</code>
</pre>

<p>这里呈现的结果和前面的例子是一致的,但允许对所需属性值进行一个规范的声明。</p>

<h2 id="自定义属性的继承性">自定义属性的继承性</h2>

<p>自定义属性会继承。这意味着如果在一个给定的元素上,没有为这个自定义属性设置值,在其父元素上的值会被使用。看这一段HTML:</p>

<pre class="notranslate"><code>&lt;div class="one"&gt;
  &lt;div class="two"&gt;
    &lt;div class="three"&gt;&lt;/div&gt;
    &lt;div class="four"&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;</code>
</pre>

<p>配套的CSS:</p>

<pre class="notranslate"><code>.two {
  --test: 10px;
}

.three {
  --test: 2em;
}</code></pre>

<p>在这个情况下, <code>var(--test)</code> 的结果分别是:</p>

<ul>
 <li>对于元素 <code>class="two"</code><code>10px</code></li>
 <li>对于元素 <code>class="three"</code><code>2em</code></li>
 <li>对于元素 <code>class="four"</code><code>10px</code> (继承自父属性)</li>
 <li>对于元素 <code>class="one"</code><em>非法值</em>,会变成自定义属性的默认值</li>
</ul>

<p>注意,这些是自定义属性,并不是你在其他编程语言中遇到的实际的变量。这些值仅当需要的时候才会计算,而并不会按其他规则进行保存。比如,你不能为元素设置一个属性,然后让它从兄弟或旁支子孙规则上获取值。属性仅用于匹配当前选择器及其子孙,这和通常的CSS是一样的。</p>

<h2 id="自定义属性备用值">自定义属性备用值</h2>

<p>{{cssxref("var()")}} 函数可以定义多个<strong>备用值</strong>(fallback value),当给定值未定义时将会用备用值替换。这对于 <a href="/zh-CN/docs/Web/Web_Components/Using_custom_elements">Custom Elements</a><a href="/zh-CN/docs/Web/Web_Components/Using_shadow_DOM">Shadow DOM</a> 都很有用。</p>

<div class="blockIndicator note">
<p><strong><u>备用值</u>并不是用于实现浏览器兼容性的。</strong>如果浏览器不支持CSS自定义属性,备用值也没什么用。<strong>它仅对支持CSS自定义属性的浏览器提供了一个备份机制</strong>,该机制仅当给定值未定义或是无效值的时候生效。</p>
</div>

<p>函数的第一个参数是<a href="https://www.w3.org/TR/css-variables/#custom-property">自定义属性</a>的名称。如果提供了第二个参数,则表示备用值,当<a href="https://www.w3.org/TR/css-variables/#custom-property">自定义属性</a>值无效时生效。第二个参数可以嵌套,但是不能继续平铺展开下去了,例如:</p>

<pre class="brush: css notranslate">.two {
  color: var(--my-var, red); /* Red if --my-var is not defined */
}

.three {
  background-color: var(--my-var, var(--my-background, pink)); /* pink if --my-var and --my-background are not defined */
}

.three {
  background-color: var(--my-var, --my-background, pink); /* Invalid: "--my-background, pink" */
}</pre>

<p>第二个例子展示了如何处理一个以上的 fallback。该技术可能会导致性能问题,因为它花了更多的时间在处理这些变量上。</p>

<div class="blockIndicator note">
<p><strong>注意:</strong><a href="https://www.w3.org/TR/css-variables/#custom-property">自定义属性</a>这些 fallback 语法允许使用逗号。比如 <code>var(--foo, red, blue)</code> 定义了一个 <code>red, blue</code> 的备用值——从第一个逗号到最后的全部内容,都会被作为备用值的一部分。</p>
</div>

<h2 id="有效性和值">有效性和值</h2>

<p>传统的CSS概念里,有效性和属性是绑定的,这对自定义属性来说并不适用。当自定义属性值被解析,浏览器不知道它们什么时候会被使用,所以必须认为这些值都是<em>有效的</em></p>

<p>不幸的是,即便这些值是有效的,但当通过 <code>var()</code> 函数调用时,它在特定上下文环境下也可能不会奏效。属性和自定义变量会导致无效的CSS语句,这引入了一个新的概念:<em>计算时有效性</em></p>

<h2 id="无效变量会导致什么?">无效变量会导致什么?</h2>

<p>当浏览器遇到无效的 <code>var()</code> 时,会使用继承值或初始值代替。</p>

<p>考虑如下代码:</p>

<h3 id="HTML">HTML</h3>

<pre class="brush: html notranslate">&lt;p&gt;This paragraph is initial black.&lt;/p&gt; </pre>

<h3 id="CSS">CSS</h3>

<pre class="brush: css notranslate">:root { --text-color: 16px; }
p { color: blue; }
p { color: var(--text-color); }
</pre>

<p>毫不意外,浏览器将 <code>--text-color</code> 的值替换给了 <code>var(--text-color)</code>,但是 <code>16px</code> 并不是 {{cssxref("color")}} 的合法属性值。代换之后,该属性不会产生任何作用。浏览器会执行如下两个步骤:</p>

<ol>
 <li>检查属性 color 是否为继承属性。是,但是 <code>&lt;p&gt;</code> 没有任何父元素定义了 color 属性。转到下一步。</li>
 <li>将该值设置为它的<strong>默认初始值</strong>,比如 black。</li>
</ol>

<h3 id="Result">Result</h3>

<p>{{EmbedLiveSample('What_happens_with_invalid_variables')}}</p>

<p>段落颜色并不是蓝色,因为无效代换导致了它被替换成了默认初始值的黑色。如果你直接写n <code>color: 16px</code> 的话,则会导致语法错误,而前面的定义则会生效(段落显示为蓝色)。</p>

<div class="note">
<p><strong>注意:</strong>当CSS属性-值对中存在语法错误,该行则会被忽略。然而如果自定义属性的值无效,它并不会被忽略,从而会导致该值被覆盖为默认值。</p>
</div>

<h2 id="JavaScript_中的值">JavaScript 中的值</h2>

<p>在 JavaScript 中获取或者修改 CSS  变量和操作普通 CSS 属性是一样的:</p>

<pre class="notranslate">// 获取一个 Dom 节点上的 CSS 变量
element.style.getPropertyValue("--my-var");

// 获取任意 Dom 节点上的 CSS 变量
getComputedStyle(element).getPropertyValue("--my-var");

// 修改一个 Dom 节点上的 CSS 变量
element.style.setProperty("--my-var", jsVar + 4);</pre>

<h2 id="Browser_compatibility" name="Browser_compatibility">浏览器支持</h2>

<p>{{Compat("css.properties.custom-property")}}</p>

<div class="blockIndicator note">
<p><strong>注意:</strong>自定义属性的前缀 <code>var-</code> 是早期标准规定的,后期改为了 <code>--</code>。Firefox 31 和以后的版本遵循新的标准。 ({{bug(985838)}})</p>
</div>

<article class="approved">
<div class="boxed translate-rendered text-content">
<h2 id="参见">参见</h2>

<ul>
 <li>{{cssxref("--*", "Custom properties")}}</li>
</ul>
</div>
</article>