aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/css/specificity/index.html
blob: bf5ad8bb9a349a834683c3d75c504026b424465b (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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
---
title: 优先级
slug: Web/CSS/Specificity
tags:
  - CSS
  - Example
  - Guide
  - Reference
  - Web
  - 参考
  - 指南
  - 选择器
translation_of: Web/CSS/Specificity
---
<div>{{CSSRef}}</div>

<p>浏览器通过<strong>优先级</strong>来判断哪些属性值与一个元素最为相关,从而在该元素上应用这些属性值。优先级是基于不同种类<a href="/en/CSS/CSS_Reference#Selectors">选择器</a>组成的匹配规则。</p>

<h2 id="优先级是如何计算的?">优先级是如何计算的?</h2>

<p>优先级就是分配给指定的 CSS 声明的一个权重,它由 匹配的选择器中的 每一种选择器类型的 数值 决定。</p>

<p>而当优先级与多个 CSS 声明中任意一个声明的优先级相等的时候,CSS 中最后的那个声明将会被应用到元素上。</p>

<p>当同一个元素有多个声明的时候,优先级才会有意义。因为每一个直接作用于元素的 CSS 规则总是会接管/覆盖(take over)该元素从祖先元素继承而来的规则。</p>

<div class="note">注意: 文档树中元素的接近度(<a href="/zh-CN/docs/Web/CSS/Specificity#%E6%97%A0%E8%A7%86DOM%E6%A0%91%E4%B8%AD%E7%9A%84%E8%B7%9D%E7%A6%BB">Proximity of elements</a>)对优先级没有影响。</div>

<h3 id="选择器类型">选择器类型</h3>

<p>下面列表中,选择器类型的优先级是递增的:</p>

<ol>
 <li><a href="/en-US/docs/Web/CSS/Type_selectors">类型选择器</a>(例如,<code>h1</code>)和伪元素(例如,<code>::before</code></li>
 <li><a href="/en-US/docs/Web/CSS/Class_selectors">类选择器</a> (例如,<code>.example</code>),属性选择器(例如,<code>[type="radio"]</code>)和伪类(例如,<code>:hover</code></li>
 <li><a href="/en-US/docs/Web/CSS/ID_selectors">ID 选择器</a>(例如,<code>#example</code>)。</li>
</ol>

<p><strong>通配选择符</strong>(universal selector)({{CSSxRef("Universal_selectors", "*")}}<strong>关系选择符</strong>(combinators)({{CSSxRef("Adjacent_sibling_combinator", "+")}}, {{CSSxRef("Child_combinator", "&gt;")}}, {{CSSxRef("General_sibling_combinator", "~")}}, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_combinator" style="white-space: nowrap;">'<code> </code>'</a>, {{CSSxRef("Column_combinator", "||")}})和 <strong>否定伪类</strong>(negation pseudo-class)({{CSSxRef(":not", ":not()")}})对优先级没有影响。(但是,在<strong> </strong> <code>:not()</code> 内部声明的选择器会影响优先级)。</p>

<p>您可以访问 <a href="/zh-CN/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance#Specificity_2">"Specificity" in "Cascade and inheritance"</a>  或者 <a href="https://specifishity.com/">https://specifishity.com</a> 来了解更多关于优先级的详细信息。</p>

<p>给元素添加的<strong>内联样式</strong> (例如,<code>style="font-weight:bold"</code>) 总会覆盖外部样式表的任何样式 ,因此可看作是具有最高的优先级。</p>

<h3 id="!important_例外规则"><code>!important</code> 例外规则</h3>

<p>当在一个样式声明中使用一个 <code>!important</code> 规则时,此声明将覆盖任何其他声明。虽然,从技术上讲,<code>!important</code> 与优先级无关,但它与最终的结果直接相关。使用 <code>!important</code> 是一个<strong>坏习惯</strong>,应该尽量避免,因为这破坏了样式表中的固有的级联规则 使得调试找bug变得更加困难了。当两条相互冲突的带有 <code>!important</code> 规则的声明被应用到相同的元素上时,拥有更大优先级的声明将会被采用。</p>

<p><strong>一些经验法则:</strong></p>

<ul>
 <li><strong>一定</strong>要优先考虑使用样式规则的优先级来解决问题而不是 <code>!important</code></li>
 <li><strong>只有</strong>在需要覆盖全站或外部 CSS 的特定页面中使用 <code>!important</code></li>
 <li><strong>永远不要</strong>在你的插件中使用 <code>!important</code></li>
 <li><strong>永远不要</strong>在全站范围的 CSS 代码中使用 <code>!important</code></li>
</ul>

<ul style="margin-bottom: 1.286em; padding-left: 0px; list-style-type: none;">
 <li>
  <p><strong>与其使用 </strong> <strong><code>!important</code></strong><strong>,你可以:</strong></p>
 </li>
</ul>

<ol>
 <li>更好地利用 CSS 级联属性</li>
 <li>使用更具体的规则。在您选择的元素之前,增加一个或多个其他元素,使选择器变得更加具体,并获得更高的优先级。
  <pre class="brush: html notranslate">&lt;div id="test"&gt;
  &lt;span&gt;Text&lt;/span&gt;
&lt;/div&gt;</pre>

  <pre class="brush: css notranslate">div#test span { color: green; }
div span { color: blue; }
span { color: red; }</pre>

  <p>无论 c​ss 语句的顺序是什么样的,文本都会是绿色的(green),因为这一条规则是最有针对性、优先级最高的。(同理,无论语句顺序怎样,蓝色 blue 的规则都会覆盖红色 red 的规则)</p>
 </li>
 <li>对于(2)的一种特殊情况,当您无其他要指定的内容时,请复制简单的选择器以增加特异性。
  <pre class="brush: css notranslate">#myId#myId span { color: yellow; }
.myClass.myClass span { color: orange; }</pre>
 </li>
</ol>

<h4 id="什么的情况下可以使用_!important:">什么的情况下可以使用 <code>!important</code></h4>

<h5 id="A_覆盖内联样式">A) 覆盖内联样式</h5>

<p>你的网站上有一个设定了全站样式的 CSS 文件,同时你(或是你同事)写了一些很差的内联样式。</p>

<p>全局的CSS文件会在全局范围内设置网站的外观,而直接在各个元素上定义的内联样式可能会覆盖您的全局CSS文件。 内联样式和!important都被认为是非常不好的做法,但是有时你可以在CSS文件里用!important去覆盖内联样式。</p>

<p>在这种情况下,你就可以在你全局的 CSS 文件中写一些 <code>!important</code> 的样式来覆盖掉那些直接写在元素上的行内样式。</p>

<pre class="brush: html notranslate">&lt;div class="foo" style="color: red;"&gt;What color am I?&lt;/div&gt;
</pre>

<pre class="brush: css notranslate">.foo[style*="color: red"] {
  color: firebrick !important;
}
</pre>

<p>许多JavaScript框架和库都添加了内联样式。 有时候可以用<code>!important</code>与优先级高的选择器一起使用,以重写覆盖这些内联样式。</p>

<h5 id="B_覆盖优先级高的选择器">B) 覆盖优先级高的选择器</h5>

<pre class="brush: css notranslate">#someElement p {
  color: blue;
}

p.awesome {
  color: red;
}</pre>

<p>在外层有 <code>#someElement</code> 的情况下,你怎样能使 <code>awesome </code>的段落变成红色呢?这种情况下,如果不使用 <code>!important</code> ,第一条规则永远比第二条的优先级更高</p>

<h4 id="怎样覆盖_!important">怎样覆盖 <code>!important</code></h4>

<p>A)很简单,只需再添加一条 带 <code>!important</code> 的CSS规则,再给这个给选择器更高的优先级(添加一个标签,ID或类);或是添加一样选择器,把它的位置放在原有声明的后面(总之,最后定义一条规则比胜)。</p>

<p>一些拥有更高优先级的例子:</p>

<pre class="brush: css notranslate">   table td { height: 50px !important; }
.myTable td { height: 50px !important; }
#myTable td { height: 50px !important; }
</pre>

<p>B)或者使用相同的选择器,但是置于已有的样式之后:</p>

<pre class="brush: css notranslate">td { height: 50px !important; }</pre>

<p>C)或干脆改写原来的规则,以避免使用 <code>!important</code></p>

