网页上的下划线样式

Avatar of John D. Jameson
John D. Jameson

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

为链接下方设置下划线样式可能是一件棘手的事情,我总是忘记根据情况选择最佳方法。不过幸运的是,John Jameson 在这篇客座文章中为我们提供了快速入门指南。

有很多不同的方法可以为下划线设置样式。您可能还记得文章 在 Medium 上制作链接下划线。Medium 并没有尝试做任何 疯狂的事情;他们只是想在文本下方创建一个看起来很正常的线条。

A thin, black underline with space around descenders
一条细细的黑色下划线,下垂部分周围有空白——来自 Marcin Wichary,在 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-bottominline 元素上的显示效果:

查看 演示

最大的问题在于下划线离文本的距离——它完全位于下垂部分下方。您可以通过将元素设置为 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-gradientbackground-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 滤镜支持情况。您可以使用 @supportsfilter,但这只会测试引用是否有效——而不是应用的滤镜本身。我的方法最终执行了一些非常糟糕的浏览器嗅探,因此请再次注意这一点。

优点
  • 定位在基线下方
  • 跳过下划线
  • 可以更改颜色、粗细和样式
  • 在任何背景上工作
缺点
  • 不能跨行换行
  • 在 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 下划线很烂,巧合的是,它也以类似的方式讨论了这个问题。