当然,这是基于永远不会有使用没有href值的
标签的理解。也许这是一个错误的假设。
这取决于你的项目。严格来说,那是一个错误的假设,因为并非每个 <a>
元素都需要有 href
属性。实际上,在 HTML5 中仍然不需要为每个 <a>
指定 href
。Chris Blake 和 Ryan P 提到了命名锚点,我要补充的是,虽然在 HTML5 中 <a>
的 name
属性已经作废, 但是由于传统和历史原因,命名锚点依然广泛存在并将继续存在。
话虽如此,从现在开始,建议作者使用 id
属性而不是命名锚点来指定文档锚点片段。
此外,缺少 href
属性但具有用于 JavaScript 的 onclick
属性的 <a>
元素会很混乱。即使您坚持使用 onclick
来绑定事件,在考虑优雅降级的情况下,您也应该至少使用 href
将其指向 某个地方。
但为了简化事情,让我们假设您不会编写没有 href
属性的 <a>
元素。
考虑到 CSS 选择器,有两个重要的要点:
它们是否相同?
不,选择器 a
和 a:link,a:visited
不严格等效。我将引用我之前在previous answer上对此问题的回答:
选择器
a
应匹配任何
<a>
元素,而
a:link
仅匹配未访问的超链接
<a>
元素(HTML 4 文档类型将超链接定义为具有
href
属性的
<a>
元素)。在任一规范中都没有说明
a
应自动转换为
a:link
或反之亦然。
换句话说,在HTML中,
a:link,a:visited
(在CSS1中)严格等同于使用属性选择器的
a[href]
(在CSS2中)或
a:any-link
(在
选择器级别4中引入的新选择器),而不是
a
。请注意,无论属性是否有值,只要存在伪类就会匹配,因此使用
[href]
。还要注意,这适用于所有当前的HTML标准,我相信这包括HTML5,因为如上所述,
href
在任何现有规范中都不是必需属性。
请记住,其他语言可能为
:link
和
:visited
定义完全不同的语义-它们恰好与HTML中同样具体的选择器重合,下面将介绍这些选择器...
特异性
这是一个很大的坑点:
a
比
a:link
或者
a:visited
不够具体,这是特别明显的优先级问题的常见来源,尤其是在分别应用样式到
a
、
a:link
和
a:visited
时。这将导致各种
!important
的hack,以解决对优先级不理解的问题。
例如,考虑以下 CSS:
a:link {
color: red;
}
a:visited {
color: maroon;
}
body > header > a {
color: white;
}
这并不像预期的那样工作,因为所谓的一般规则/选择器
a:link
和
a:visited
比所谓的专用规则/选择器
body > header > a
更加具体,因此标题链接实际上
永远不会变成白色。
a:link, a:visited
body > header > a
现在,大多数CSS编码者首先想到的是加入
!important
,完全取代特定性:
body > header > a {
color: white !important;
}
但这会给你带来各种不好的声誉,对吧?所以我们不要那样做。
选择器级别4为您提供了不止一个,而是两个解决此特定性问题的方法。尽管这些新的解决方案在Internet Explorer和Microsoft Edge Legacy(UWP / EdgeHTML /非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;
}
body > header > a:any-link {
color: white;
}
2. :where()
伪类
:where()
也有一些历史背景,但本质上它是 :is()
的类比,唯一的例外是它会将其参数的特异性归零。请参阅 这个问题 中我的答案,了解它的详细使用方法。
您可以在 :where()
中包装 :link
和 :visited
伪类,以消除它们的伪类特异性,从而允许它们被专门的规则覆盖:
a:where(:link) {
color: red;
}
a:where(:visited) {
color: maroon;
}
body > header > a {
color: white;
}
3. a[href]
(适用于旧版浏览器)
幸运的是,如果您需要支持旧版浏览器,属性选择器和伪类一样具有特定性。这意味着您可以使用a[href]
来表示a:link
和/或a:visited
,而不会遇到特异性问题,因为它们具有相同的特定性!
body > header > a[href] {
color: white;
}
那么要使用哪些选择器呢?
这仍然非常主观,但我遵循以下个人经验法则:
对于不依赖于链接状态的样式(即只要是链接就行),请应用到a
。
对于需要区分链接是否已访问的样式,请应用到a:link
和a:visited
。
考虑到上述的特异性问题,请不要在a
和a:link
/a:visited
规则之间混合任何声明。如果我需要在某个地方同时应用相同的属性,但我已经有了单独的a:link
和a:visited
规则,则我会使用上述3种选项之一来避免特异性问题。
例如,这是我在网站“即将推出”页面中使用的链接样式:
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”。但是,特异性匹配原则仍然适用。
希望我的建议能帮助您处理链接样式的混乱情况。