display: grid
は便利であり様々な使い方ができます。これを表のように使いたくなるときがあります。例えば次のようなコードで表のようなレイアウトを実現できます。
<div class="table"> <div>名前</div> <div>年齢</div> <div>職業</div> <div>田中</div> <div>30</div> <div>エンジニア</div> <div>佐藤</div> <div>25</div> <div>デザイナー</div> </div>
.table { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; border: 1px solid #ccc; padding: 8px; } .table > div { padding: 4px; background-color: #f9f9f9; }
こんな感じで表を作れます。ただ、これはDOM的にはいまいちわかりにくいものになっています。行が変わってもただ div が連続しているだけです。こうなっていると行単位や列単位で操作するクエリを書くのが手間になります(一応 nth-child を駆使すればできなくはないです)。そこで行を表す要素で行内のセル要素を括りたくなります。しかしながら単に要素を増やすだけだとグリッドデザインを壊すことになってしまいます。表としての見た目を崩さずにこれを実現しようとする場合 display: contents
が使えます。
display: contents
な要素はDOM要素ではあるけど、レイアウト上ではその存在が無視されます。具体的にはdisplay: contents
な要素はdisplay: grid
の直下でもグリッドアイテムとしては扱われません。代わりにdisplay: contents
直下の要素らがグリッドアイテムとして扱われます。これを利用することでDOM構造が明確で扱いやすいdisplay: grid
で作った表を実現できます。
display – CSS: カスケーディングスタイルシート | MDN#contents
実際にdisplay: contents
を使ったグリッドデザインの表が次です。
See the Pen
display contents by cpt-sugiura (@cpt-sugiura)
on CodePen.
<div class="table"> <div class="row"> <div>名前</div> <div>年齢</div> <div>職業</div> </div> <div class="row"> <div>田中</div> <div>30</div> <div>エンジニア</div> </div> <div class="row"> <div>佐藤</div> <div>25</div> <div>デザイナー</div> </div> </div>
.table { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; border: 1px solid #ccc; padding: 8px; } .row { display: contents; /* この要素自体はレイアウトに現れない */ } .table > .row > div { padding: 4px; background-color: #f9f9f9; transition: background-color 0.2s; } .table > .row.header > div { background-color: #ddf; } /* ホバー時:行ごとに背景色を変える */ .table > .row:hover > div { background-color: #e0f7ff; }
DOM構造が見た目と一致するようになり行単位でスタイルをあてるのが容易になりました。こうすると例にある行にホバーした際の背景色変更といったスタイルも容易に記述できます。
こんな感じでdisplay: contents
は作りたいデザインとあるべきDOM構造の差異を吸収することができます。CSSに限らずクエリセレクタが複雑、コンポーネントの都合で複数要素をそのまま渡せない、扱いにくいくらい多重にネストされた要素になってしまう、などといった事態が起きた時、display: contents
な要素を作ることでそれを解決しやすいです。