在 web 中經常會見到這樣的設計,很多 UI 元件庫也稱之為 Avator 元件,也就是頭像的意思,當頭像未設定時,會顯示名稱的首字元充當預設頭像,如下所示:
實際效果可以檢視CSS avator(codepen.io),那麼如何通過 CSS 實現這一效果呢?
一、圖片載入失敗時的佔位
現代瀏覽器(Chrome、Firefox) img 標籤都支援偽元素了,不過只有當圖片載入失敗的時候才能看到
<img class="avator" src="https://tva1.sinaimg.cn/large/008i3skNgy1grgo8qjty1j30e80e8aad.jpg">
<img class="avator" src="">
.avator::before{
content: '我是偽元素';
color: red;
}
效果如下
有了偽元素,要做一些事情就很方便了,比如將預設的“佔點陣圖”擠出去,設定偽元素高度為100%就行了,同時設定超出隱藏
.avator{
width: 40px;
height: 40px;
overflow: hidden; /*記得超出隱藏*/
}
.avator::before{
content: '';
display: flex;
background: bisque;
height: 100%;
}
效果如下
二、alt 首字元佔位
一般在使用 img 標籤時都推薦加上 alt 屬性,用來描述圖片資訊,也非常符合語義化。
<img class="avator" src="" alt="xboxyan">
然後在圖片載入失敗時,可以通過 attr
獲取到完整的 alt 資訊
.avator::before{
content: attr(alt); /* 獲取 alt 屬性 */
color: rgb(250, 84, 28);
}
為了方便演示,這裡暫時把超出隱藏開啟
那麼,如何只顯示第一個字元呢?
嘗試了一下::first-letter
,發現不起作用,偽元素裡面不能再用偽元素了
.avator::before::first-letter{
/*無效*/
}
需要換一種思路,比如增加字元間距,讓其餘字元都處於容器之外
.avator::before{
/**/
letter-spacing: 40px;
}
效果如下
這樣一來,首字元“x”確實處於視線之中了。
不過新問題也來了,如何讓首字元水平垂直居中呢?
三、首字元水平垂直居中
垂直居中比較好辦。設定行高就行了
.avator::before{
/**/
line-height: 40px;
}
水平居中貌似有些棘手,不過發揮你的奇思妙想,問題還是可以解決的!
首先,由於寬度限制,可以把所有的字元強制換行,保證每個字元都處於單獨一行,首行也不另外
.avator::before{
/**/
word-break: break-all; /*換行*/
}
前面我們加了一個字元間距,但是字元間距是跟隨在字元後面的,所以第一個字元的前面是沒有間距的。為了保持首行左右平衡,所以手動加上同樣的間距,這裡採用text-indent
來實現
.avator::before{
/**/
text-indent: 40px; /*首行縮排*/
}
這樣對於首行來說,其實是左右邊距是一樣的。接下來,通過 flex 佈局居中就可以了
.avator::before{
/**/
display: flex;
justify-content: center; /*水平居中*/
}
對於英文字母來說,可能需要轉成大寫
.avator::before{
/**/
text-transform: capitalize; /*首字母大寫*/
}
然後超出隱藏看看效果吧
四、特殊符號的影響
後來測試中,發現了另外一個問題,當 alt 中有一些特殊標點符號時,首字元會消失不見
<img class="avator" src="" alt="xboxyan(測試)">
開啟隱藏其實是這樣的
是不是看著一團糟?其實就是一些閉尾標點惹的禍!比如這裡的(
,預設情況下是不允許出現在一行的末尾的,所以強制換到了下一行,導致整個佈局錯亂。為了解決這個問題,可以使用一個比較冷門的 CSS 屬性 line-break - CSS(層疊樣式表) | MDN (mozilla.org) 來解決,有興趣的可以參考張鑫旭的這篇文章:CSS line-break屬性與中文標點換行
.avator::before{
/**/
line-break: anywhere; /*任意地方都換行*/
}
這下就沒問題了,都是整整齊齊的換行~
下面整理一下,附上完整程式碼
<ul class="list">
<li class="item">
<img class="avator" src="https://tva1.sinaimg.cn/large/008i3skNgy1grgo8qjty1j30e80e8aad.jpg" alt="xboxyan">
xboxyan
</li>
<li class="item">
<img class="avator" src="" alt="xboxyan">
xboxyan
</li>
<li class="item">
<img class="avator" src="" alt="前端偵探">
前端偵探
</li>
<li class="item">
<img class="avator" src="" alt="體驗設計部">
體驗設計部
</li>
</ul>
.list{
list-style: none;
padding: 0;
}
.avator{
width: 40px;
height: 40px;
border-radius: 8px;
overflow: hidden;
background: bisque;
}
.avator::before{
content: attr(alt);
display: flex;
width: 100%;
height: 100%;
background-color: bisque;
text-transform: uppercase;
line-height: 40px;
letter-spacing: 40px;
text-indent: 40px;
justify-content: center;
text-align: center;
/* word-break: break-all; */
line-break: anywhere;
color: rgb(250, 84, 28);
}
.item{
display: flex;
align-items: center;
gap: 15px;
height: 64px;
font-size: 18px;
}
效果如文章開頭所示,有需要的可以直接用起來了
或者訪問線上連結 CSS avator(codepen.io) 或者 CSS avator (juejin.cn)
五、總結一下
以上就是本文的全部內容了,非常簡單實用的一個小功能,下面簡單總結一下
- 現代瀏覽器支援 img 偽元素了,並且只有在資源載入失敗時才可用,利用這一點可以設定圖片佔位符
- 偽元素通過 attr 屬性可以獲取 img 標籤屬性,推薦使用 alt
- 偽元素不能再使用偽類了
- 增加字元的行間距可以在可視範圍內僅看到一個字元
- 垂直居中可以通過行高來實現
- 水平居中可以通過首行縮排 和 flex 居中實現
- 部分特殊符號由於“避尾”或者“避首”特性,導致換行佈局錯亂
- line-break 可以打破以上規則
唯一的遺憾就是 Safari 不支援圖片偽元素,不過沒關係,不影響功能,也可以學到一些你可能不知道的小技巧。最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