这当然是假设永远不会有理由使用没有值的<a>
标签。href
也许这是一个错误的假设。
这取决于您的项目。严格来说,这是一个错误的假设,因为并非每个<a>
元素都需要有一个href
属性。事实上,在 HTML5 中仍然不需要href
为每个<a>
. Chris Blake和Ryan P提到了命名锚点,我要补充一点,虽然 for 的name
属性在 HTML5<a>
中已经过时,但命名锚点仍然很普遍,并且将继续存在,仅仅是由于传统和传统。
也就是说,今后,建议作者使用id
属性而不是命名锚来指定文档锚片段。
此外,<a>
缺少href
属性但具有onclick
JavaScript 属性的元素是一团糟。即使您坚持使用onclick
绑定事件,为了优雅降级,您至少应该使用href
.
但是为了简单起见,让我们假设您不会编写没有属性的<a>
元素。href
考虑到这一点,回到 CSS 选择器,有两点需要考虑:
他们是一样的吗?
不,选择器a
和a:link, a:visited
不是严格等价的。我将引用我之前关于这个主题的答案:
选择器a
应该匹配任何<a>
元素,而a:link
只匹配未访问的超链接<a>
的元素(HTML 4 文档类型将超链接定义为具有属性的元素)。它在任何一个规范中都没有说明应该自动转换为,反之亦然。<a>
href
a
a:link
换句话说,在 HTML 中,a:link, a:visited
(在 CSS1 中)严格等同于a[href]
(在带有属性选择器的 CSS2 中)或a:any-link
(在选择器级别 4中的新),而不是a
. 请注意,属性是否具有值并不重要,只要它存在,伪类就会匹配,因此[href]
. 另请注意,这适用于所有当前的 HTML 标准,我相信这包括 HTML5,因为如上所述href
不是任何现有规范中的必需属性。
请记住,其他语言可能为:link
and定义完全不同的语义:visited
——碰巧它们与 HTML 中同样特定的选择器相吻合,接下来将介绍...
特异性
这是一个巨大的陷阱:a
比a:link
or更不具体a:visited
,这是一个非常常见的特异性问题来源,在将样式应用于a
,a:link
和a:visited
单独应用时尤其明显。然后,这会导致各种!important
黑客攻击来解决对特异性缺乏了解的问题。
例如,考虑这个 CSS:
/* All unvisited links should be red */
a:link {
color: red;
}
/* All visited links should be slightly darker */
a:visited {
color: maroon;
}
/* But no matter what, header links must be white at all times! */
body > header > a {
color: white;
}
这不能按预期工作,因为a:link
and a:visited
(我称之为通用规则/选择器)比body > header > a
(我称之为专用规则/选择器)更具体,因此标题链接实际上永远不会是白色的:
/* 1 pseudo-class, 1 type -> specificity = (0,1,1) */
a:link, a:visited
/* 3 types -> specificity = (0,0,3) */
body > header > a
现在大多数 CSS 编码人员首先想到的就是投入!important
,完全胜过特异性:
body > header > a {
color: white !important;
}
但这会让你得到各种各样的坏名声,对吧?所以我们不要那样做。
选择器级别 4 为您提供的不是一个,而是两个解决此特异性问题的方法。这些解决方案虽然是新的,但在 Internet Explorer 和 Microsoft Edge Legacy(UWP/EdgeHTML/not-Chromium 之一)中不受支持,但值得庆幸的是,在 Internet Explorer 7 及更高版本中还有第三种解决方案,a[href]
即我上面提到的属性选择器。
1.:any-link
伪类
:any-link
它背后有一些历史,您可以在我对这个问题的回答中阅读,但实际上,:any-link
它可以作为:link, :visited
. 它的主要目的是消除选择器重复,因此实际上存在:is(:link, :visited)
.
您可以a:any-link
在您的专门规则中使用来匹配通用规则a:link
和a:visited
规则的特殊性,从而允许它覆盖它们:
a:link {
color: red;
}
a:visited {
color: maroon;
}
/* 1 pseudo-class, 3 types -> specificity = (0,1,3) */
body > header > a:any-link {
color: white;
}
2.:where()
伪类
:where()
它背后也有一些历史,但本质上它是一个类似物,:is()
除了它将其论点的特殊性归零。有关它如何工作的深入指南,请参阅我对这个问题的回答。
:link
您可以将 s和:visited
伪类包装在:where()
s 中以删除它们的伪类特异性,从而允许它们被专用规则覆盖:
/* 1 type -> specificity = (0,0,1) */
a:where(:link) {
color: red;
}
/* 1 type -> specificity = (0,0,1) */
a:where(:visited) {
color: maroon;
}
/* 3 types -> specificity = (0,0,3) */
body > header > a {
color: white;
}
3. a[href]
(对于旧版浏览器)
幸运的是,如果您需要支持较旧的浏览器,属性选择器与伪类一样具体。这意味着您可以使用a[href]
来表示 both/eithera:link
和/or a:visited
,而不会遇到具体问题,因为它们同样具体!
/* 1 attribute, 3 types -> specificity = (0,1,3) */
body > header > a[href] {
color: white;
}
那么使用哪个选择器呢?
这仍然是非常主观的,但我遵循以下个人经验法则:
适用于不依赖于链接状态的a
样式(即只要是链接就可以)。
应用于a:link
和是否访问链接无关紧要a:visited
的样式。
考虑到上面提到的特殊性问题,不要在 and / 规则之间混用 a
任何a:link
声明a:visited
。如果我需要将相同的属性应用于某处的两个州,但我已经在单独a:link
的a:visited
规则中拥有它,我将使用上述 3 个选项之一来避免特异性问题。
例如,以下是我在网站发布前的 Coming Soon 页面中使用的链接样式:
a {
text-decoration: none;
transition: text-shadow 0.15s linear;
}
a:link {
color: rgb(119, 255, 221);
}
a:visited {
color: rgb(68, 204, 170);
}
a:hover, a:active {
text-shadow: 0 0 0.5em currentColor;
}
a:focus {
outline: thin dotted;
}
/* ... */
footer a:link, footer a:visited {
color: rgb(71, 173, 153);
}
text-shadow
过渡是为所有元素定义的,a
无论它们是否被访问,因为过渡只有在其中一个被鼠标悬停并单击时才会生效(对应于a:hover, a:active
规则)。
现在,我希望访问过的链接比未访问过的链接有更深的阴影,所以我将颜色放在单独的a:link
规则a:visited
中。但是,出于某种原因,无论是否访问页脚链接,我都希望页脚链接显示相同的颜色。
如果我使用footer a
,我会遇到上面描述的特异性问题,所以我选择footer a:link, footer a:visited
了。这是出于遗留原因(如下所示,我最初是在 2012 年发布的!),但当然可以将其缩短为footer a:any-link
. 然而,特异性匹配原则同样适用。
希望我的建议可以帮助您处理链接样式的混乱。