LoginSignup
1
0

More than 5 years have passed since last update.

複数の name-value リストで name 列の幅を CSS だけで動的に揃える

Posted at

TL;DR

複数の dl 要素による name-value リストにおいて、name 列(dt 要素)の幅を CSS だけで動的に(幅を決め打ちしないで)揃える方法です。

グリッドレイアウト display: griddisplay: contents で実現できます。ただし、2018 年 9 月時点で IE 11 と Edge は後者をサポートしていません

お急ぎの方は CodePen をご覧ください。

背景

Web アプリの UI を実装していると、よく次のような name-value リストが必要になることがあります。

name-value リスト

このようなリストは HTML では通常 dl, dt, dd 要素を用いて次のようなマークアップを行います。

<div class="container">
  <header>
    <h1>User Information</h1>
  </header>
  <div class="content">
    <dl>
      <dt>Username</dt><dd>john-smith</dd>
    </dl>
    <dl>
      <dt>Full name</dt><dd>John Smith</dd>
      <dt>Age</dt><dd>20</dd>
      <dt>Email address</dt><dd>john-smith@example.com</dd>
    </dl>
    <dl>
      <dt>Type</dt><dd>Admin</dd>
      <dt>Language</dt><dd>English</dd>
    </dl>
  </div>
</div>

ここで、上図の破線のように、name 列(dt 要素)の幅を揃えたいとします。全ての行が一つの dl 要素内であれば、display: table などを用いて比較的簡単に実装できます。

しかし、今回は複数の dl 要素からなっています。こういった場合にリストをまたいで name 列の幅を揃えるにはどうすればよいでしょうか。この記事では、その具体的な方法を書きます。

なお、複数の dl 要素を使っているのは、リストを意味ごとにグループ分けしたいという目的があるので、スタイルのためにマークアップを変更するのは前提として避けます。

グリッドレイアウト + display: contents

方法としては、グリッドレイアウト display: griddisplay: contents を用います。スタイルシートは次のような感じになります(重要な部分のみ抜粋)。

.content {
  display: grid;
  grid-template-columns: max-content 1fr;
}

dl {
  display: contents;
}

リストのコンテナでグリッドを定義

まず、複数の dl 要素を持つコンテナ(今回は <div class="content">...</div>)で display: grid とし、grid-template-columns で列の幅を定義します。

ポイントは一列目の max-content で、これは要素の中身に合わせて幅が最適化されるという非常に便利な値です。今回のケースでは、dt 要素の中のテキストが改行されないように、かつ余りが出ないようにピッタリな幅を自動的に計算してくれます。

max-content は CSS Intrinsic & Extrinsic Sizing Module Level 3 で追加されました。より詳細を知りたい方は Intrinsic Size Determination セクションをご覧ください。

これで、以下のようなグリッドレイアウトで表示されるようになります。

グリッドレイアウト

でも崩れてしまっていますね…。それもそのはず、定義した各グリッドの中に入るのは、display: grid にした要素の直下の要素だからです(「グリッドアイテム」と呼ばれます)。直下にあるのは dl 要素なので、リストごと各グリッドの中に放り込まれている状態です。

display: contents でその要素を “無かったことに” する

そこで登場するのが、display: contents です。これは、指定した要素を “無かったことに” します。これを先ほどの dl 要素に対して指定することで、dl 要素は無かったこととしてレイアウトされ、その中の dt, dd 要素が display: grid にした要素の直下に来るようになります。

よって、以下のようなレイアウトになり、作りたかったものができました。

display: contents を用いたあとのレイアウト

display: contents のイメージとしては、それを指定した要素だけが display: none になることかなと思います。display: none はその要素自身とその配下の要素すべてが生成されなくなりますが、display: contents は自身だけが生成されず、その配下の要素は通常通り生成されます。

display: contents は CSS Display Module Level 3 で定義されています。詳細は Box Generation: the ‘none’ and ‘contents’ keywords セクションをご覧ください。

また、display: contents の用途などについてはこちらの記事 “More accessible markup with display: contents” がわかりやすいです。

対応ブラウザ

2018 年 9 月時点での各機能の実装状況です。IE 11 と Edge は対応していないのでご注意ください。

max-content

Can I use max-content?

スクリーンショット 2018-09-29 14.50.26.png

display: contents

Can I use display: contents?

スクリーンショット 2018-09-29 14.50.57.png

ソースコード・デモ

CodePen でご覧いただけます。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0