为链接下方设置下划线样式可能是一件棘手的事情,我总是忘记根据情况选择最佳方法。不过幸运的是,John Jameson 在这篇客座文章中为我们提供了快速入门指南。
有很多不同的方法可以为下划线设置样式。您可能还记得文章 在 Medium 上制作链接下划线。Medium 并没有尝试做任何 疯狂的事情;他们只是想在文本下方创建一个看起来很正常的线条。

这只是一个非常基础的下划线,但大小合适,而且还会跳过下垂部分。这绝对比大多数浏览器的默认样式要好。好吧,事实证明 Medium 为了在网页上实现这种样式,不得不费尽心思。两年过去了,为下划线设置一个好看的样式仍然很困难。
目标
直接使用 text-decoration: underline
有什么问题?如果我们谈论的是理想情况,下划线应该能够做到以下几点:
- 将其自身定位在基线下方
- 跳过下垂部分
- 更改颜色、粗细和样式
- 在换行文本中重复
- 在任何背景上工作
我认为这些都是很合理的要求,但据我所知,目前还没有简单直观的方法在 CSS 中实现所有这些要求。
方法
那么,在网页上设置文本下划线样式有多少种不同的方法呢?
以下是我能想到的几种方法:
text-decoration
border-bottom
box-shadow
background-image
- SVG 滤镜
- Underline.js (canvas)
text-decoration-*
让我们逐一讨论每种方法的优缺点。
text-decoration
text-decoration
是设置文本下划线样式最直接的方法。您只需应用一个属性,就完成了所有操作。在较小的尺寸下,这种方法看起来还算不错,但如果增加字体大小,同一条线就开始显得笨拙了。
查看 演示。
text-decoration
最大的问题在于它缺乏自定义功能。它使用应用于它的文本的颜色和字体大小,并且没有跨浏览器的方法可以更改样式。我们稍后会详细说明这一点。
优点
- 易于使用
- 定位在基线下方
- 在 Safari 和 iOS 中默认情况下会跳过下垂部分
- 跨行换行
- 在任何背景上工作
缺点
- 无法在其他浏览器中跳过下垂部分
- 无法更改颜色、粗细或样式
border-bottom
border-bottom
在速度和自定义功能之间取得了良好的平衡。这种方法使用了经过验证的 CSS 边框,这意味着您可以轻松地更改颜色、粗细和样式。
这是 border-bottom
在 inline
元素上的显示效果:
查看 演示。
最大的问题在于下划线离文本的距离——它完全位于下垂部分下方。您可以通过将元素设置为 inline-block
并减小 line-height
来解决这个问题,但这会导致您无法换行文本。适合单行文本,但不适合其他情况。
查看 演示。
此外,您可以使用 text-shadow
来遮盖下划线靠近下垂部分的部分,但您必须使用与背景相同的颜色来伪造它。这意味着它只适用于纯色背景,不适用于渐变或图像背景。
查看 演示。
到目前为止,有四个属性用于设置单个下划线的样式。这比 text-decoration
要多得多。
优点
- 可以使用
text-shadow
跳过下垂部分 - 可以更改颜色、粗细和样式
- 可以对颜色和粗细进行过渡和动画
- 默认情况下会换行,除非它是一个
inline-block
- 在任何背景上工作,除非使用
text-shadow
缺点
- 位置距离很远,难以重新定位
- 要使它完美,需要使用许多无关的属性
- 使用
text-shadow
时,文本选择效果很糟糕
box-shadow
box-shadow
使用两个内嵌的阴影来绘制下划线:一个用来创建一个矩形,另一个用来遮盖它。这意味着您需要一个纯色背景才能使这种方法生效。
查看 Pen 下划线 5:box-shadow,作者 John D. Jameson (@johndjameson) 在 CodePen 上发布。
您可以使用相同的 text-shadow
技巧来伪造下划线与文本下垂部分之间的间隙。但如果线条颜色与文本颜色不同——或者只是足够细——它就不会像 text-decoration
那样发生冲突。
优点
- 可以定位在基线下方
- 可以使用
text-shadow
跳过下垂部分 - 可以更改颜色和粗细
- 跨行换行
缺点
- 无法更改样式
- 在任何背景上都不起作用
background-image
background-image
最接近我们想要的一切,而且出现的问题最少。其思想是使用 linear-gradient
和 background-position
来创建一个水平重复自身的图像,横跨文本行。
您还需要将这种方法设置为 display: inline;
。
查看 演示。
这种方法也不必使用 linear-gradient
。您可以使用自己的背景图像来实现一些酷炫的效果。
查看 演示。
优点
- 可以定位在基线下方
- 可以使用
text-shadow
跳过下垂部分 - 可以更改颜色、粗细(允许使用半像素)和样式
- 可以使用自定义图像
- 跨行换行
- 在任何背景上工作,除非使用
text-shadow
缺点
- 图像可以根据分辨率、浏览器和缩放级别进行不同的调整大小
SVG 滤镜
我一直在尝试的一种方法是:SVG 滤镜。您可以创建一个内嵌的 SVG filter
元素来绘制一条线,然后扩展文本以遮蔽我们想要透明的部分。然后,您可以为 filter
指定一个 id
,并在 CSS 中使用类似 filter: url(‘#svg-underline’)
的代码进行引用。
这种方法的优点在于,它添加了透明度而不依赖于 text-shadow
。这意味着您可以在任何背景上跳过下垂部分,包括渐变和背景图像!不过,这种方法只适用于单行文本,因此请注意这一点。
查看 演示。
以下是其在 Chrome 和 Firefox 中的显示效果:

在 IE、Edge 和 Safari 中,支持情况存在问题。很难测试 CSS 中的 SVG 滤镜支持情况。您可以使用 @supports
和 filter
,但这只会测试引用是否有效——而不是应用的滤镜本身。我的方法最终执行了一些非常糟糕的浏览器嗅探,因此请再次注意这一点。
优点
- 定位在基线下方
- 跳过下划线
- 可以更改颜色、粗细和样式
- 在任何背景上工作
缺点
- 不能跨行换行
- 在 IE、Edge 或 Safari 中不起作用,但您可以回退到
text-decoration
。Safari 的下划线看起来还不错。
Underline.js (Canvas)
Underline.js 很迷人。我认为 Wenting Zhang 能够用 JavaScript 和一些对细节的关注做到这一点真是太棒了。如果你以前没有看过 Underline.js 的 技术演示,一定要停下来读一分钟,看看它。在 如何运作 上有一个迷人的九分钟长的演讲,但我告诉你简短的版本:它用 <canvas>
元素绘制下划线。这是一个新颖的方法,效果出奇地好。
尽管名字很吸引人,但 Underline.js 只是一个技术演示。这意味着你不能把它直接放到任何项目中,而无需先对其进行大量的修改。
值得在这里把它作为一个概念证明。<canvas>
有可能创建漂亮、交互式的下划线,但你需要编写一些自定义 JavaScript 才能让它们工作。
text-decoration-* 属性
还记得“稍后再谈”的部分吗?现在我们到了这里。
text-decoration
本身工作得很好,但你可以添加一些实验属性来自定义它的外观
text-decoration-color
text-decoration-skip
text-decoration-style
只是不要太兴奋。你知道,浏览器支持。
text-decoration-color
text-decoration-color
允许你更改下划线的颜色,与文本颜色分开。这个属性甚至有比预期更好的浏览器支持——它在 Firefox 中有效,并且在 Safari 中带有前缀。这里有一个问题:如果你没有清除下划线,Safari 会将线放在文本的上面。🙃
Firefox

Safari

text-decoration-skip
text-decoration-skip
切换在带下划线的文本中跳过下划线。

此属性是非标准的,目前仅在 Safari 中有效,因此你需要使用 -webkit-
前缀才能使用它。不过,Safari 默认情况下启用了此属性,这就是为什么即使在没有指定此属性的网站上,下划线也会跳过下划线的原因。
如果你使用 Normalize,请注意,最近的版本禁用了此属性以保持浏览器之间的一致性。如果你想要那些梦幻般的下划线,你需要重新启用它。
text-decoration-style
text-decoration-style
提供了与 border-style
相同类型的线,但还添加了 wavy
线。
以下是你可以使用的不同值
dashed
dotted
double
solid
wavy
目前,text-decoration-style
仅在 Firefox 中有效,因此这里有一张截图

各种实色下划线样式
看起来眼熟吗?
缺少什么?
text-decoration-*
属性比使用其他 CSS 属性来设置下划线样式要直观得多。但是,如果我们再看一下我们早期的要求,这些属性不提供指定线粗细或位置的方法。
经过一番研究,我发现了这两个属性
text-underline-width
text-underline-position
看起来它们是在 CSS 的早期草案中提出的,但由于缺乏兴趣而从未实现。嘿,不要怪我。
结论
那么,设置下划线文本的最佳方法是什么?
对于小文本,我建议使用 text-decoration
,然后在上面乐观地应用 text-decoration-skip
。它在大多数浏览器中看起来有点平淡,但下划线一直都是这样,人们似乎并不介意。此外,总有机会,如果你足够耐心,你所有的下划线都会在以后看起来很棒,而你无需更改任何东西。
对于正文文本,可能使用 background-image
方法。它有效,看起来很棒,而且有 Sass 的 mixin。如果你下划线很细或者与文本颜色不同,你可能可以省略 text-shadow
。
对于单行文本,使用 border-bottom
以及你想使用的其他属性。
对于在渐变或背景图像上跳过下划线,尝试使用 SVG 滤镜。或者干脆避免使用下划线。
在未来,当浏览器支持更好时,答案就是一直使用 text-decoration-*
。
另请参阅 Benjamin Woodruff 的文章 CSS 下划线很烂,巧合的是,它也以类似的方式讨论了这个问题。
还有使用
position: absolute
、bottom: <value>
和height: <value>
的伪元素。我通常将其用于带有下划线动画的按钮悬停啊,说得对!我忘了伪元素。它们具有很大的灵活性——尤其是对于过渡和动画——但与许多其他方法一样,它们也存在相同的换行问题。如果你牢记约束,它们仍然很有趣。很棒的例子 :D
很棒的总结!我在这个演示中还有一个例子:http://codepen.io/tomhodgins/pen/PGoVGJ
在这个笔中寻找“下划线”示例。它创建了两个重叠的椭圆形,并允许你创建一个与单词一样宽的弯曲下划线。唯一的问题是,你需要有一个纯色背景(并使用该背景色作为顶部的椭圆形)才能使效果生效
本地
text-decoration-skip
的一个好处是,它实际上跳过了整个下划线——这在你有像小写g
这样的东西时很重要(所有其他选项都会在下划线中留下一小部分,我认为这看起来非常别扭)。我同意,尽管我喜欢其他技术使下划线末端与下划线形状相符的方式。
text-decoration-skip
看起来它只是跟随字形的边界框。更好的方法是扩展形状的轮廓,但使用非零绕组规则而不是更常见的奇偶规则来区分字形的内部和外部。我不确定对于这里的任何技术是否可能。
实际上,这也行不通。它有助于解决示例中可爱的闭合碗状 g,但仍然无法处理 y 或递归 j 形状。
不错的总结。
查看以下背景线性渐变方法
http://stackoverflow.com/a/32145544/947370
您演示的所有链接似乎都已损坏。它们都指向“您已在互联网结构中撕开了一个洞”错误页面。
使用 NoScript?允许 codepen.io、cloudfare.com、wp.com 以及 {sob} google-analytics.com
请注意,高对比度模式可能会删除背景和阴影,并可能导致链接无法被感知。我认为指出这一点很重要。
我最终使用了一个 JS 测试(通过其
addTest
方法插入了 Modernizr)和ms-high-contrast media
查询,在检测到高对比度模式时回退到经典的下划线。这里有一个使用渐变样式化下划线的示例:http://codepen.io/ffoodd/pen/jbRMqJ/
以及一个在 Modernizr 中插入高对比度检测的 gist:https://gist.github.com/ffoodd/78f99204b5806e183574
那如何使用 mix-blend-mode 来去除背景呢?http://codepen.io/Kingeek/pen/PGZdyz
很棒!
好文章!
希望我需要的时候能记住它。=D
为什么人们想跳过下降字母?对我来说这看起来更令人分心,而不是我期望的下划线的样子。
好文章,但我认为带文本阴影的下边框看起来很棒。
+1 支持伪元素。您还可以执行诸如相对于父元素设置宽度之类的操作。这对标题很有效。
自发布以来,CSS 工具箱中添加了更多用于下划线的工具,例如
text-decoration-thickness