HN 日本語サマリー

← 一覧へ戻る
Web開発

アイコンとラベルのより良い配置

Better Icon and Label Alignment (ishadeed.com)

16 pointsby eustoria2 コメント

要約

リスト内のアイコンとテキストの配置は、特にテキストが複数行に折り返される場合に問題となることがあります。この記事では、アイコンがHTML要素として、または疑似要素として追加される場合の、この配置問題を解決するためのCSSテクニックを解説します。`lh`ユニットや`aspect-ratio`などのモダンなCSS機能を用いた、柔軟でロバストな配置方法を紹介しています。

全文翻訳

Better Icon and Label Alignment

しばしば見落とされたり、見過ごされたりする一般的なデザインパターンがあります。それは、各項目にアイコンを持つリストです。テキストが1行の場合はアイコンは中央揃えになりますが、テキストが複数行になると、アイコンは依然として中央揃えになりますが、奇妙に見えます。

例を挙げます:

[画像: アイコンと複数行のテキストラベルの配置例]

この記事では、HTMLに基づいた私が使用する2つの解決策を示します:

  • アイコンはHTML要素(例: <svg> または <img>)である
  • アイコンは疑似要素として背景画像で追加されている

マークアップ内のアイコン

この場合、アイコンとコンテンツを含むコンテナがあります。通常、flexboxを使用します。以下のような構造です:

<ul class="list">
  <li class="list-item">
    <svg class="icon"></svg>
    <span class="label">How to align an icon to a label.</span>
  </li>
  <!-- Other items -->
</ul>
.list-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

デフォルトでは、これは問題なく表示されます。以下がその例です:

List385px

Highlight

  • How to align an icon to a label.

しかし、リストの幅が狭くなり、テキストが折り返されると、アイコンは中央揃えになります。これは望ましい動作ではありません。

List250px

Highlight

  • How to align an icon to a label.

テキストが折り返されたときに、アイコンを垂直方向に揃えたままにするにはどうすればよいでしょうか?まず、基本に戻ります。align-items: centerの代わりに、startを値として使用します。

.list-item {
  display: flex;
  align-items: start;
  gap: 0.5rem;
}

しかし、これはさらに大きな配置の問題を引き起こしました。ハイライトされた領域は行の高さです。テキスト要素の高さには、フォント自体に由来する上部と下部の空白があります。align-items: startが適用されると、アイコンはコンテナの上部に配置されます。

List250px

Highlight

  • How to align an icon to a label.

アイコンを下にずらして、最初の行に揃えるのはどうでしょうか?

List250px

Highlight

  • How to align an icon to a label.
.list-item {
  display: flex;
  align-items: start;
  gap: 0.5rem;
}

.icon {
  transform: translateY(3px);
}

これでうまくいきました。これを限界まで試して、問題が持続するか確認しましょう!そのために、以下のいずれかまたは複数を変更するようにデモを構築しました:

  • リストアイテムのフォントサイズ
  • アイコンのサイズ
  • リストコンテナの幅

試してみて、アイコンがどのように配置がずれるかを確認してください。

Icon20px

Font size25px

List250px

Highlight

  • How to align an icon to a label.

transformに固定値を指定しても、アイコンサイズ、フォントサイズ、またはコンテナ幅が変更されると機能しなくなります。

解決策: lhユニットの使用

行の高さを取得でき、アイコンのサイズがわかっていれば、それらに対するオフセットを相対的に計算できます。さらに詳しく知りたい場合は、ブログで行の高さユニットについて書きました。

.icon {
  /* --icon-size はJSで定義されます */
  --size: var(--icon-size);
  --offset: calc((1lh - var(--size)) / 2);
  transform: translateY(var(--offset));
}

Icon20px

Font size25px

List250px

Highlight

  • How to align an icon to a label.

この解決策では、3つの値のいずれかを変更しても、配置は正しく機能します。場合によっては、オフセットが負になることもあります。以下はその例です:

Icon24px

Font size17px

List250px

Highlight

  • How to align an icon to a label.

疑似要素としてのアイコン

時には、アイコンをHTML要素として追加する必要がなく、疑似要素を使用することもあります。

基本的なCSSは以下の通りです:

.list-item {
  display: flex;
  gap: 0.5rem;
}

.list-item::before {
  content: "";
  --size: var(--icon-size);
  width: var(--size);
  height: var(--size);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23222' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
}

