🚀

display: contents; とは一体何なのか

2020/12/13に公開

tailwindcssを途中から導入しはじめたプロジェクトで、contentsクラスを使用している箇所がデザイン崩れを起こしていたので、tailwindcssにおけるcontentsクラスが持っているプロパティdisplay: contents;について調べた。

まとめ記事あるけど、長いのでみんなきっと理解できてない

https://coliss.com/articles/build-websites/operation/work/how-to-work-display-contents.html

coliss が[CSS]「display: contents;」がすごい便利!ラッパーを使った実装が大きく変わるこれからのテクニックと「すごい便利!」まで言って2018年に解説した記事作ってくれているけど、なかなかボリューミーな記事。
会社の同僚たちが「わからん」言ってたのと、Twitterみても「あとぜ読むぜ」くらいのリアクションしかわかんなかったので、「結局いつ使うねん」だけは、わかるようにまとめてみる。

display: contents; is 何

結論「display: gridと併用して、DOMの構造化のために使用する」

display: contents;が他の要素に与える影響はいろいろある様なんですが、結論は「display: gridと併用して、DOMの構造化のために使用する」です。終わりです。

今のところdisplay: gridの子要素としてしか基本的に使い道はない!との結論に個人的に落ち着いています。

サンプルと共に解説

どういうことかというと、CSS Grid Layout を使用すると、 grid の子要素(grid-item)が全て並列になってしまい、子要素同士をグループ化する事はできないんですが、こんな時に便利らしいです。

例えばこんな感じの、レイアウト作りたい時はこんなマークアップになります。
表示イメージ

<div class="grid">
  <div class="item side-navi">side-nav</div>

  <div class="item content">content</div>
  <div class="item content-footer">content-footer</div>
  
  <div class="item footer-navi">footer-navi</div>
  <div class="item footer">footer</div>
</div>

例だと、きっと content と content-footer を main要素でくくったり、footer-navi と footer をfooter要素でくくったりしたくなるはず...(きっと...)

そこで、display: contents;の出番です。
display: contents;が指定された要素はgrid-itemにならず、その子要素がgrid-itemとしてレイアウトされるので、こんな感じで書けるようになります。

<div class="grid-with-contents">
  <div class="item side-navi">side-nav2</div>

  <main class="contents">
    <article class="contents">
      <div class="item content">content2</div>
      <footer class="item content-footer">content-footer2</footer>
    </article>
  </main>
  
  <footer class="contents">
    <navi class="item" id="footer-navi-2">footer-navi2</navi>
    <div class="item" id="footer-2">footer2</div>
  </footer>
</div>

https://codepen.io/eeonk/pen/VwKPbZM sample書いてみたので、display:contents;あると崩れないけど、トルと崩れる様子を確認できると思います。

ちなみに、colisではこんな感じのレイアウトを、参考に説明されてらっしゃいました。
colisのサンプル

個人的には、CSS Grid Layout がっつり使った事そんなに多くないので、どちらの例に関しても、果たして活躍することがあるのか?と思ってしまっているんですが、きっとその時がくれば、便利さに涙を流すことを期待しています。

Can I use CSS display:contents ?

ちなみに、サポート状況(2020/12)はこんな感じで、IEは死亡、モダンブラウザに関してもまだまだパーシャルサポートみたいです。

https://caniuse.com/?search=CSS display%3Acontents

果たして、がっつり使ってる人どれくらいいるんだろうか気になる。

詳しく

もうすこしだけ、詳しくdisplay:contentsについて書いてみます(本当に少しだけ)
冒頭で、display:contentsが効いている部分が崩れてる話をしていたんですが、何で崩れたのを書きます。
ざっくり説明すると、contents の要素は、contentブロックに対するstyle以外が無効になるからみたいんです。
margin が効かなくなったことで崩れてました。

contentブロックてのは、chrome devツールで言うこの真ん中の青い部分ですね。

MDNの参考も貼っておく
https://developer.mozilla.org/ja/docs/Web/CSS/Containing_block

効かなくなるCSSと影響ないCSSはざっくりですが、こんな感じでした。

.contents { 
  display: contents;

  /*   OK   */
  font-weight: bold;
  color: red;
  text-decoration: underline;
  cursor: pointer;
  &::before{
    content: 'before'
  }
  &::after{
    content: 'after'
  }
  
  /*   NG   */
  background: #000;
  padding: 10px;
  margin: 10px;
  border: solid 1px #000;
  box-shadow: 2px 2px 10px #000;
  width: 10px;
}

https://codepen.io/eeonk/pen/vYXgxrZ
まあ、contentsつけた要素に対して他のstyle当てることないはずなので、気にしなくても良さそうな気はするけどね。

ちなみに、詳しくは、colisの記事の[CSS]「display: contents;」がすごい便利!ラッパーを使った実装が大きく変わるこれからのテクニックの『「display: contents;」について詳しく解説』のところで詳しく書いてあるので、そっち読み込んでもいいかもです。

Discussion