SMART

CSSの単位: lhでリストマーカーを調整する方法

CSSにはさまざまな単位があります。
em、rem、%、vw、vhなどなど。

今回注目している単位はlh(エルエイチ)です。
line-heightの略ですね。lhは1行分の長さになります。
このlh単位を使用して独自のリストマーカーの位置調整をスマートにコーディングしましょう!

オリジナルリストマーカーの位置調整

オリジナルのリストマーカー、作ってますか?作っていますよね。デザイナーさんが作成したデザインカンプをコーディングで実現していく中で色や形さまざまなリストデザインがあることでしょう。

でも、リストの1行目にちょうどいい配置にするのってちょっと面倒だったりしません?私はマーカーは基本的にemの単位を使ってサイズ調整をしています。
理由はフォントサイズに応じてマーカーのサイズも変わるから。
ただし、位置はずれたりしますよね。特に行間が変化するとズレに対応できないんです。

以前までのコードは以下のような感じです。
シンプルにピンクの丸マーカーを作成しました

<ul class="list">
  <li>リストスタイル</li>
  <li>リストスタイル</li>
  <li>リストスタイル</li>
</ul>
// htmlタグのリセット
ul,li {
  margin:0;
  padding:0;
  list-style:none;
}

.list {
  > li {
    padding-left: 1em;
    line-height: 1.5;
    font-size: 20px;
    color: #333;
    position: relative;
    &::before {
      content: "";
      width: 0.6em;  // font-sizeが変化しても比率がかわらにようにemでサイズ指定
      aspect-ratio: 1; // widthとの比率を1:1にして数値入力をwidthに限定する
      border-radius: 50%;
      background: pink;
      position: absolute;
      left: 0;
      top: 0.5em;  // 行間の影響をうけるので、計算と見た目で調整するしかない。。
    }
  }
}

はい、だいたいこんな記述で書いてました。::before要素でマークを作成し、position:absoluteで位置調整です。
leftは0で問題ないんですが、上下センターの位置、topの値をline-heightと計算してemで調整。それでもセンターに見えない場合は見た目で合わせるといった具合です。

この記述だとfont-sizeが変わってもだいたい位置がズレることはありません。
ただし、行間が違うスタイルのテキストにあてると位置は変わってしまいます。ようするにこのtopの値を調整するのが難しかったんですね。

transformでの上下中央配置はNG

よく要素を中央に配置する方法としてtransformを使った手法がありますが、この方法は最適解ではありません。
なぜなら、リストのテキストが1行で完結するとは限らないからです。テキストが2行以上になるとその複数行の上下センターの位置にマーカーが配置されてしまいます。

.list {
  > li {
    padding-left: 1em;
    line-height: 1.5;
    font-size: 20px;
    color: #333;
    position: relative;
    &::before {
      content: "";
      width: 0.6em;
      aspect-ratio: 1;
      border-radius: 50%;
      background: pink;
      position: absolute;
      left: 0;
      top:50%;
      transform:translateY(-50%); // 上下センターにはなるが、複数行のテキストには対応できない
    }
  }
}

上図のようにテキストが2行になるとマーカーの位置が2行の高さ分の中央に配置されます。

コーディングにおいては可変する可能性が考えられる要素のことを考慮してコードを書く必要がありますね。

lhを使って記述してみる

.list {
  > li {
    padding-left: 1em;
    line-height: 1.5;
    font-size: 20px;
    color: #333;
    position: relative;
    &::before {
      content: "";
      width: 0.6em;
      aspect-ratio: 1;
      border-radius: 50%;
      background: pink;
      position: absolute;
      left: 0;
      top:calc(0.5lh - 0.3em): // 1行の半分(0.5lh)からマーカーの要素の半分(0.3em)を引いた値を計算
    }
  }
}

はい、いかがでしょう。マーカーの位置綺麗に1行目のセンターに配置されています。
この手法の素晴らしいところは異なる文字サイズ、異なる行間のテキスト要素にも当てはまることです。

ためしに上記のコードのfont-sizeやline-heightの値をかえてみてください。サイズも位置もずれることありません。すばらしい!

マーカーが画像の時の位置調整

マーカーがコーディングでは実現できないアイコン画像の時もあるでしょう。実はその方がもっと簡単です。
実際に見ていきましょう

.list-icon {
  > li {
    padding-left: 1em;
    line-height: 1.5;
    font-size: 20px;
    color: #333;
    position: relative;
    &::before {
      content: "";
      width: 0.8em;
      height: 1lh;  // heightは1行分の高さを指定
      background: url(../images/star.svg) no-repeat center / contain; // backgroundで背景画像の指定。位置は上下左右センター。サイズはcontain。
      position: absolute;
      top: 0;
      left: 0;
    }
  }
}

アイコン画像を配置しました。ポイントは以下の2行です

height: 1lh;  // heightは1行分の高さを指定
background: url(../images/star.svg) no-repeat center / contain;

高さの値を1lhとすることで1行分の高さに設定します。これのおかげで親要素のテキストのline-heightが変わっても1行の高さという値は変わらない。

そこに背景画像を上下左右センターに配置して、サイズは枠に収まるcontainを指定します。

まとめ

いかがだったでしょうか。
これまで計算したり、見た目で合わせたりしても、再利用時に都度調整する必要があったんですが、lhの登場でリストのコンポーネントをスマートに配置することができました。

モバイルバージョンを終了