<pre class="brush: css notranslate">[id="someElement"] p {
  color: blue;
}

p.awesome {
  color: red;
}</pre>

<p>将id作为属性选择器的一部分而不是id选择器,将使其具有与类相同的特异性。 上面的两个选择器现在具有相同的权重。 在优先级相同情况下,后面定义的CSS样式会被应用。</p>

<h4 id="若想了解更多信息,请参考:">若想了解更多信息,请参考:</h4>

<ul>
 <li><a href="https://stackoverflow.com/questions/3706819/what-are-the-implications-of-using-important-in-css">https://stackoverflow.com/questions/3706819/what-are-the-implications-of-using-important-in-css</a></li>
 <li><a href="https://stackoverflow.com/questions/9245353/what-does-important-in-css-mean">https://stackoverflow.com/questions/9245353/what-does-important-in-css-mean</a></li>
 <li><a href="https://stackoverflow.com/questions/5701149/when-to-use-important-property-in-css">https://stackoverflow.com/questions/5701149/when-to-use-important-property-in-css</a></li>
 <li><a href="https://stackoverflow.com/questions/11178673/how-to-override-important">https://stackoverflow.com/questions/11178673/how-to-override-important</a></li>
 <li><a href="https://stackoverflow.com/questions/2042497/when-to-use-important-to-save-the-day-when-working-with-css">https://stackoverflow.com/questions/2042497/when-to-use-important-to-save-the-day-when-working-with-css</a></li>