一見すると、問題なく表示されているように見えますね?フォントサイズを少し大きくしてみてください。

Icon24px

Font size17px

List264px

Highlight

  • How to align an icon to a label.

アイコンが切り取られていることに気づきましたか?これは、背景サイズを制限する必要があるためです。

.list-item {
  display: flex;
  gap: 0.5rem;
}

.list-item::before {
  content: "";
  --size: var(--icon-size);
  width: var(--size);
  height: var(--size);
  background-image: url("data:image/svg+xml,%3Csvg .... ");
  background-size: contain;
  background-repeat: no-repeat;
}

Icon24px

Font size17px

List264px

Highlight

  • How to align an icon to a label.

フォントサイズを大きくしてみてください。アイコンの幅が縮小していることに気づきましたか?これは、デフォルトではflexアイテムが縮小するためです。これを上書きする必要があります。

.list-item {
  display: flex;
  gap: 0.5rem;
}

.list-item::before {
  content: "";
  --size: var(--icon-size);
  flex-shrink: 0;
  width: var(--size);
  height: var(--size);
  background-image: url("data:image/svg+xml,%3Csvg .... ");
  background-size: contain;
  background-repeat: no-repeat;
}

Icon24px

Font size17px

List264px

Highlight

  • How to align an icon to a label.

また…ラベルのフォントサイズを大きくしてみてください。アイコンサイズはそのままです。次のステップは、アイコンサイズ、フォントサイズ、コンテナ幅などの要因が変化する場合のセンタリングを処理することです。

解決策

現在、リストアイテムはflexboxコンテナであり、デフォルトではアイテムは(垂直方向に)ストレッチします。なぜこのケースでアイコンがストレッチしないのでしょうか?それは、固定の高さを設定したためです。

heightプロパティをautoに設定しました。

.list-item {
  display: flex;
  gap: 0.5rem;
}

.list-item::before {
  content: "";
  --size: var(--icon-size);
  flex-shrink: 0;
  width: var(--size);
  height: auto;
  background-image: url("data:image/svg+xml,%3Csvg .... ");
  background-size: contain;
  background-repeat: no-repeat;
}

Icon24px

Font size17px

List264px

Highlight

  • How to align an icon to a label.

これで少しトリッキーになりました。フォントサイズを大きくすると、アイコンの幅は正方形に近いままになります。小さくすると、余白のある長方形のようになります。

見てみましょう:

Icon24px

Font size14px

List264px

Highlight

  • How to align an icon to a label.

それを避けるために、アスペクト比を強制的に正方形にする必要があります。

.list-item {
  display: flex;
  gap: 0.5rem;
}

.list-item::before {
  content: "";
  --size: var(--icon-size);
  flex-shrink: 0;
  aspect-ratio: 1;
  width: var(--size);
  height: auto;
  background-image: url("data:image/svg+xml,%3Csvg .... ");
  background-size: contain;
  background-repeat: no-repeat;
}

Icon24px

Font size14px

List264px

Highlight

  • How to align an icon to a label.

これで、前述と同じテクニックを使用して、疑似要素を数ピクセルオフセットします。

.list-item {
  display: flex;
  gap: 0.5rem;
}

.list-item::before {
  content: "";
  --size: var(--icon-size);
  --offset: calc((1lh - var(--size)) / 2);
  flex-shrink: 0;
  aspect-ratio: 1;
  width: var(--size);
  height: auto;
  background-image: url("data:image/svg+xml,%3Csvg .... ");
  background-size: contain;
  background-repeat: no-repeat;
  transform: translateY(var(--offset));
}

Icon24px

Font size14px

List264px

Highlight

  • How to align an icon to a label.

アイコンは現在中央揃えになっています。ここで使用されているものは興味深いですね:

  • flexbox
  • aspect-ratio
  • lhユニット
  • calc()
  • height: auto

Outro

これで終わりです。プロジェクトで問題を解決し、それを共有したかったのです。何か新しいことを学んでいただけたら幸いです。

お読みいただきありがとうございました。

The Layout Maestro

レイアウトの構築は、特にCSSレイアウトのコアメンタルモデルを知らない場合、困難な作業となることがあります。もう心配する必要はありません。インタラクティブなCSSレイアウトコースをリリースし、それをThe Layout Maestroと名付けました。

[画像: The Layout Maestroコースのランディングページのスクリーンショット]

The Layout Maestroコースをチェックして、CSSレイアウトスキルをレベルアップしましょう。