歡迎關注我的公眾號:前端偵探
最近有同事問我這樣一個問題:需要繪製一個自適應文字的寫作網格線,設計稿是這樣的
其實就是一行行虛線,要求如下
- 虛線的縱向間隔要跟隨行高自適應,確保文字在每一欄虛線上
- 虛線後面的背景是動態的,可以是純色,可以是漸變,也可以是圖片
繪製這樣的虛線,看似容易,其實暗藏玄機,下面一起看看有哪些實現方式吧
一、純色背景下的虛線
首先來看這種簡單情況,大可以透過兩層漸變覆蓋的方式實現。
假設文字行高是2
,先繪製水平方向的
body{
background: linear-gradient(#666 1px,transparent 0) 0 -1px/100% 2em;
}
注意,這裡的背景尺寸是100% 2em
,高度跟隨文字行高,所以高度是2em
,效果如下
然後,繪製縱向的實線,蓋在上面,為了區分,先用一個淺紅色來代替
body{
background: linear-gradient(to right, #ffdbdb 4px,transparent 0) 0 -4px/8px 100%, /*垂直*/
linear-gradient(#666 1px,transparent 0) 0 -1px/100% 2em; /*水平*/
}
這樣就繪製了一個垂直平鋪,間隔為4px
的虛線,效果如下
應該比較好理解吧,就是兩個方向上的漸變疊加
然後,將這個紅色改成和底色相同的顏色就行了,比如這裡是白色
body{
background: linear-gradient(to right, #fff 4px,transparent 0) 0 -4px/8px 100%, /*垂直*/
linear-gradient(#666 1px,transparent 0) 0 -1px/100% 2em; /*水平*/
}
這樣就實現了純色下的虛線網格,效果如下
二、漸變背景下的虛線
如果不是純色,而是漸變的呢?假設有一個這樣的背景
如果直接用前面的方式,可能就變成了這樣
白色直接把背後的漸變背景也覆蓋了。
那如何解決這個問題呢?
像這種疊加混合的情況一般都會想到混合模式,沒錯,這裡也可以透過混合模式簡單處理。要用混合模式,必須要讓這兩層背景處於不同的容器中,然後使用mix-blend-mode
html{
background: linear-gradient(45deg, #f5ffc0, #fff);
}
body{
font-size: 20px;
background: linear-gradient(to right, #fff 4px,transparent 0) 0 -4px/8px 100%, linear-gradient(#666 1px,transparent 0) 0 -1px/100% 2em;
mix-blend-mode: darken;
}
這裡使用了混合模式中的darken
,這種模式可以去除白色部分,保留其他,效果如下
完整程式碼可以檢視以下任意連結
三、透過錐形漸變繪製
下面再介紹一個比較硬核的繪製方式:錐形漸變(conic-gradient)
為什麼說比較硬核呢?因為這種方式繪製出來的圖形就是完完全全的虛線,也沒有混合模式的諸多限制。
首先我們從圖形上分析,找到最小的重複單元,如下
找到了,就是這個,其實就是這個位於左上角的矩形,那麼,如何透過錐形漸變來繪製呢?
注意: 有同學可能會奇怪,這樣一個矩形線性漸變不是可以很輕鬆的實現嗎?確實可以,但是隻能實現一個,無法平鋪
看著好像不沾邊,下面帶你一步步演變
首先是最原始的語法
div{
background: conic-gradient(#666, transparent);
}
這是一個從透明到灰色的漸變,效果如下
這才是錐形漸變的樣子!
然後,我們可以將漸變的分界線調整一下
div{
background: conic-gradient(#666 90deg, transparent 0deg);
}
這樣就變成了一個邊界分明的正方形
然後改變起始角度,透過from
關鍵詞
div{
background: conic-gradient(from 270deg, #666 90deg, transparent 0deg);
}
這樣起始角度就會從270deg
的地方開始,如下
接著,改變中心點的位置,預設是水平垂直居中的,我們要改到左上角,需要用到at
關鍵詞
div{
background: conic-gradient(from 270deg at 40px 10px, #666 90deg, transparent 0deg);
}
這裡改成了左上角40px,10px
的地方,如下
最後,改變背景的尺寸,預設是寬高100%
的,我們要改成實際需要的大小
div{
background: conic-gradient(from 270deg at 40px 10px, #666 90deg, transparent 0deg);
background-size: 80px 90px;
}
這樣就會自動平鋪展開,如下
原理就是這樣,實際上的虛線比較小,應該是4px 1px
,所以實際應用應該是這樣
div{
background: conic-gradient(from 270deg at 4px 1px, #666 90deg, transparent 0deg);
background-size: 8px 2em;
}
效果如下
完整程式碼可以檢視以下任意連結
四、動態SVG背景繪製
最後再來介紹一個實現起來最容易的方式,就是“切圖”。
但是,這種“切圖”不同於一般的切圖,因為這個尺寸是動態的,要跟隨文字的行高變化而變化,所以需要採取一定的“手段”。
首先在繪圖軟體中繪製這樣一個圖形,例如下面是figma
中繪製的
外面的寬高無所謂,隨便設定。可以得到這樣一段SVG
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="10" height="10" fill="none"/>
<rect width="5" height="1" fill="#D9D9D9"/>
</svg>
然後,我們將這個svg
轉換成內聯 CSS
格式
推薦張鑫旭老師的線上轉換工具:SVG線上壓縮合並工具
直接用到背景上
body{
font-size: 20px;
background: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0h10v10H0z'/%3E%3Cpath fill='%23D9D9D9' d='M0 0h5v1H0z'/%3E%3C/svg%3E") 0 0/10px 2em;
}
效果如下
為啥這裡的虛線都錯位了呢?
這也是 SVG
不同於常規圖片的一點,在外部背景尺寸超過viewbox
尺寸後,SVG
畫布會整體縮放,但是具體的元素並不會,具體表現是這樣的
那麼,有沒有辦法在畫布縮放的時候,裡面的元素仍然位於左上角呢?就像這樣
當然也是可以的,只需要將viewbox
改為0 0 100% 100%
就行了,或者乾脆刪除(預設就是100%),SVG
的寬高也要改成100%
,如下
<svg width="100%" height="100%" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="10" height="10" fill="none"/>
<rect width="5" height="1" fill="#D9D9D9"/>
</svg>
這樣一來,不管背景尺寸如何變化,內部的虛線位置都不受影響,效果如下
完整程式碼可以檢視以下任意連結
除了上面這種方式,還可以換一種思路,讓預設的虛線是居中的,這樣在放大後也是居中的,如下
這樣在不改變viewbox
的情況下也能實現相同的效果,有興趣的小夥伴可以下去試一試
五、總結一下優缺點
以上共介紹了 3 種完全不同的繪製虛線的方式,原理各不相同,也有各自的優缺點,下面總結一下
CSS 漸變混合模式的優點在於實現思路比較簡單,很容易想到,純色背景優先推薦,缺點是混合模式有一些侷限性,比如在黑色背景下可能需要換一種模式了
CSS 錐形漸變的優點在於程式碼實現簡單,不受結構限制,缺點是有點不好理解,還有就是相容性稍微差一些
SVG 自適應背景的優點在於使用簡單,基本等同於“切圖”,缺點是需要掌握 SVG 的特性,而且無法直接透過 CSS 改變顏色,只能換圖
綜合來講,如果相容性沒有要求,首推第2種方式,其次是 SVG 方式,最後才是混合模式
這幾種方式你學會了嗎?最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤
歡迎關注我的公眾號:前端偵探