</ul>

<h3 id="is_和_not_例外规则"><span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-string"><code>:is()</code> 和 <code>:not()</code> 例外规则</span></span></span></span></h3>

<p>The matches-any pseudo-class {{CSSxRef(":is", ":is()")}} {{Experimental_Inline}} and the negation pseudo-class {{CSSxRef(":not", ":not()")}} are <em>not</em> considered a pseudo-class in the specificity calculation. But selectors placed into the pseudo-class count as normal selectors when determining the count of <a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/Specificity$edit#Selector_Types">selector types</a>.</p>

<p><code>:not</code> 否定伪类在优先级计算中不会被看作是伪类。事实上,在计算选择器数量时还是会把其中的选择器当做普通选择器进行计数。</p>

<div id="The_not_exception-example">
<p>有如下 CSS 样式声明:</p>

<pre class="brush: css notranslate">div.outer p {
  color: orange;
}

div:not(.outer) p {
  color: blueviolet;
}
</pre>

<p>将其应用于以下的 HTML 时:</p>

<pre class="brush: html notranslate">&lt;div class="outer"&gt;
  &lt;p&gt;This is in the outer div.&lt;/p&gt;
  &lt;div class="inner"&gt;
    &lt;p&gt;This text is in the inner div.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;
</pre>

<p>会在屏幕上出现以下结果:</p>

<p>{{EmbedLiveSample("The_not_exception-example")}}</p>
</div>

<h3 id="The_where_exception" name="The_where_exception"><code>:where()</code> <span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-string">例外规则</span></span></span></span> {{Experimental_Inline}}</h3>

<p>{{SeeCompatTable}}</p>

<p>The specificity-adjustment pseudo-class {{CSSxRef(":where", ":where()")}} {{Experimental_Inline}} always has its specificity replaced with zero.</p>

<p>有如下 CSS 样式声明:</p>

<pre class="brush: css notranslate">div:where(.outer) p {
  color: orange;
}

div p {
  color: blueviolet;
}
</pre>

<div class="hidden">
<pre class="brush: css; notranslate">#no-where-support {
  margin: 0.5em;
  border: 1px solid red;
}

#no-where-support:where(*) {
  display: none !important;
}
</pre>
</div>

<p>将其应用于以下的 HTML 时:</p>

<div class="hidden">
<pre class="brush: html; notranslate">&lt;div id=no-where-support&gt;
⚠️ Your browser doesn't support the &lt;code&gt;&lt;a href="https://developer.mozilla.org/docs/Web/CSS/:where"&gt;:where()&lt;/a&gt;&lt;/code&gt; pseudo-class.
&lt;/div&gt;
</pre>
</div>

<pre class="brush: html notranslate">&lt;div class="outer"&gt;
  &lt;p&gt;This is in the outer div.&lt;/p&gt;
  &lt;div class="inner"&gt;
    &lt;p&gt;This text is in the inner div.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;
</pre>

<p>会在屏幕上出现以下结果:</p>

<p>{{EmbedLiveSample("The_where_exception")}}</p>

