嵌套 CSS 选择器而不增加特异性
Posted
技术标签:
【中文标题】嵌套 CSS 选择器而不增加特异性【英文标题】:Nesting CSS selectors without increasing specificity 【发布时间】:2016-03-29 19:19:35 【问题描述】:让我们来看看这三个选择器,从高到低排序:
.special-section p
.weird-font
p
许多 CSS 专家建议不要像在第一个选择器 .special-section p
中那样进行嵌套,因为它的特异性足够高,以至于您无法使用像 .weird-font
这样的简单类来覆盖它。我想找到一种方法来仍然像.special-section p
那样实现嵌套,但不增加特异性。像这样的:
.weird-font
.special-section p /* with hack to decrease specificity */
p
用例:
使用像p
这样的简单选择器为排版和文档范围应用默认值是非常安全的。但是,我想更改特定部分的这些默认值,类似于.special-section p
,而不必使用黑客来增加选择器的特异性,例如.weird-font
。我宁愿使用 hack 来降低 .special-section p
的特异性,也不愿使用 hack 来增加 .weird-font
的特异性。有没有办法做到这一点?
【问题讨论】:
!important
的问题是只有一层覆盖。如果你制作了一个更具体的选择器,你可以用一个更具体的选择器再次覆盖它。使用!important
后,你别无选择。
添加类然后由它们选择不是一个技巧;这是选择元素的定义方式。如果您有一些示例标记,则用例可能会更清楚。
@TylerH:这不是 OP 所指的。您真的不需要示例标记来推断在示例 CSS 中,p 和 .weird-font 指的是同一个元素。
@BoltClock 我不同意;我完全不清楚 OP 的标记会是什么样子。即使通过巨大的努力,我们可以做出一个假设(所有答案都是如此),但通过一个简单的标记示例,它会变得更清晰、更容易理解(因此对其他人有帮助)。此外,如果我们知道标记,我们可以提供一种潜在的替代方法来实现 OP 的目标。例如,接受的答案与 OP 想要的完全相反(它在他想要避免增加特异性的地方增加了特异性)。
@TylerH:我不否认总有改进的余地,但考虑到 only 的情况,做出这样的假设并不需要“很大的努力”当两个选择器都引用同一个元素时,甚至适用于特殊性。接受的答案和我自己的建议都建议增加而不是减少它,因为你 can't 减少它,并且对于 OP 的问题没有任何其他解决方案不依赖于标记(而且,显然,OP 对这样的解决方案也不是很感兴趣,这也是 fine)。
【参考方案1】:
您不能降低特异性,但可以为异常添加更具体的选择器。
.weird-font, /* Normal weird font */
.special-section p.weird-font /* Override for special section */
但正如您所见,它是一个滑动比例。所以那些大师可能是对的。如果您要删除.special-section p
,而是给这些P 自己的选择器.special-section-para
或其他东西,那么您就不会有这个问题。
但就个人而言,我不介意时不时地添加一个像上面那样的例外。我认为整个特殊性都是为了这个目的,如果你需要一个更具体的选择器来设置样式,对我来说这似乎是正确的做法。
一个常见的解决方案是使用!important
。 !important 的问题在于只有一层覆盖。如果你制作了一个更具体的选择器,你可以用一个更具体的选择器再次覆盖它。使用 !important 后,您将别无选择。更重要的是,使用!important
可能会干扰用户为了提高可读性而可能拥有的特殊样式表。出于这个原因,我从不在这种情况下使用!important
。
但话又说回来,我不认为自己是 CSS 大师。 ;)
【讨论】:
【参考方案2】:作为一名 CSS 专家,我很遗憾放弃选择器必须提供的所有内容,以避免出现特殊性问题。这并不是说我不相信特异性机制有缺陷,但肯定有不那么引人注目的解决方法。
首先:不,您不能降低选择器的特异性。选择器不提供任何具有负特异性水平的特征,这些特征会以这种方式降低特异性。您可以使用的最低值是*
,它具有零 特异性(即它不会使复杂的选择器变得或多或少地具有特定性)。
所以你在选择器级别上唯一的办法就是增加它。不使用 hack 是否可以做到这一点取决于您对“hack”的定义。
以下是我认为的 hack,因为它使用了一个语法上合法但语义上无意义的选择器,例如 :not(_)
,它没有明显的目的,只是将类型选择器的特殊性添加到复杂选择器(即远非显而易见,尤其是外行):
.special-section p
.weird-font, :not(_).weird-font
以下内容不是我认为是 hack,因为这是你通常会做的事情。几乎唯一的“问题”是它明显重复了单独的类选择器:
.special-section p
.weird-font, .special-section p.weird-font
如果您为了提高特异性而将任何类型的无关选择器视为 hack(这是一个完全合理的 POV,请不要误会),那么 不是 hack 的下一个最好的事情是!important
.
就个人而言,我会选择一种特异性破解。 !important
有,咳咳,重要的影响,不附带特异性黑客 - 请记住 !important
and specificity have different semantics。例如,您不能使用内联样式或 javascript 覆盖 !important
声明,除非它们也被标记为重要。1
1事实上,这是我对 Lea Verou 的回应,当时她有一个 discussion on Twitter 与 !important
相比的特异性黑客攻击。
【讨论】:
在旁注中,我是唯一一个发现 Twitter 上的讨论无法阅读的人吗?例如,在您链接的讨论中,我可以看到@LeaVerou 回复您说“好点”,但我看不到您最初说的是什么! imgur.com/lUzfW7g @Flimm:哈,这就是为什么我说我对她的回应就是我的回答中给出的 :) 不是你——我将我的帐户设为私有是因为我停止使用 Twitter,但我仍然收到垃圾邮件通知.不好玩:( AFAIK 你不能用任何类型的 CSS 覆盖 JavaScript 插入的!important
属性。你需要更多的 JavaScript 才能做到这一点。
@TylerH:是的 - 我专门指的是 CSS 级别的 !important 声明。
@BoltClock 啊,“或 JavaScript”位让我失望 :-)【参考方案3】:
如今,在 2018 年,这已接近可能。
首先,CSS4 将有一种方法允许您创建更具体的选择器而不增加特异性:
:where(.special-section) p
color: red;
这会将.special-section
中的段落颜色设置为红色,但具有001 的特异性(即与普通p
选择器具有相同的特异性)。
spec 仍然称这个特殊的伪类为:something()
,但chances are it's going to be called :where()
。 (旁注:我真的want这被称为“蜜獾选择器”)。
但这仍是未来。
然而,如果您不再需要支持 IE(或者对不太完美的回退感到满意),实际上有一种方法可以实现这一点今天 ),即使用custom properties aka CSS 变量。
所以你想要这个:
.special-section p color: red;
.weird-font color: magenta;
p color: green;
但第一部分的特异性低于任何包含类的选择器。你可以这样做:
.special-section p --low-specificity-color: red;
.weird-font color: magenta;
p color: var(--low-specificity-color, green);
如果你在现代浏览器中运行下面的 sn-p,你应该注意到第二段是红色的,因为它在一个特殊的部分,但第三段是洋红色的,因为它是 .weird-font
-- 即使@ 987654333@ 具有 010 特异性,.special-section p
具有 011。
.special-section p --low-specificity-color: red;
.weird-font color: magenta;
p color: var(--low-specificity-color, green);
<p>This is a paragraph.</p>
<section class="special-section">
<p>This is a paragraph inside a special section.</p>
<p class="weird-font">This is a paragraph with a weird font inside a special section.</p>
</section>
<p class="weird-font">This is a paragraph with a weird font.</p>
<div class="weird-font">This is a div with a weird font.</div>
这是可行的,因为虽然 --low-specificity-color
被更改为 011 特异性,但它仅应用为 001 特异性。
【讨论】:
:something
(或任何名称)现在是我在科技领域期待的事情的首位!
顺便说一下,为什么是“蜜獾选择器”。我知道它与!important
的相反之处,但我没有得到链接。【参考方案4】:
我喜欢当前需要尽可能具体。我确实喜欢为将来的 CSS 更改留出空间,所以不要为了它而尽可能具体,例如:
.great-grandfather .grandfather .father .child
如果必须,我当然会。但是以上面的例子为例,如果我想为使用此类的特定元素覆盖 .child
,其样式可能如下所示:
.child
color: black;
如果可能的话,我会去上面的一位家长覆盖它:
.father .child
color: white;
再往下说,如果特定页面上的元素使用.child
类,在这种情况下我需要同时覆盖.father .child
,我将再上一层:
.grandfather .father .child
color: red;
这样做可以确保您不需要使用!important
... 我尽可能避免像瘟疫一样!
【讨论】:
那么有没有办法实现与.parent child
选择器相同的效果,但特异性较低?以上是关于嵌套 CSS 选择器而不增加特异性的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 中显示保存文件文档选择器而不提供本地文件 url