ant design 的頭像組件中有一個效果就是會根據頭像內文字的數量自動縮放文字大小
這是 Ant Design 的效果,很棒
現在我們有了 CSS 的容器查詢單位(Chrome 105 + 支持)之後,可以輕鬆的只使用 CSS 實現這個效果
為了大家比較方便的測試,這裡給出 HTML 代碼,方便直接複製拿去測試, 這裡使用了 CDN 上的 vue2 和 UnoCSS 的運行時,這只是方便寫 Demo,原理並不依賴這兩個,沒有這兩個依賴你依舊可以將它用在任何地方。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/@unocss/runtime"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<title>頭像內文字自適應Demo</title>
<style>
.avator {
/* flex居中 */
display: flex;
align-items: center;
justify-content: center;
/* 寬高 */
width: 50px;
height: 50px;
/* 圓角顏色 */
border-radius: 8px;
background: #eaeaea;
/* 不允許文字換行 */
white-space: nowrap;
}
.avator-inner {
position: relative;
}
.avator-inner::before {
content: attr(alt);
visibility: hidden;
font-size: 40px;
}
/* 利用定位,將這個盒子設置的和外面的.avator-inner設置成一樣大 */
/* 也就是avator-inner::before由文字撐開,avator-inner和自己的before一樣大,avator-container利用定位和avator-inner一樣大 */
.avator-container {
position: absolute;
inset: 0;
container-type: inline-size;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.avator-container span {
/* 用cqw做到與寬度成反比,也就是文字越多,avator-inner的before越大,這裡的font-size也就越小 */
font-size: calc(24px - 10cqw);
/* 因為avator-container是定位在中間的,所以和邊界沒有距離,這加padding寫與邊界的距離 */
display: inline-block;
padding: 0 2px;
overflow: hidden;
max-width: 40px;
text-overflow: ellipsis;
}
</style>
</head>
<body>
<div id="app" class="min-h-screen">
<main class="grid place-content-center gap-16px">
<!-- 創建一份一模一樣的文本,讓外層容器(A)寬度由內部文本決定,然後將容器盒子(B)的寬度設置成和(A)一樣 -->
<!-- 通過這樣完成容器查詢 -->
<div class="avator" v-for="(item, index) in arr" :key="index">
<!-- 外層容器的文本通過偽元素生成,文字會把avator-inner::before撐開 -->
<div class="avator-inner" :alt="item">
<div class="avator-container">
<span>{{item}}</span>
</div>
</div>
</div>
</main>
</div>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
arr: ['我', '名字', '三個字', '有四個字', 'A', 'AB', 'ABC', 'ABCD', 'English']
}
}
})
</script>
</body>
</html>