让我们专门讨论这个主题。(敲击声!)
解释它的最佳方式是从特定性变得混乱且可能不像预期那样运行的示例开始。然后我们将仔细研究如何计算实际的特定性值以确定哪个选择器具有优先权。
这是一个简单的无序列表
<ul id="summer-drinks">
<li>Whiskey and Ginger Ale</li>
<li>Wheat Beer</li>
<li>Mint Julip</li>
</ul>
现在您想指定其中一种为您的最爱饮料并更改其样式。您需要一个挂钩来执行此操作,因此您通过列表元素上的类名来应用它。
<ul id="summer-drinks">
<li class="favorite">Whiskey and Ginger Ale</li>
<li>Wheat Beer</li>
<li>Mint Julip</li>
</ul>
现在您打开 CSS 并对新类进行样式化
.favorite {
color: red;
font-weight: bold;
}
然后您查看自己的作品,但是,它没有起作用! 您最喜欢的饮料的文本没有变成红色或变粗! 这里有些奇怪的事情在发生。
在 CSS 中进一步探查,您会发现这一点
ul#summer-drinks li {
font-weight: normal;
font-size: 12px;
color: black;
}
这就是您的问题所在。两个不同的 CSS 选择器告诉该文本的颜色和字体粗细。只有一个字体大小语句,因此很明显,该语句将生效。这些不一定是“冲突”,但浏览器确实需要决定这些语句中的哪一个应该被认可。它是通过遵循一组标准的特定性规则来实现的。
我认为这会让一些初学者感到困惑,因为他们还没有完全弄清楚这一点。他们可能会认为,因为 .favorite 语句“在 CSS 中更靠下”,或者因为类=”favorite”在 HTML 中“更靠近实际文本”,它将是“获胜者”。
事实上,CSS 中选择器的顺序确实起作用,“更靠下”的选择器在特定性值完全相同的情况下确实会获胜。例如
.favorite {
color: red;
}
.favorite {
color: black;
}
颜色将是黑色…… 但我扯远了。
这里的重点是,您应该尽可能地使用特定性。即使使用上面提供的简单示例,您最终也会明白,仅仅使用类名来定位该“最爱饮料”是不够的,或者即使它起作用,也不安全。使用以下方法会更明智
ul#summer-drinks li.favorite {
color: red;
font-weight: bold;
}
这就是我所说的“尽可能地使用特定性”。您实际上可以更具体,并使用以下方法
html body div#pagewrap ul#summer-drinks li.favorite {
color: red;
font-weight: bold;
}
但这有点过分。它会使您的 CSS 难以阅读,而且没有实际的好处。另一种增强“.favorite”类的特定性值的方法是使用!important 声明。
.favorite {
color: red !important;
font-weight: bold !important;
}
我曾经听说,!important 就像 CSS 中的绝地心灵控制术。确实如此,您可以通过使用它来强制您的意志覆盖元素的样式。但!important 通过大幅提高特定选择器属性的特定性来施加这种意志。
如果误解了!important 声明,很容易被误用。最好使用它来保持 CSS 的整洁,在您知道具有特定类选择器的元素应该使用特定样式集无论如何的示例中。反之,不要将其用作快速解决方法来覆盖某些东西的样式,而是要弄清楚原始作者是如何构建和使用 CSS 的。
我经常使用的经典示例之一是
.last {
margin-right: 0 !important;
}
我经常在有多个浮动块的情况下使用它,用于一行中的最后一个右侧块。这确保最后一个块没有任何右外边距,这会阻止它紧贴其父元素的右侧边缘。这些块中的每一个可能都有更具体的 CSS 选择器来应用右外边距,但!important 会突破这一点,并通过一个简单/干净的类来处理它。
计算 CSS 特定性值
为什么我们第一次尝试更改颜色和字体粗细失败了?正如我们所知,这是因为仅仅使用类名本身具有较低的特定性值,并且被另一个选择器(它针对具有 ID 值的无序列表)所取代。这句话中重要的词是类和ID。CSS 对类和 ID 应用了截然不同的特定性权重。事实上,ID 的特定性值无限高! 也就是说,没有任何数量的类本身可以超过 ID。
让我们来看看这些数字是如何计算的
换句话说
- 如果元素具有内联样式,则该样式将自动1 获胜(1,0,0,0 分)
- 对于每个 ID 值,应用 0,1,0,0 分
- 对于每个类值(或伪类或属性选择器),应用 0,0,1,0 分
- 对于每个元素引用,应用 0,0,0,1 分
您通常可以将这些值视为一个数字,例如 1,0,0,0 是“1000”,因此显然胜过 0,1,0,0 或“100”的特定性。逗号是为了提醒我们这并不是一个真正的“十进制”系统,因为您实际上可以有像 0,1,13,4 这样的特定性值——而且这个“13”不会像十进制系统那样溢出。
示例计算
更新::not() 类伪类本身不添加任何特定性,只有括号内的内容会添加到特定性值。
重要说明
- 通配符选择器 (*) 没有特定性值 (0,0,0,0)
- 伪元素 (例如 :first-line) 获得 0,0,0,1,不像它们的伪类兄弟获得 0,0,1,0
- 伪类 :not() 本身不添加任何特定性,只有它括号内的内容会添加特定性。
- 附加到 CSS 属性值的!important 值是自动获胜。它甚至会覆盖标记中的内联样式。唯一可以覆盖!important 值的方法是在 CSS 中稍后声明的另一个!important 规则,且具有相同或更大的特定性值,否则就会被覆盖。您可以将其视为在特定性值中添加 1,0,0,0,0。
资源
- Smashing Magazine 有一篇关于 CSS 特定性的非常全面的文章
- W3 关于 CSS3 中特定性的规范
- IE 怪癖(尝试在 Fx 中查看此页面,然后查看 IE)
- 模糊特定性技巧:IE(甚至 beta 8!)和旧版 Opera 浏览器存在一个错误,在特定情况下会认可正确的选择器。
您好!
感谢这篇文章! 我最近养成了使用非常具体的样式的习惯。另外,我喜欢您在查看一些屏幕截图后如何布局 CSS 文件! 这很有帮助,现在我的 CSS 文件更容易阅读。
继续努力!
ChaZ
我是一个文章中提到的“困惑的初学者”。:) 这很有帮助。这肯定会收藏起来并经常参考。
谢谢……
我还建议您查看并测试CSS 特定性计算器。只需粘贴您的 CSS,它就会为您计算特定性。如果您正在处理大型 CSS 文件(而不是多个较小的文件),它真的很方便。
这使得特定性更容易理解。仔细想想,这将成为一个不错的 CSS 编辑器插件!
很棒的解释,我喜欢视觉效果。
感谢这篇文章。我会在意计算,而不是代码的顺序:)
我一直理解特定性,但我从未见过计算方法,非常巧妙。
很棒的解释。积分系统的类比使其真正易于理解。谢谢
感谢您发布这篇精彩且实用的文章! 这是一个有趣的方法。
firebug 可以帮助您省去“在 CSS 中搜索”的麻烦,因为它会很好地显示应用于您选择的任何元素的选择器。
写得很好。
谢谢您。
我很少遇到这些麻烦,但遇到时,我想到的第一件事就是 firebug。
但这里对我来说新奇的是“计算 CSS 特定性值”,我在一些书中读过它,但没有理解。现在它变得如此简单易记。
再次感谢。
干杯
我习惯于在需要的时候查看 Firebug 工具栏,但你的图片确实说明了问题。不错!
哇,我真的认为这篇文章对很多人来说都是一个“顿悟时刻”。插图也很好。
来自德国的问候
只是为了澄清,特异性计算器并不完全准确。例如,如果你有一个元素应用了 11 个类,它不会超过一个带有单个 ID 选择器的元素。
例如,
.a .b .c .d .e .f .g .h .i .j a.k { color:red; }
#myel {color:blue;}
<span class=”a b c d e f g h i j k” id=”myel”>仍然是蓝色。</span>
这种情况发生的可能性很小,但需要注意。
对于那些设计中棘手的 CSS 表格来说,很棒的内容。谢谢
只是为了补充乔纳森·斯努克的评论
计算不是基于值的“加法”。特异性计算是基于最左边的值是最高的。如果两个竞争选择器在给定的识别单元上具有匹配的值,则比较将继续向左移动到下一个顺序,直到找到更大的值。
我在关于 CSS 特异性 的文章中用图表突出了这一点。
我一直想知道在 CSS 中是否可以创建颜色快捷方式。
目前在我的网站中,如果我需要更改字体颜色代码,我需要检查所有应用了该颜色的类。
但是,如果我有“myCustomYellowColor”这样的“快捷方式”名称,它将具有自定义颜色代码,我将能够在一行中立即更改它。
我从未尝试过,但它应该可以满足你的要求:LESS
帕布罗,你不能在 CSS 中创建常量或变量,但我自己也渴望过。我发现最好的方法是将常用的颜色放在一个地方。例如
如果你想要更复杂的东西,另一个选择是肖恩·因曼的 CSS Cacheer。
帕布罗 - CSS 变量正在到来。它们在 Webkit(Safari)的最新版本中可用,但还需要一段时间才会成为主流。
如果你将你的样式分成排版和结构/布局,它可以更容易更改 - 但是,根据你的样式表的大小,它可能会使查找变得更加困难 - 例如。如果你正在查找特定元素/选择器的所有样式,你需要引用多个位置,而不是仅引用组合的排版/结构位置。
乔纳森 完全正确,这篇文章在这方面极具误导性。特异性并非以十进制为基础。它不是以任何熟悉的东西为基础:实际上,特异性值具有一个无限基数。真的。因此你不会“将点加在一起”,至少不会以任何阅读这篇文章的人可能认为的方式。
这就是为什么在编写特异性值时,首选使用分隔的表示法(逗号最常见)。参见 http://meyerweb.com/eric/css/link-specificity.html 获取示例,或参见 CSS2.1 规范本身。
安迪·克拉克的 特异性战争 文章,来自几年前,是我理解特异性的方式。
无论你拥有多少冲锋队员,他们都无法战胜达斯·维达!
我以为我对特异性很精通,但我从未知道不同的选择器类型实际上有数字值分配给它们,很棒的文章!
很棒的文章,插图真的帮助像我这样视觉型的人理解整个概念。谢谢。
感谢克里斯的精彩文章。我也喜欢你的视觉解释 - 顺便问一下,你在文章中使用什么软件来创建视觉元素?
哇,埃里克·迈耶有点刻薄... 不像斯努克那样温和和建设性。
我 - 首先 - 爱上了你的十进制近似值,它巧妙地适合直观的图形示例。我经常向同事解释特异性,但我的话从未像今天早上那样清晰,当时我带着你的文章的打印副本和那些可爱的十进制分数气泡。非常棒的工作!
但是... 感觉好像缺少了一些重要的东西。;-)
明确性始终有助于理解代码并确保对元素的控制。
谢谢,这是一个很好的提醒!
很棒的文章!
我建议你创建一个可打印的备忘单。那将会很有用!
关于 CSS 特异性的精彩文章!甚至不需要解释,图片就足够了。但是克里斯,鉴于埃里克·迈耶的修正,你为什么不修复你的图片呢?**移除加号并添加逗号。**
我认为 :first-letter 是一个伪元素,价值 1 分,而不是一个伪类,价值 10 分。有人可以确认一下吗?
没错,亚历克斯。此外,出于一些晦涩的技术原因,伪元素在 CSS2 的特异性计算中被忽略 (http://www.w3.org/TR/CSS2/cascade.html#specificity),但在 CSS2.1 中获得 1 分 (http://www.w3.org/TR/CSS21/cascade.html#specificity)。哪个发生取决于你的浏览器实施了哪套规则,当然。
我很高兴你更新了这篇文章。我不断看到关于 CSS 特异性的文章(Smashing Mag、NetTuts,甚至 Malarky)在计算特异性值时出错。
感谢你更新,我认为保持信息尽可能最新和准确非常重要,因为仍然有人在搜索这些答案。
臃肿会带来危险。小心那些类和 id!在编写代码之前尝试计划你的网站!
我一直很喜欢安迪·克拉克的星球大战人物图解,用来解释这一点。
我同意斯科特·科根。
我尽量少使用类和 id。如果我必须使用它们,我会用非常通用的名称来命名它们,以便它们可以通用地使用。
另一个经验法则是,如果我的 CSS 在实际元素之前有 1 个以上类或 id,那么我可能做错了什么。
使用图形来阐述你的观点,很棒。
嗨,克里斯!很棒的文章。我想知道你是否可以最终在一个整洁的帖子/页面中发布你所有自定义的 CSS-Tricks 类。例如,你在本篇文章中提到了你的 .last {} 类技巧,你在处理边框/浮动问题时创建的。我认为将这些项目放在 CSS 重置文件中会很有用,你可以反复使用它们。
布局很好。谢谢!
我想到的是,!important 规则应该在作者样式表中避免,因为它们也会覆盖用户样式表中的声明。用户样式表应该被视为更重要(如果用户有一个特殊的样式表,那么肯定有其理由)。使用 !important 会让在样式表中进一步覆盖这个声明变得更加困难。
正如我所说,你的问题有很多解决方案。如果一个样式对整个列表很重要,最好将样式应用到列表本身,而不是列表项。如果你将颜色应用到 ul#summer-drinks,那么在 .favorite 上应用不同的颜色就不会有任何问题。你可以通过利用继承来避免大多数特异性问题。
我知道这篇文章已经很旧了,但我想添加一些有用的信息,以防将来有人看到这个评论。
http://www.w3.org/TR/CSS2/cascade.html
6.4.2 !important 规则
您好,我想介绍一种简单的方法来避免您上面示例中的
.last margin-right: 0 !important
技巧。如果您能阅读巴西葡萄牙语,那就太好了,如果不能,请使用一些在线翻译器(我使用 Google 翻译器为您翻译了,只需点击这里 http://bit.ly/baZpJ6)并查看我的这篇文章 http://edsonjunior.com/lista-de-itens-horizontal/
顺便说一句,好文章。添加到我的 Delicious 中吧!:)
一个很好的提醒是,避免比你需要的更具体,有时这可以帮助提高性能,并且也使维护/重复使用更容易。您不需要 “ul#summer-drinks” 上的 “ul”,因为每个页面只能有一个 ID.. 拥有更少的和 更有效的选择器 可以使您的页面渲染更快。
另一件事是始终将元素(例如 “p、a、h1”)和通用类(例如 “last”)放在其他规则之前,这样更容易理解哪些会被覆盖..
做得好,伙计!真的很好看 *g*
这是我最喜欢的关于 CSS 特定性的文章之一。我从来没有真正理解这是什么,即使我上过学。我遇到的老师也没有很好地解释它。令人惊讶的是,CSS 确实如此强大。我甚至不知道任何关于 CSS5 的知识,所以我有很长的路要走。
计算方法很有趣。很多时候我最终会使用 “!important” 而不是尝试找出问题所在。
感谢您更新这篇文章。如今在网络上,我只能找到过时的、不正确的信息。您是网络上少数几个好网站之一。
特定性是 CSS 最令人困惑的方面之一。您的文章是我所见过的解释得最好的文章,做得非常好。
我担心人们会找到这篇文章。几年前我第一次遇到这个问题时,我不知道它被称为 “特定性”。我只是在试图找出为什么附加到 ID 的样式会覆盖在 ID 元素中包含的元素上定义的类样式!
了解人们在尝试解决这个问题时搜索了什么,然后确保文章对这些搜索做出反应,将会非常有趣。
我不喜欢使用通用选择器 *,有时我会失去对它的控制,也许其他设计师无法理解我的 CSS 代码。
感谢这篇文章!
您提醒我,通用选择器没有特定性 :)
当我想与其他开发人员分享特定性时,我也会使用 不同的系统。
我发现您关于特定性的 “!important” 解释有点令人困惑。例如
“Foo” 文本在 “a” 中的颜色将是绿色,但大多数人可能认为它是红色。
!important
应用于它所分配的元素,而不是子元素。我认为在这种情况下<a>
被认为是<p>
的子元素。父元素内的任何文本都将是红色,无论对通用p
选择器应用了哪些样式;但是<a>
将保留其指定的样式。使用来自 Initializr.com 的 Bootstrap 模板,有一个内置样式,其特定性似乎是 0,0,1,0
我想给它加上圆角和边框(没问题),并给列之间留一些空间,这样边框就不会接触。我创建了这段代码,对我来说,它似乎有 0,0,2,0 的特定性
根据 Firebug,两个选择器都被考虑了,但非-.rounded 的选择器输给了普通的选择器。因此,我尝试创建相反的,对我来说,它似乎也有 0,0,2,0 的特定性
果然,它胜过了普通的选择器,显然是因为它具有更高的特定性。
我还尝试改变选择器的顺序,内联还是包含,以及类的列出顺序 (.rounded.col-lg-4),但没有区别。我在 Chrome 中进行了测试。
所以让我好奇的是,为什么同一个元素上的两个类以及同时定位这两个类的选择器,没有比只定位一个类的选择器更高的特定性?或者我的计算可能错了?
我找到了问题所在。上面有一个 @media 选择器覆盖了我试图覆盖的样式。因此,我认为这意味着 @media 具有非常高的值,虽然我不确定它将位于此层次结构中的哪个位置。也许可以将这些信息添加到这篇文章中?