有没有一种按类名前缀选择的CSS选择器?

242

我想将CSS规则应用于任何一个类名以指定前缀开头的元素。

例如,我希望有一条规则适用于一个具有以status-开头的类名的div元素(在以下代码片段中,适用于A和C,但不适用于B):

<div id='A' class='foo-class status-important bar-class'></div>
<div id='B' class='foo-class bar-class'></div>
<div id='C' class='foo-class status-low-priority bar-class'></div>

是否可以将以下两种选择器的内容进行组合:
div[class|=status]div[class~=status-]

在CSS 2.1下可以实现吗?在任何CSS规范下都可以实现吗?

注:我知道可以使用jQuery来模拟此效果。

4个回答

498

使用CSS2.1是不可行的,但是可以使用CSS3属性子字符串匹配选择器(在IE7+中受支持):

div[class^="status-"], div[class*=" status-"]

注意第二个属性选择器中的空格字符。这会选取其class属性满足以下任一条件的div元素:
  • [class^="status-"] — 以"status-"开头

  • [class*=" status-"] — 包含子字符串"status-",直接在空格字符后出现。根据HTML规范,类名由空格分隔per the HTML spec,因此空格字符很重要。如果指定了多个类,则检查第一个类之后的任何其他类,并添加检查第一个类的奖励,以防属性值带有空格填充(某些动态输出class属性的应用程序可能会出现这种情况)。

当然,这也适用于jQuery,如here所示。
需要按照上述方式组合两个属性选择器的原因是,一个属性选择器(例如[class*="status-"])将匹配以下元素,这可能是不希望的:
<div id='D' class='foo-class foo-status-bar bar-class'></div>

如果您能确保这种情况永远不会发生,那么出于简单起见,您可以使用这样的选择器。然而,上述组合更加健壮。
如果您控制HTML源代码或生成标记的应用程序,则将status-前缀作为自己的status类可能更简单正如Gumbo所建议的那样

1
如果由于某种奇怪的原因您有一个名为status-的类,并且您不想匹配它,那么选择器会变得更加复杂:div[class^="status-"]:not(.status-), div[class*=" status-"]:not(.status-)。此外,您将失去IE7 / IE8的支持。幸运的是,如果您的标记合理,您将不需要排除这样的类。 - BoltClock
2
@WebDevRon:你忘记了 ^= 部分。如果你的类属性保证以 anim-overlay- 开头,那么你可能不需要 *= 部分。 - BoltClock
2
@Daniel Compton:感谢您的编辑。事后我意识到,像那样的话可能会让某些人感到居高临下,因为对于他们来说,某些事情可能并不那么明显。我知道有些人真的不喜欢这种改变,所以我主要是想让您知道我接受了您的修改。 - BoltClock
根据您提供的HTML规范链接,类名可以由任何ASCII空格分隔,包括例如制表符和换行符。因此,例如如果HTML文档具有class="fooTABstatus-important"class="fooNEWLINEstatus-important",选择器是否仍将匹配此类?CSS规范是否说选择器中的空格将匹配_任何_空格,还是只匹配字面上的空格字符?如果它只匹配一个字面上的空格字符,则不能保证该选择器始终有效。 - Garret Wilson
好的,没问题,但这并不是答案所说的。在计算机科学中,某些东西“能用”和“大部分时间都能用”之间有很大的区别。答案让它看起来像是符合CSS选择器匹配规则,但实际上并不是。我认为,如果你说“它在我测试的数据上可以运行,即使它没有涵盖规范的变化”,你可能会遇到很大的麻烦。这与使用正则表达式而不是XML解析器解析XML一样危险。至少,答案需要声明这是一种启发式方法,不能覆盖所有可能性。 - Garret Wilson
显示剩余5条评论

23

CSS属性选择器可以让您检查字符串的属性(在本例中是类名)。

https://developer.mozilla.org/zh-CN/docs/Web/CSS/Attribute_selectors

(看起来实际上处于2.1和3的“推荐”状态)


以下是我认为它工作原理的大纲:

  • [ ] :如果您愿意,这是复杂选择器的容器 ……
  • class :在这种情况下,“class”是您要查看的属性
  • * :修改器(如果有):在这种情况下,“通配符”表示您正在寻找任何匹配项。
  • test- :属性的值(如果有)- 包含字符串“test-”(可以是任何内容)

例如:

[class*='test-'] {
  color: red;
}

如果您有充分的理由,您可以更加具体,包括元素:

ul[class*='test-'] > li { ... }

我尝试找出边缘情况,但我认为没有必要使用^*的组合-因为*会获取所有内容...

例如:http://codepen.io/sheriffderek/pen/MaaBwp

http://caniuse.com/#feat=css-sel2

IE6以上的浏览器都能够很好地支持。 :)

请注意:

[class] { ... }

将选择任何带有类的内容...


1
[class*='test-'] 可以匹配这样的元素 <div class='foo-test-bar'>。 这是需要结合使用^和*的一种特殊情况,正如我的答案中所描述的。而IE6不支持属性选择器。 - BoltClock
@BoltClock - 感谢您的澄清!- 我不支持 < EI9 - 我永远不会编写任何会互相干扰的类 - 所以对我来说这很有效。:) - sheriffderek
1
当CSS选择器变成正则表达式时,这真是有趣。哈哈,我知道这不是一个无用的技能! - Michael Martell

5
这在 CSS 选择器中是不可能的。但是,您可以使用两个类代替一个类,例如使用 statusimportant 来代替 status-important

15
将其分离成自己的类别是个好主意,但使用CSS选择器也是可能的。请参考我的答案。 - BoltClock

2
您无法这样做。有一个属性选择器与减号之前的内容完全或部分匹配,但在这里不起作用,因为您有多个属性。如果您要查找的类名称始终是第一个,可以这样做:
<html>
<head>
<title>Test Page</title>
<style type="text/css">
div[class|=status] { background-color:red; }
</style>
</head>
<body>
<div id='A' class='status-important bar-class'>A</div>
<div id='B' class='bar-class'>B</div>
<div id='C' class='status-low-priority bar-class'>C</div>

</body>
</html>

请注意,这只是为了指出哪个CSS属性选择器最接近,不建议假设类名始终在前面,因为JavaScript可以操作属性。

2
是的,考虑到了这一点。当jQuery介入时,可能会成为一个问题,因为它可能会在前面插入一个类。 - THX-1138
是的,我会编辑我的帖子,以使其清楚地表明这绝对不是推荐的做法。如果您可以控制类名,则Gumbo的建议肯定是正确的方法(加上旧版IE浏览器上的属性选择器不受支持)。 - SBUJOLD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接