盤點CSS文本兩端對齊的N種方式
介紹一個你可能見過的文本兩端布局(也可以叫文本均等分布),如下:
說難不難,說簡單也不簡單。這里盤點了多種實現該布局的方式,看看你都知道哪些吧~
一、加空格
很多人從直覺上會加空格,從視覺上達到文本兩端對齊的效果,也是比較符合直覺的,例如像這樣。
<ul class="demo">
<li>技 術 部</li>
<li>體驗設計部</li>
<li>行 政 部</li>
</ul>
但是直接加空格沒啥效果,因為默認情況下空格會合并。
如果不想合并,可以用white-space來改變這種行為。
li{
white-space: pre;
}
這樣,無論敲多少個空格,都會原封不動保留下來。
這樣就得到了一種“近似”的兩端對齊效果。
除了用white-space改變以外,還可以用 來輸入“實體”空格。
<ul>
<li>技 術 部</li>
<li>體驗設計部</li>
<li>行 政 部</li>
</ul>
也能得到類似的效果。
二、加標簽
上面的實現其實只是“近似”的,并不能完美對齊,如下:
很明顯還是差了點。
不過可以換一種思路,因為空格并不能很好的描述一個中文字符的寬度,無論多少個空格,總是有點差距的,所以這里可以手動加一個空標簽。
<ul>
<li>技<span></span>術<span></span>部</li>
<li>體驗設計部</li>
<li>行<span></span>政<span></span>部</li>
</ul>
然后,我們給這些標簽設置一個字符的寬度就好了。
li span{
width: 1em;
}
這樣就能完美對齊了。
前面這兩種方式其實都不大推薦,局限性太大,需要手動去補全剩余空間,如果字數不一樣,又得手動重新計算了。
下面介紹幾個實際更推薦的方式。
三、justify-content: space-between
很多同學可能都會想到這種方式,畢竟現在flex布局實在太普遍了,不過這只適合具體的元素,不適合純文本,所以需要改造一下,將所有文本拆分成單獨的標簽,類似這樣。
<ul>
<li><span>技</span><span>術</span><span>部</span></li>
<li><span>體</span><span>驗</span><span>設</span><span>計</span><span>部</span></li>
<li><span>行</span><span>政</span><span>部</span></li>
</ul>
這么多標簽,手寫太麻煩了,可以在 JS自動生成。
txt.split('').map(el => `<span>${el}</span>`).join('')
然后直接利用flex布局的兩端對齊就可以了。
li{
display: flex;
justify-content: space-between;
}
效果如下:
而且這種適應性更好,改變外層寬度,也能做到兩端對齊。
四、flex:1
利用flex布局,還可以用另一種方式來實現。
我們可以在每個字符中間都添加一個空標簽,然后讓這些空標簽自動分配剩余空間,這樣不就實現文本兩端對齊了嗎?
<ul>
<li>技<span></span>術<span></span>部</li>
<li>體<span></span>驗<span></span>設<span></span>計<span></span>部</li>
<li>行<span></span>政<span></span>部</li>
</ul>
同樣可以用JS來生成,相比上一種方式更容易。
txt.split('').join('<span></span>')
然后設置flex:1。
li{
display: flex;
}
li span{
flex: 1;
}
效果如下:
這兩種方式適應性更好,基本可以在實際生產使用了,不過需要對HTML進行改造,稍微麻煩點,而且看著不夠干凈,畢竟都是空標簽,沒有實際價值。
下面再介紹兩個不需要改變HTML的方式。
五、text-align: justify
文本對齊方式中天然就有一個兩端對齊的方式,叫做justify,但是這種方式不包括最后一行。
由于不支持最后一行,所以對于單行文本,這種對齊方式自然也就失效了。
既然不支持單行文本,我們可以手動讓“單行”變成“多行”,具體做法其實也很簡單,用一個偽元素,強制換行就可以了,具體實現如下:
li::after{
content: '';
display: inline-block;
width: 100%;
}
這樣在設置text-align: justify時,原本的第一行就不再是最后一行了,自然也就生效了。
li{
text-align: justify;
}
效果如下:
不過由于換行的關系,導致整體高度要比以前高出一部分,所以這種方式需要手動限制一個高度。
li{
text-align: justify;
height: 24px;
line-height: 24px;
}
這樣就完美實現了。
另外,在 MDN文檔上還看到這樣一個屬性值justify-all,可以滿足我們的需求。
不過現在還沒有任何瀏覽器支持。
六、text-align-last: justify
CSS中還有一個專門適用于最后一行文本的對齊方式,叫做text-align-last,剛好可以滿足這個場景。所以我們可以在HTML不做任何修改的情況下,設置最后一行文本兩端對齊就可以了。
li{
text-align-last: justify;
}
效果如下:
這應該是最完美的方式了,不過兼容性稍微差點,又是Safari脫了后腿。
七、SVG 中的lengthAdjust
除了以上CSS的各種方式外,SVG中也可以實現類似這樣的文本兩端對齊,需要用到lengthAdjust屬性。
這個屬性有兩個值,一個是spacing,表示剩余空間自動填充,另一個是spacingAndGlyphs,表示會讓字符自動壓縮或拉伸來適配整個文本長度(textLength)。
<svg width="300" height="150" xmlns="http://www.w3.org/2000/svg">
<g font-face="sans-serif">
<text x="0" y="20" textLength="300" lengthAdjust="spacing">
Stretched using spacing only.
</text>
<text x="0" y="50" textLength="300" lengthAdjust="spacingAndGlyphs">
Stretched using spacing and glyphs.
</text>
<text x="0" y="80" textLength="100" lengthAdjust="spacing">
Shrunk using spacing only.
</text>
<text x="0" y="110" textLength="100" lengthAdjust="spacingAndGlyphs">
Shrunk using spacing and glyphs.
</text>
</g>
</svg>
效果如下:
我們也可以用這種對齊方式來實現我們想要的效果。
八、總結和說明
以上共介紹了7種方式來實現文本兩端對齊,完整 demo 可以查看以下鏈接。
- CSS text justify (juejin.cn)[1]
除此之外,你還知道哪些方式呢?歡迎留言討論,下面總結一下。
- 加空格的方式比較符合直覺,但是只能達到近似的對齊效果。
- 加標簽可以實現精準對齊,但是是純手動,而且和文字字數也有關系。
- flex布局的兩端對齊需要給每個文字套上一個標簽。
- 也可以在每個文字之間加上一個空標簽,設置自動填充。
- text-align: justify可以實現文本兩端對齊,但是不包括最后一行。
- 借助偽元素換行,可以手動將原本的最后一行變成非最后一行。
- text-align-last: justify可以最完美的實現這個效果,不過兼容性欠佳。
- SVG中的lengthAdjust也能實現類似的對齊效果。
資訊一下,如果面試(5年內)出這樣一道題,你們覺得難嗎?
[1]CSS text justify (juejin.cn): https://code.juejin.cn/pen/7399192945481482290