<h3 id="基于形式的优先级(Form-based_specificity)">基于形式的优先级(Form-based specificity)</h3>

<p>优先级是基于选择器的形式进行计算的。在下面的例子中,尽管选择器*[id="foo"] 选择了一个ID,但是它还是作为一个<strong>属性选择器</strong>来计算自身的优先级。</p>

<p>有如下样式声明:</p>

<pre class="brush: css notranslate">*#foo {
  color: green;
}

*[id="foo"] {
  color: purple;
}
</pre>

<p>将其应用在下面的HTML中:</p>

<pre class="brush: html notranslate">&lt;p id="foo"&gt;I am a sample text.&lt;/p&gt;
</pre>

<p>最终会出现下面的效果:</p>

<p>{{EmbedLiveSample("基于形式的优先级(Form-based_specificity)")}}</p>

<p>虽然匹配了相同的元素,但是 <strong>ID 选择器</strong>拥有更高的优先级。所以第一条样式声明生效。</p>

<h3 id="无视DOM树中的距离">无视DOM树中的距离</h3>

<p>有如下样式声明:</p>

<pre class="brush: css notranslate">body h1 {
  color: green;
}

html h1 {
  color: purple;
}
</pre>

<p>当它应用在下面的 HTML 时:</p>

<pre class="brush: html notranslate">&lt;html&gt;
  &lt;body&gt;
    &lt;h1&gt;Here is a title!&lt;/h1&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>

<p>浏览器会将它渲染成:</p>

<p>{{EmbedLiveSample("无视DOM树中的距离")}}</p>

<h3 id="直接添加样式_vs._继承样式">直接添加样式 vs. 继承样式</h3>

<p>为目标元素直接添加样式,永远比继承样式的优先级高,无视优先级的遗传规则。</p>

<pre class="brush: css notranslate">#parent {
  color: green;
}

h1 {
  color: purple;
}</pre>

<p>当它应用在下面的HTML时:</p>

<pre class="brush: html notranslate">&lt;html&gt;
  &lt;body id="parent"&gt;
    &lt;h1&gt;Here is a title!&lt;/h1&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>

<p>浏览器会将它渲染成:</p>

<p>{{EmbedLiveSample("直接给目标元素添加样式和目标元素继承样式对比")}}</p>

<p>因为 <code>h1</code> 选择器明确的定位到了元素,但绿色选择器的仅仅继承自其父级。</p>

<h2 id="规范">规范</h2>

<div style="overflow: auto;">
<table class="standard-table">
 <thead>
  <tr>
   <th scope="col">规范</th>
   <th scope="col">状态</th>
   <th scope="col">备注</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName("CSS4 Selectors", "#specificity-rules", "Calculating a selector's specificity")}}</td>
   <td>{{Spec2("CSS4 Selectors")}}</td>
   <td>Add the specificity adjustment selector {{CSSxRef(":where", ":where()")}}.</td>
  </tr>
  <tr>
   <td>{{SpecName("CSS3 Selectors", "#specificity", "Calculating a selector's specificity")}}</td>
   <td>{{Spec2("CSS3 Selectors")}}</td>
   <td>添加伪元素 <a href="/en-US/docs/Web/CSS/Pseudo-elements">pseudo-elements</a>.</td>
  </tr>
  <tr>
   <td>{{SpecName("CSS2.1", "cascade.html#specificity", "Calculating a selector's specificity")}}</td>
   <td>{{Spec2("CSS2.1")}}</td>
   <td>添加伪类 <a href="/en-US/docs/Web/CSS/Pseudo-classes">pseudo-classes</a>.</td>
  </tr>
  <tr>
   <td>{{SpecName("CSS1", "#cascading-order", "Cascading order")}}</td>
   <td>{{Spec2("CSS1")}}</td>
   <td>初始化定义.</td>
  </tr>
 </tbody>
</table>
</div>

<h2 id="参见">参见</h2>

<ul>
 <li>Specificity Calculator: An interactive website to test and understand your own CSS rules - <a href="https://specificity.keegan.st/">https://specificity.keegan.st/</a></li>
 <li>CSS3 选择器优先级 - <a class="external" href="http://www.w3.org/TR/selectors/#specificity" rel="freelink">http://www.w3.org/TR/selectors/#specificity</a></li>
 <li>{{CSS_Key_Concepts}}</li>
</ul>