在我最近一篇关于 Chrome 中 CSS 下划线错误 的文章中,我讨论了 text-decoration-thickness
和 text-underline-offset
,这两个相对较新且广泛支持的 CSS 属性,它们使我们能够更好地控制下划线的样式。
让我在一个简单的示例中演示 text-decoration-thickness
的实用性。 Ubuntu 网页字体 具有相当粗的默认下划线。我们可以像这样使该下划线变细
:any-link {
text-decoration-thickness: 0.08em;
}

/explanation 在本文中,我将使用 :any-link
选择器而不是 a
元素来匹配超链接。使用 a
标签作为选择器的问题在于它匹配所有 <a>
元素,即使那些没有 href
属性且因此 不是超链接 的元素。:any-link
选择器仅匹配是超链接的 <a>
元素。Web 浏览器在其用户代理样式表中也使用 :any-link
而不是 a
。
悬停下划线
许多网站,包括 Google 搜索和维基百科,都会从链接中删除下划线,并且仅在用户将鼠标悬停在链接上时才显示它们。从正文中的链接中删除下划线 不是一个好主意,但在链接间隔较大的地方(导航、页脚等)这样做可能是有意义的。综上所述,以下是在网站标题中为链接实现悬停下划线的简单方法
header :any-link {
text-decoration: none;
}
header :any-link:hover {
text-decoration: underline;
}
但是,存在一个问题。如果我们在浏览器中测试此代码,我们会注意到标题中的下划线具有默认粗细,而不是我们之前声明的较细样式。为什么在添加悬停下划线后 text-decoration-thickness
停止工作了?
让我们再次查看完整的 CSS 代码。您能否想到自定义 thickness
不适用于悬停下划线的原因?
:any-link {
text-decoration-thickness: 0.08em;
}
header :any-link {
text-decoration: none;
}
header :any-link:hover {
text-decoration: underline;
}
这种行为的原因是 text-decoration
是一个简写属性,而 text-decoration-thickness
是其关联的长写属性。将 text-decoration
设置为 none
或 underline
会产生重新初始化其他三个文本装饰组件(thickness
、style
和 color
)的副作用。这在 CSS 文本装饰模块 中定义。
text-decoration
属性是用于在一个声明中设置text-decoration-line
、text-decoration-thickness
、text-decoration-style
和text-decoration-color
的简写。省略的值将设置为其初始值。
您可以在浏览器的 DevTools 中确认这一点,方法是在 DOM 检查器中选择其中一个超链接,然后在 CSS 面板中展开 text-decoration
属性。

为了使 text-decoration-thickness
在悬停下划线上起作用,我们需要对上述 CSS 代码进行一些小的更改。实际上,有多种方法可以实现这一点。我们可以
- 在
text-decoration
之后设置text-decoration-thickness
, - 在
text-decoration
简写中声明粗细,或者 - 使用
text-decoration-line
代替text-decoration
。
选择最佳的 text-decoration 选项
我们首先想到的可能是简单地在 :hover
状态中重复 text-decoration-thickness
声明。这是一个快速简单的修复方法,确实有效。
/* OPTION A */
header :any-link {
text-decoration: none;
}
header :any-link:hover {
text-decoration: underline;
text-decoration-thickness: 0.08em; /* set thickness again */
}
但是,由于 text-decoration
是一个简写,而 text-decoration-thickness
是其关联的长写,因此实际上无需同时使用两者。作为简写,text-decoration
允许在一个声明中同时设置下划线本身和下划线的粗细。
/* OPTION B */
header :any-link {
text-decoration: none;
}
header :any-link:hover {
text-decoration: underline 0.08em; /* set both line and thickness */
}
如果您觉得此代码不熟悉,则可能是因为将 text-decoration
用作简写的想法相对较新。此属性只是随后在 CSS 文本装饰模块 中变成了简写。在 CSS 2 时代,text-decoration
是一个简单的属性。
不幸的是,Safari 尚未完全赶上这些变化。在 WebKit 浏览器引擎中,text-decoration
的简写变体仍然带有前缀(-webkit-text-decoration
),并且它尚不支持 thickness
值。有关更多信息,请参阅 WebKit 错误 230083。
这排除了 text-decoration
简写语法。即使我们添加了 -webkit-
前缀,上述代码在 Safari 中也不会起作用。幸运的是,还有另一种方法可以避免重复 text-decoration-thickness
声明。
当 text-decoration
变为简写时,引入了新的 text-decoration-line
长写来接管其旧工作。我们可以使用此属性来隐藏和显示下划线,而不会影响其他三个文本装饰组件。
/* OPTION C */
header :any-link {
text-decoration-line: none;
}
header :any-link:hover {
text-decoration-line: underline;
}
由于我们仅更新 text-decoration
值的 line
组件,因此之前声明的 thickness
保持不变。我认为这是实现悬停下划线的最佳方法。
注意简写
请记住,当您设置简写属性(例如,text-decoration: underline
)时,值中任何缺失的部分都会重新初始化。这也是为什么如果您随后设置 background: url(flower.jpg)
,则样式(如 background-repeat: no-repeat
)会被撤消的原因。有关此行为的更多示例,请参阅文章 “意外的 CSS 重置”。
不明白为什么不能将 text-decoration-thickness 设置为 0。为什么存在限制?
最小厚度为“一个设备像素”。我想这个决定是为了简单起见。