本文主要介紹了添加下划線樣式的幾乎所有方法,並且比較了每一種方法的優缺點。沒想到之前一直沒有注意的下划線還有這么多玄機奧秘!
英文出處:css-tricks.com
有很多種添加下划線樣式的方法。可能你還記得《 Crafting link underlines on Medium 》這篇文章。Medium 並沒有嘗試特殊的方法,只是想創建一個漂亮的看起來正常的下划線。

一條纖細的黑色下划線並且與下行字母有間隙——引自 Marcin Wichary 的《 Crafting link underlines on Medium 》
這是基本的下划線樣式,但是尺寸適中並且避開了下行字母。比大多數瀏覽器的默認效果要好。事實證明 Medium 為了獲得這種樣式遇到了很多麻煩。兩年過去了,添加一個好看的下划線樣式仍然很困難。
目標
使用 text-decoration: underline 添加下划線有什么問題嗎?如果我們討論一個理想的場景,下划線應該符合以下特點:
- 位於文本基線以下
- 避開下行字母
- 可以改變顏色、粗細及樣式
- 適用於文本換行的情況
- 適用於任意背景
我認為這些要求非常合理,但是據我所知,CSS 中還沒有簡單的方法實現上述所有要求。
方法
那么有哪些在網頁中添加下划線的方法?
以下是我能想到的方法:
text-decorationborder-bottombox-shadowbackground-image- SVG 濾鏡
- Underline.js (canvas)
text-decoration-*
讓我們逐一分析這些方法的優缺點。
text-decoration
text-decoration 是添加文本下划線最直接的方式。你只需要應用一個單獨的屬性就可以全部搞定。字號較小的話,下划線看起來不錯,但增加字號之后,同樣的下划線就很難看。
See the Pen Underlines 1: text-decoration by John D. Jameson (@johndjameson) on CodePen.
text-decoration 的最大問題是缺乏自定義。它繼承文字的顏色及字號,並且無法通過跨瀏覽器的方式改變樣式。稍后做詳細介紹。
優點
- 易於使用
- 位於文本基線以下
- 默認在 Safari 和 iOS 上會避開下行字母
- 可以換行
- 適用於任意背景
缺點
- 在其它瀏覽器中不能避開下行字母
- 不能改變顏色、粗細或樣式
border-bottom
border-bottom 介於快速及可自定義之間。這種方法使用真正的 CSS border,意味着你可以改變它的顏色、粗細及風格樣式。
以下就是 border-bottom 添加到 inline 元素上的效果。
See the Pen Underlines 2: border-bottom by John D. Jameson (@johndjameson) on CodePen.
最大的問題是下划線到文本的距離——它完全在下行字母以下。可以通過設置元素為 inline-block 以及減少 line-height 解決這個問題,但是文本換行就不行了。這種方法只適合單行文本,不適合多行文本。
See the Pen Underlines 3: border-bottom (inline-block) by John D. Jameson (@johndjameson) on CodePen.
另外,可以使用 text-shadow 覆蓋下行字母附近的下划線,但必須使用與背景色一樣的顏色。這意味着只在純色背景上有效,而不能應用於漸變色或者圖片上。
See the Pen Underlines 4: border-bottom (text-shadow) by John D. Jameson (@johndjameson) on CodePen.
現在,需要四個屬性來定義一個單下划線。相比 text-decoration 的工作量要大。
優點
- 可以使用
text-shadow避開下行字母 - 可以改變顏色、粗細及樣式
- 可以給顏色及粗細添加 transition 和 animate 屬性
- 只要不使用
inline-block,可以換行 - 只要不使用
text-shadow,可以適用於任意背景
缺點
- 下划線距離文本較遠,難以定位
- 需要很多不想關的屬性才能正確顯示
- 使用
text-shadow之后選擇文本顯得粗糙
box-shadow
box-shadow 使用兩個內陰影畫一條下划線:一個用於創建長方形,另一個覆蓋在上面。這意味着該屬性必須在純色背景上使用。
See the Pen Underlines 5: box-shadow by John D. Jameson (@johndjameson) on CodePen.
同樣要使用 text-shadow 的方法偽造下划線與下行字母的間隙。但是如果下划線與文本的顏色不一樣,或者太細,並不會像 text-decoration 那樣不協調。
優點
- 可以位於文本基線以下
- 使用
text-shadow屬性可以避開下行字母 - 可以改變顏色及粗細
- 可以換行
缺點
- 不能改變樣式
- 不能適用於任意背景
background-image
background-image 是最容易滿足我們要求的屬性並且問題較少。思路就是通過 linear-gradient 和 background-position 創建沿着文本水平復制的圖像。
這個方法也要設置 display: inline;
See the Pen Underlines 6: background-image by John D. Jameson (@johndjameson) on CodePen.
下面的方法不必使用 linear-gradient ,你可以用自己的圖片做出酷炫的效果。
See the Pen Underlines 7: background-image (External) by John D. Jameson (@johndjameson) on CodePen.
優點
- 可以位於文本基線以下
- 使用
text-shadow屬性可以避開下行字母 - 可以改變顏色、粗細(允許半個像素)及樣式
- 適用於自定義圖片
- 可以換行
- 只要不使用
text-shadow,可以適用於任意背景
缺點
- 圖片在不同的分辨率、瀏覽器及縮放級別下可能大小不同
SVG filters
我一直在考慮使用 SVG 濾鏡的方法。可以創建一個行內 SVG 濾鏡元素畫一條線,通過擴展文本邊界遮蓋下行字母附近的下划線。然后給濾鏡一個 id ,通過 filter: url(‘#svg-underline’) 在 CSS 中引用它。
濾鏡的優點不需要借助 text-shadow 添加了透明間隙。這意味着可以在任何背景上避開下行字母,包括漸變及圖片背景。這種方法只適用於單行文本,需要注意這一點。
以下是在 Chrome 和 Firefox 中的效果:

在 IE、Edge 和 Safari 上的瀏覽器支持有問題。很難在 CSS 中測試 SVG 濾鏡的支持情況。可以使用 filter 的 @supports 屬性,但是只能檢測引用是否可用,而不能檢測濾鏡本身。我最終的方法是使用一些瀏覽器嗅探檢測,所以也要注意這一點。
優點
- 位於文本基線以下
- 可以避開下行字母
- 允許改變顏色、粗細及樣式
- 適用於任意背景
缺點
- 不允許換行
- 在 IE、Edge 及 Safari 中無效,但是你可以使用
text-decoration。Safari 中的下划線看起來很棒。
Underline.js (Canvas)
Underline.js 很迷人。我覺得最印象深刻的是 Wenting Zhang 使用了 JavaScript 實現以及對細節的關注。如果你還沒有看過 Underline.js 的 tech demo ,一定要停下來看一看。有一個關於它 工作原理 的 9 分鍾的視頻,但是我可以簡單說一下:它是通過 <canvas> 元素添加下划線。這是一種新方法,效果非常好。
盡管 Underline.js 有一個引人注目的名字,但只是一個技術演示。這意味着在修改完善之前還不能用在任何項目中。
這種方法作為概念證明有必要提出來。<canvas> 可以創建漂亮、可交互的下划線,但是需要寫一些 JavaScript 才能正常工作。
text-decoration-* properties
還記得“稍后做詳細介紹”這句話嗎?現在就講到這里了。
text-decoration 自身可以表現的更好,但是必須添加一些實驗性的屬性定制它的外觀:
text-decoration-colortext-decoration-skiptext-decoration-style
不要高興的太早,因為有瀏覽器兼容的問題。
text-decoration-color
text-decoration-color 允許你改變下划線的顏色。這一屬性比預期的瀏覽器支持要好——它可以在 Firefox 以及 Safari (需加前綴)中工作。需要注意的是:如果沒有清除下行字母,Safari 中的下划線會位於文本之上。
Firefox:

Safari:

text-decoration-skip
text-decoration-skip 設置文本下划線是否避開下行字母。

這是一個非標准屬性,只在 Safari 中正常工作,所以要加 -webkit- 前綴。Safari 默認使用該屬性,所以即使沒有設置,下划線也會避開下行字母。
如果你正在使用 Normalize.css ,需要知道當前版本為了瀏覽器之間的一致性而禁用了該屬性。如果你想要這個優秀的下划線樣式,你需要自己設置一下。
text-decoration-style
text-decoration-style 提供了和 border-style 一樣的線條樣式,但是也增加了 wavy 波浪線樣式。
以下是你可以使用的不同屬性值:
dasheddotteddoublesolidwavy
現在, text-decoration-style 只在 Firefox 上有效,以下是截圖:

眼熟嗎?
還缺少什么?
text-decoration-* 屬性比其它添加下划線的 CSS 屬性要方便。但是如果我們回顧一下之前的需求,這個屬性不能改變下划線的粗細及位置。
研究了一下之后,我發現了下面兩個屬性:
text-underline-widthtext-underline-position
這些屬性好像在 CSS 早期的草案中就被提出來了,但是因為缺乏興趣而沒有實施。嘿,不要怪我!
總結
那么添加下划線最好的方法是什么?
對於字號小的文本,我推薦使用 text-decoration 並且樂觀地使用 text-decoration-skip 。這種樣式在大多數瀏覽器中看上去有些乏味,但是因為下划線樣式一直如此,所以用戶不會介意。如果你有足夠的耐心,所有的下划線在以后看上去會很棒,而你不需要修改任何東西。
對於正文部分,可以使用 background-image 方法。這種方法看上去很棒,而且也有相應的 Sass mixins 。如果下划線很細或者與文本的顏色不一樣,可以省略 text-shadow 屬性。
對於單行文本,使用 border-bottom 以及你希望配合使用的其它屬性。
如果想要在漸變或者圖片背景上避開下行字母,嘗試使用 SVG 濾鏡。或者避免使用下划線。
將來,當瀏覽器的支持性更好,答案一定是 text-decoration-* 屬性。
