アイコンのサイズは px ではなく 1cap で指定して文字に追従させる
インラインのアイコンを width: 1cap; height: 1cap; にすると、隣の文字の大文字の高さと同じ大きさになり、フォントサイズを変えてもアイコンが自動で追従する。
どんな時に使う?
- ボタンやラベルの「アイコン+テキスト」で、文字サイズごとにアイコンの px を調整し直すのが面倒な時
1emで指定するとアイコンが文字より一回り大きく見えたり、上下中央がずれて見えたりする時- 同じコンポーネントを小・中・大サイズで使い回したい時
コード
css
.label {
display: flex;
align-items: baseline; /* アイコンの下端を文字のベースラインに揃える */
gap: 0.4em;
}
.label svg {
width: 1cap; /* 大文字の高さ = アイコンの高さ */
height: 1cap;
flex-shrink: 0;
}html
<button class="label">
<svg viewBox="0 0 16 16" aria-hidden="true">…</svg>
Download
</button>capは「いま使っているフォントの大文字の高さ(キャップハイト)」を 1 とする単位。em(フォントサイズ全体)より小さく、ラテン文字の見た目の高さにぴったり合う。- SVG のような置換要素はベースラインが下端になるので、
align-items: baselineと組み合わせると「アイコンの下端が文字のベースライン、上端が大文字の上端」に揃い、目で見た中央がずれにくい。 .labelのfont-sizeを変えるだけで、アイコンも同じ比率で大きく・小さくなる。
注意点・対応状況
cap単位は Chrome 118+、Firefox 97+、Safari 17.2+ で使える。古いブラウザ向けにはwidth: 0.7em; width: 1cap;のように先にフォールバックを書いておく。- 日本語だけの文字列では大文字が無いので、キャップハイトはフォントの情報(無ければ近似値)から決まる。和文の見た目に合わせたい場合は
1emや1ic(全角文字の幅)の方が合うこともある。 - 元の投稿は SVG 側のコードの途中で切れているため、上のコードは投稿の趣旨(1cap でサイズ指定し、baseline で揃える)から組み立て直したもの。
- 文字の上下の余白そのものを削りたい場合は text-box で文字の上下の余白を削り、見た目どおりの padding にする の
text-box-edge: cap alphabeticも併せて使える。 - アイコンを
maskで描く方法は アイコンは SVG コンポーネントではなく CSS の mask で(Icons in Pure CSS)、押せる範囲を広げる方法は アイコンより大きいヒットエリアを ::after で確保する を参照。