以下是来自 HubSpot 的 Francisco Dias 的客座文章。我在今年的 CSS Dev Conf 上看到 Francisco 和 Cris Necochea 以快速有趣的演示形式展示了这一点。 展示与讲述。他欣然同意为一篇博文准备它!
19种覆盖背景色的方法
从几乎最低特异性选择器开始
div {
background: black;
}
有很多方法可以提升现有特异性,而无需重复相同的技巧。
点击每个步骤,查看间谍如何将其颜色(黑色或白色)强制覆盖在之前的颜色之上。当特异性提升停止时,他们袖子里还有更多技巧!
(间谍形状是通过演示中div
上的clip-path
创建的,使其更有趣且更像间谍大战。如果您当前使用的浏览器不支持clip-path
,您将只会看到白色或黑色方块。)
查看 CodePen 上 Francisco Dias 的作品 间谍大战 (@FranDias)。
这里到底发生了什么?上面演示 CodePen 中的文本包含有关每个步骤的更多信息,但作为快速概述,以下是各个阶段
步骤 1:元素选择器
0, 0, 0, 1
div {
background: black;
}
步骤 2:两个元素选择器
0, 0, 0, 2
body div {
background: white;
}
步骤 3:三个元素选择器
0, 0, 0, 3
html body div {
background: black;
}
步骤 4:类选择器
0, 0, 1, 0
.spy {
background: white;
}
步骤 5:类 + 元素选择器
0, 0, 1, 1
div.spy {
background: black;
}
步骤 6:元素 + 类 + 伪类选择器
0, 0, 2, 1
div.spy:only-of-type {
background: white;
}
步骤 7:堆叠类
0, 0, ∞, 0
.spy.spy.spy.spy.spy.spy.spy.spy.spy {
background: black;
}
步骤 8:ID 选择器
0, 1, 0, 0
#spy {
background: white;
}
步骤 9:ID + 属性选择器
0, 1, 1, 0
#spy[class^="s"] {
background: black;
}
步骤 10:组合以上多种方法…
0, 1, 3, 3
html body div#spy[class="spy"]:first-of-type.spy {
background: white;
}
步骤 11:内联样式
1, 0, 0, 0
<div class="spy" id="spy" style="background: black;"></div>
步骤 12:!important
有点像每个属性的 [1, 0, 0, 0](可以覆盖内联样式)。
div {
background: white !important;
}
步骤 13:在内联样式中使用 !important
有点像每个属性的 [∞, 0, 0, 0],任何 CSS 都无法覆盖。
<div class="spy" id="spy" style="background: black !important;"></div>
步骤 14:box-shadow 技巧
某些属性会绘制在其他属性之上。box-shadow
绘制在背景之上。
div {
box-shadow: inset 0 9001rem 0 white;
}
步骤 15:反转滤镜
div {
-webkit-filter: invert(1);
filter: invert(1);
}
我很幸运地在那个展示和讲述中现场看到了这个。很酷的演示。干得好,伙计们
再次感谢,感谢您在演示期间和现在给予的鼓励。
现在我脑海里挥之不去的是歌曲“50 Ways to Leave Your Lover”……
我们需要一些类似于 !superimportant 的东西,它可以简单地覆盖所有糟糕的 CSS(到处都是 !important,今天我看到 !important 用在选择器 'a img' 上,它破坏了我的整个 Joomla 门户网站)来自由初级开发人员编写的第三方组件。是啊,为什么不呢!
我认为那不会很好 :)
问题是,一旦那些初级开发人员了解了这个新的特异性,我们就需要添加
!superduperimportant
:)我同意 Brad 和 Jeffrey 的观点——
我们需要的是更好地了解如何负责任地封装您的功能。Jeffery Sweeny 说得很好,如果我们有比
!important
更极端的东西,他们可能会使用它。在某些情况下,带有刻意指定的选取器或仅具有一个功能的实用程序类(例如
.uppercase { text-transform: uppercase;}
)的!important
修饰符可能很有用,甚至可以帮助扩展项目。不幸的是,!important
似乎更多地是出于沮丧而不是作为一种有意识的工具而使用的。我认为更有效的方法是忽略 !important 并恢复到标准的特异性。这样,与其发起咄咄逼人的开发者对更高王牌的军备竞赛,不如让真正理解 CSS 的人能够理清其他人留下的混乱。
所以我们有我们理解的特异性,因此 'div > p' 比 'p' 高并获胜。让我们简化并将其设为 !1、!2、!3、!4……直到无穷大?100?更简单 ;) 如果你看到一个初级开发者使用 !100,那就是纯粹的邪恶 :D
一半开玩笑,一半认真,是啊,为什么不呢——讨论一下。
附注:无论如何,我认为最好学习特异性,而不是在单个 CSS 规则的末尾添加更多内容。
好吧,从一开始,CSS 的设计就是为了拥有覆盖服务器发送的作者 CSS 的单个本地用户 CSS(但每个人都讨厌它并假装它不存在),因此可以想象在跨站点 CSS 和自己的站点 CSS 之间进行区分。(不过这在这里没有帮助,因为 !important 已经胜过了用户 CSS。)
必须同意其他评论。此外,您可能需要重新考虑是否完全使用此扩展(当然,开发人员可能精通 PHP/JS,只是不熟悉 CSS……)。
!unimportant 将很棒
示例
抱歉……示例中的错别字,应该是 !unimportant
哎呀!
!important
规则应该更多地被视为调试工具。就像调试消息一样,它不应在生产代码中使用。我们最不需要的就是另一层特异性,例如!superimportant。我们现在拥有的那个已经导致了太多问题。我甚至赞成在我们的代码中添加一个标志/规则/指令/断言,它可以禁用它。
“他们有原子弹,所以我们制造了氢弹”并不是最好的软件架构策略。;)
这必须是我见过的最具创意和信息量的 CSS 特异性演示。我看到了很多以前从未见过或想过的方法,但与此同时,我怀疑还有数十种方法被省略了。
哇,谢谢你的评论,这是一个巨大的赞美。源代码中还有两个技巧被注释掉了,因为它们不适用于
clip-path
,你还可以链接 ID#spy#spy#spy
。除此之外,我不想深入讨论动画中的!important
或使用细微差别更大的选择器以避免显得过于刻板。再次感谢!对我来说,第 19 步没有显示。我只看到粉红色的主体。不过,这仍然是一个很棒的演示。我使用的是 Chrome 版本 48.0.2564.71 beta-m (64 位)。
我处理特异性问题的最喜欢的技巧
感谢您的错误报告和赞美。我会看看我能做什么。
我原本期待在这里看到内联样式覆盖技巧,但由于我没有看到;所以在这里。假设您有一个应用了内联样式的 div(可能是由 JavaScript 应用的),那么您可以执行以下操作以从内部/外部 CSS 覆盖内联样式。
您只是使用
!important
规则来覆盖内联 CSS,就像我们在步骤 12 中看到的那样。我认为需要注意的是,通过修改style 属性使用 Javascript 更改元素的外观与内联样式不同。它只是具有相同特异性。
不过这里有一些有趣的事情。我预计您的 CSS 仅针对 HTML 中实际设置了
style
属性的元素,但我错了。显然,它还针对使用 Javascript 在 DOM 中设置了 style 属性的元素。http://codepen.io/Ghodmode/pen/GoExqW
最低的是 *。
通用选择器不具有任何特异性(!important 也不具有)。
你说得对(除非你算上浏览器默认样式)。它没有被包含在内,因为我无法将其裸露地放置。感谢您的评论。
并且感谢这篇文章——从第 14 步开始的技巧很有趣(即使很hacky)。
这是关于背景颜色,但是如果您试图更改文本颜色,我见过的最棘手的野兽之一是 -webkit-text-fill-color。真的,那个曾经让我发疯,当时整整一个小时我都无法理解为什么即使 !important 也不起作用……