CSS 属性选择器详解

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您的旅程各个阶段提供云产品。 立即开始使用 200 美元免费积分!

CSS 能够根据 HTML 元素的任何属性来定位元素。 您可能已经了解了类和 ID。 查看这段 HTML 代码

<h2 id="title" class="magic" rel="friend">David Walsh</h2>

此单个元素具有三个属性:ID、类和 rel。 要在 CSS 中选择此元素,您可以使用 ID 选择器(#title)或类选择器(.magic)。 但您是否知道您也可以根据 rel 属性来选择它? 这被称为属性选择器

h2[rel="friend"] {
   /* woohoo! */
}

不过,属性选择器还有更多内容,让我们仔细看看所有不同的选项,并尝试涵盖一些在它们可能有用时的一些“现实世界”场景。

属性完全等于某个值

在我们上面使用的示例中,h2 元素的属性是“friend”。 我们编写的 CSS 选择器定位了该 h2 元素,因为它的 rel 属性恰好是“friend”。 换句话说,等号的意思与您想的一样……完全匹配。 请查看另一个基本示例

<h1 rel="external">Attribute Equals</h1>
h1[rel="external"] { color: red; }

这在样式化博客链接方面是一个很好的现实世界示例。 假设您有一系列指向朋友网站的链接,如下所示

<a href="http://perishablepress.com">Jeff Starr</a>
<a href="http://davidwalsh.name">David Walsh</a>
<a href="http://accidentalninja.net/">Richard Felix</a>

然后您想稍微不同地设置每个链接的样式。 传统方法可能是为每个链接提供一个类名称作为定位目标,但这需要额外的标记,而这始终是需要避免的事情(语义等)。 另一种方法可能是使用 :nth-child,但这要求它们的顺序永远不会改变。 这正是属性选择器的完美用例……这些链接已经拥有可以定位的唯一属性!

a[href="http://perishablepress.com"] { color: red; }

我相信最常见的用法是将常规属性选择器用于输入。 有文本、按钮、复选框、文件、隐藏、图像、密码、单选按钮、重置和提交(我有没有遗漏任何?)。 它们都是<input>,但它们又截然不同。 因此,像这样input { padding: 10px; }大多数情况下是一个坏主意。 很常见的是看到类似以下内容

input[type="text"] { padding: 3px; }
input[type="radio"] { float: left; }

这实际上是获取某些类型的输入而不影响其他输入以及不添加额外标记的唯一方法。

关于引号的说明:在属性选择器中,您通常可以不使用引号,例如 [type=radio],但省略引号的规则很奇怪,并且在实际浏览器实现之间不一致。 因此,最佳实践是使用引号,例如 [type="radio"]。 这样做更安全,并且始终有效。

属性包含某个值(位于任意位置)

从这里开始变得更有意思。 属性选择器中的等号前面可以添加其他字符,从而略微改变其含义。 例如,“*=” 表示“匹配以下值在属性值中的任意位置”。 请查看此示例

<h1 rel="xxxexternalxxx">Attribute Contains</h1>
h1[rel*="external"] { color: red; }

请记住,类和 ID 也是属性,可以与属性选择器一起使用。 因此,假设您正在为一个网站编写 CSS,您无法控制标记,并且一位粗心的开发者有三个您需要定位的 DIV

<div id="post_1"></div>
<div id="post_two"></div>
<div id="third_post"></div>

您可以使用以下方法选择它们

div[id*="post"]  { color: red; }

属性以某个值开头

<h1 rel="external-link yep">Attribute Begins</h1>
h1[rel^="external"] { color: red; }

使用它的一个现实世界示例是,假设您想将指向朋友网站的所有链接的样式与其他链接不同。 无论您是链接到他们的主页还是任何子页面,您都希望将指向他们的任何链接都设置样式。

a[href^="http://perishablepress.com"] { color: red; }

这将匹配指向他们主页的链接,以及所有其他子页面。

属性以某个值结尾

我们可以根据属性值的开头来选择,为什么不能根据结尾来选择呢?

<h1 rel="friend external">Attribute Ends</h1>
h1[rel$="external"] { color: red; }

使用这些的一个好用例是,根据文件类型对带图标的文件下载锚链接进行标记。 例如,PDF 文件使用 PDF 图标,Word 文档使用 Word 图标

a[href$=".pdf"] { background: url(icon-pdf.png) left center no-repeat; padding-left: 30px; }
a[href$=".doc"] { background: url(icon-doc.png) left center no-repeat; padding-left: 30px; }

属性位于空格分隔的列表中

您可能已经知道,您可以将多个类应用于元素,对吧? 如果这样做,您仍然可以在 CSS 中使用 .class-name 来定位其中的任何一个。 属性选择器没有那么容易。 如果您的 rel 属性具有多个值(例如,空格分隔列表中的值),则需要使用“~=

<h1 rel="friend external sandwich">Attribute Space Separated</h1>
h1[rel~="external"] { color: red; }

您可能在想,为什么我要使用这个,而 *= 也能匹配这个,并且更加通用? 的确,它更加通用,但它也可能过于通用。 此选择器要求值周围有空格,而 *= 则不需要。 因此,如果您有两个元素,一个具有rel=home friend-link另一个具有rel=home friend link您将需要空格分隔选择器才能正确地定位第二个元素。

属性是破折号分隔列表的开头

这将选择如果破折号分隔的属性值列表的开头与选择器匹配。

<h1 rel="friend-external-sandwich">Attribute Dash Separated</h1>
h1[rel|="friend"] { color: red; }

请注意,即使它是根据选择器的开头进行匹配,但第一个破折号之前的整个字符串部分也必须匹配。 因此,在上面的示例中,如果rel属性是friend2-external-sandwich,则它将不匹配,而^=属性选择器将匹配。

多个属性匹配

需要注意的是,您可以在同一个选择器中使用多个属性选择器,这要求它们全部匹配才能使选择器本身匹配。

<h1 rel="handsome" title="Important note">Multiple Attributes</h1>
h1[rel="handsome"][title^="Important"] { color: red; }

不区分大小写的属性选择器

默认情况下,属性选择器内部的字符串区分大小写,但您可以传递一个使它不区分大小写的值,而不是在需要匹配大小写的情况下匹配大小写的多种排列组合

/* Will match
<div data-state="open"></div>
<div data-state="Open"></div>
<div data-state="OPEN"></div>
<div data-state="oPeN"></div>
*/
[data-state="open" i] { }

在 CSS 中使用属性

您不仅可以通过属性进行选择,还可以在 CSS 内容中使用属性,例如…

.el::before {
  content: attr(data-prefix) ": ";
}

希望有一天,我们会在 CSS 中的attr()函数中获得对类型备用的支持,例如

.el {
  /* <div class="el" data-font-size="18"> */
  font-size: attr(data-font-size px);

  /* <div class="el"> */
  font-size: attr(data-font-size px, 18px);
}

浏览器支持

上面的每个示例都可以在所有现代浏览器中运行:Safari、Chrome、Firefox、Opera 和 IE。 Internet Explorer 对所有这些都具有完美支持,直到版本 7,但在版本 6 中没有支持。 要在您的浏览器中进行测试,请查看 测试页面。 如果行/选择器样式为红色,则表示它可以运行。