在網頁中新增下劃線
有很多種新增下劃線樣式的方法。可能你還記得《 Crafting link underlines on Medium 》這篇文章。Medium 並沒有嘗試特殊的方法,只是想建立一個漂亮的看起來正常的下劃線。
一條纖細的黑色下劃線並且與下行字母有間隙——引自 Marcin Wichary 的《 Crafting link underlines on Medium 》
這是基本的下劃線樣式,但是尺寸適中並且避開了下行字母。比大多數瀏覽器的預設效果要好。事實證明 Medium 為了獲得這種樣式遇到了很多麻煩。兩年過去了,新增一個好看的下劃線樣式仍然很困難。
目標
使用 text-decoration: underline
新增下劃線有什麼問題嗎?如果我們討論一個理想的場景,下劃線應該符合以下特點:
- 位於文字基線以下
- 避開下行字母
- 可以改變顏色、粗細及樣式
- 適用於文字換行的情況
- 適用於任意背景
我認為這些要求非常合理,但是據我所知,CSS 中還沒有簡單的方法實現上述所有要求。
方法
那麼有哪些在網頁中新增下劃線的方法?
以下是我能想到的方法:
text-decoration
border-bottom
box-shadow
background-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
新增到行內元素上的效果。
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
新增了透明間隙。這意味著可以在任何背景上避開下行字母,包括漸變及圖片背景。這種方法只適用於單行文字,需要注意這一點。
See the Pen Underlines 8: SVG Filters by John D. Jameson (@johndjameson) on CodePen.
以下是在 Chrome 和 Firefox 中的效果:
在 IE、Edge 和 Safari 上的瀏覽器支援有問題。很難在 CSS 中測試 SVG 濾鏡的支援情況。可以使用 filter 的 @support 屬性,但是隻能檢測引用是否可用,而不能檢測濾鏡本身。我最終的方法是使用一些瀏覽器嗅探檢測,所以也要注意這一點。
優點
- 位於文字基線以下
- 可以避開下行字母
- 允許改變顏色、粗細及樣式
- 適用於任意背景
缺點
- 不允許換行
- 在 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-* 屬性
還記得“稍後做詳細介紹”這句話嗎?現在就講到這裡了。
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.css ,需要知道當前版本為了瀏覽器之間的一致性而禁用了該屬性。如果你想要這個優秀的下劃線樣式,你需要自己設定一下。
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 mixins 。如果下劃線很細或者與文字的顏色不一樣,可以省略 text-shadow
屬性。
對於單行文字,使用 border-bottom
以及你希望配合使用的其它屬性。
如果想要在漸變或者圖片背景上避開下行字母,嘗試使用 SVG 濾鏡。或者避免使用下劃線。
將來,當瀏覽器的支援性更好,答案一定是 text-decoration-*
屬性。
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!