ant design のアバターコンポーネントには、アバター内の文字数に応じて文字サイズが自動的にスケーリングされる効果があります。
これは Ant Design の効果で、とても素晴らしいです。
現在、CSS のコンテナクエリユニット(Chrome 105 + サポート)を使用することで、この効果を CSS だけで簡単に実現できます。
皆さんが比較的簡単にテストできるように、ここに HTML コードを示しますので、直接コピーしてテストしてください。 ここでは CDN 上の vue2 と UnoCSS のランタイムを使用していますが、これはデモを書くための便利さのためであり、原理はこの 2 つに依存していません。この 2 つの依存関係がなくても、どこでも使用できます。
<!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>アバター内文字自適応デモ</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', '英語']
}
}
})
</script>
</body>
</html>