コハム

Webクリエイターのコハムが提供する、Web制作に役立つ情報をまとめたブログです。

【display: contents】って知ってた?flexやgridとも相性がいいプロパティの使い道

The Magical CSS Display Property: Contents!

記事は上記記事を意訳したものです。

※当ブログでの翻訳記事は元サイト様に許可を得て掲載しています。


CSSにはたくさんの表示プロパティがあります。頻繁にCSSを書かない方は、比較的最近導入された面白いプロパティを見逃しているかもしれません。それほど新しくはありませんが(2018年頃から主要ブラウザでサポートされ始めました)。そう、display: contents のことです。

contents は何をするのか?

divspanなどのHTML要素は、パディングやマージンなどを指定できる見えないボックスで囲まれています。一般的に、私たちはボックスを扱います。しかし、display: contents を適用すると、そのボックスが魔法のように消えてしまいます。正確には、擬似要素や子要素に置き換えられます。つまり、擬似ボックスや子ボックスに置き換わるのです。そのボックスが存在しないかのようになります。例を見てみましょう:

<div id="parent-contatiner">
  <div id="container" style="display: contents">
    <h3> 私はパンダです! </h3>
    <p> 私は猫が好きです! </p>
  </div>
</div>

container divの周りにはボックスがなくなり、見えなくなります。代わりに、その子要素であるh3p要素に置き換えられます。つまり、これらはもはやcontainerの子ではなく、parent-containerの子になります。DOMツリーから消えるわけではありませんが、ツリーはそれがないふりをするのです。面白いですよね?

contents をどこで使うのか?

「コンテナ自体が消えてしまうと、すべてのスタイルやイベントも消えてしまうのでは?」と疑問に思うかもしれません。答えは「いいえ」です。イベントは依然として付加されたままで、失われるスタイルはボックス生成に関連するスタイル(マージン、パディング、ボーダーなど)だけです。では、どこで使うのでしょうか?

すぐに2つのシナリオを挙げることができます。

  1. セマンティックな可読性のために何かをコンテンツでラップする必要があるが、そうすることでデザインが崩れてしまう場合。contentsを使用することで、セマンティックな可読性と必要なデザインの両方を兼ね備えた理想的な状況を作り出すことができます。

  2. flexやgridを使用しているコンテナの直接の子要素として、すべての要素が必要な状況に直面するかもしれません。条件などに基づいて一部の子要素にスタイルを適用する必要がある場合。その場合、その条件に基づいてdisplay: contentsを持つコンテナ内にそれらの子要素をラップすることができます。

これが少し難しく聞こえますか?では、私がこのプロパティを最初に見つけた経緯をお話しましょう。

少し練習してみましょう!

まず問題を説明します。モバイルファーストのアプローチを使用してレスポンシブなウェブページに取り組んでいました。3つのボックスがありました。デスクトップビューでは、それらは画像1のように横並びに表示されます。

画像1:デスクトップビュー

単純なflex-rowですよね?しかし、モバイルビューでは、Box2とBox3がスタックのように表示され、このスタックがBox1と横並びになります(画像2のように)。

画像2:モバイルビュー

さて、これをどのように実現できるでしょうか?考えてみてください。これによってcontentsを理解し、実践的な経験を得ることができるでしょう!

私の解決策をお見せしましょう(これが唯一の方法ではないかもしれません。私が個人的に解決した方法で、きれいだと思っています!)

display: flexが適用された親コンテナ内に3つのボックスがあります。Box2とBox3をコンテナでラップしました。モバイルビューでは、このコンテナはdisplay: flexを持ちます。つまり、Box1とコンテナが兄弟要素となり、flexプロパティはこの2つにのみ適用されます。Box2とBox3には、コンテナを通じて別のflexプロパティが適用されます。しかし、デスクトップビューでは、このコンテナはdisplay: contentsを持ちます。つまり、デスクトップビューでは、コンテナが視覚的に消え、Box2とBox3が親コンテナの直接の子になります。これで3つのボックスすべてが兄弟要素となり、親コンテナからのflexプロパティがすべてに適用されます。以上です。

コードは次のようになります:

<div class="outer-container">
  <span> Box1 </span>
  <div class="inner-container">
    <span> Box2 </span>
    <span> Box3 </span> 
  </div>
</div>
.outer-container {
  display: flex;
  flex-direction: row;
}

.inner-container {
  display: flex;
  flex-direction: column;
}

@media only screen and (max-width: <breakpoint>px) {
  .inner-container {
    display: contents;
  }
}

ちょっとした注意!

display: contentsがすべての要素で同じように機能するわけではないことを言及しておくべきです。CSSのボックスの概念だけでは純粋にレンダリングされない要素もあり、異なる挙動を示す場合があります。詳細についてはこのドキュメントを参照してください。

以上が、私がdisplay: contentsを見つけた経緯であり、魔法のように機能すると思います。そう思いませんか?

©コハム