display: contents

display: contents; を設定した要素は、DOMツリー(アクセシビリティツリー)から削除される。
省略されるのはcontentsを指定した要素のみで、子孫要素へは影響を与えない。
display: contents の値を設定すると、指定した要素のコンテンツ領域以外は描画されなくなる。

<p>テキスト</p>

コンテンツ領域とはタグで囲んだ中身のことで、上記であればpタグの中にある「テキスト」という文字のこと。
つまり、その他のpadding・border・marginがブラウザに描画されなくなる、ということである。

display:none との違い

ブラウザに対する非表示指定の値としては「none」もあるが、違いは『コンテンツ領域を表示するか・しないか』である。
display: contents はコンテンツ領域(pタグと「テキスト」という文言)を描画しているのに対し、display: none はコンテンツ領域含めすべて描画されない。
検証ツールで確認してみても、display: contents を指定したdiv要素は選択できないが、子要素にあたるpタグは選択することができる。
これはブラウザに描画されなくなる要素が、display: contents を指定した要素のみに限定されていることを意味している。

display: contents のメリット

  1. HTMLを構造化できる
  2. 不要なラッパー要素となるHTMLを省略できる

display: contents の実装例

FlexBoxとの組み合わせ

display: flexを使用して、以下のようなボックスを作成する。

<div class="container">
  <img class="thumbnail" src="thumbnail.png" alt="">
  <div class="contents">
    <h2 class="title">ブログのタイトルが入ります。</h2>
    <p class="text">ブログの説明が入ります。</p>
    <button type="button" class="button">Enter</button>
  </div>
</div>

上記のdivタグ(contentsクラス)にdisplay: contentsを指定する。

@media screen and (max-width:600px) {
  .contents {
    /* align-items: center; */
    display: contents;
  }
}

divタグ(contentsクラス)にdisplay: contentsを指定したことで、containerクラスの子要素(フレックスアイテム)は以下のように変化する。
同時に検証ツール上(DOM)でもcontentsクラスのdivタグが触れなくなっている。

実際のHTMLコードが変わっているわけではないが、DOM上だと以下のような振る舞いになる。
画像以外の要素を囲んでいたdivタグ(contentsクラス)をdisplay: contentsで認識させなくしたことで、4つのタグが兄弟要素のように扱われる。

フレックスアイテム
display: contents指定前imgタグ・divタグ(contentsクラス)
display: contents指定後imgタグ・h2タグ・pタグ・buttonタグ
<div class="container">
  <img class="thumbnail" src="thumbnail.png" alt="">
  <h2 class="title">ブログのタイトルが入ります。</h2>
  <p class="text">ブログの説明が入ります。</p>
  <button type="button" class="button">Enter</button>
</div>

同列のフレックスアイテムとなったtitleクラスのh2タグに、orderプロパティを指定する。
orderプロパティを指定することで、フレックスコンテナ内での並びを変えることができる。

@media screen and (max-width:600px) {
  .title {
    font-size: 20px;
    order: -1;
  }
}

order: -1を指定したことで、titleクラス(h2タグ)の順番を、imgタグより上に移動させることができる。

ブラウザが認識する要素の階層が変わることで、フレックスアイテムも変化し、元のHTML階層では干渉できなかった要素へ影響を与えることが可能となる。

Gridレイアウトとの組み合わせ

display: gridと組み合わせてソースを簡略化することもできる。

<div class="table">
  <div class="required">必須</div>
  <div class="contents">必須項目の記載をここに行う</div>
  <div class="required">必須</div>
  <div class="contents">必須項目の記載をここに行う</div>
  <div class="optional">任意</div>
  <div class="contents">任意項目の記載をここに行う</div>
  <div class="optional">任意</div>
  <div class="contents">任意項目の記載をここに行う</div>
  <div class="required">必須</div>
  <div class="contents">必須項目の記載をここに行う</div>
</div>
.table {
  width: 500px;
  margin: 20px auto 0;
  display: grid;
  grid-template-columns: repeat(2, auto);
  border-top: solid 1px #000;
}

.required {
  text-align: center;
  color: #ff0000;
  border-bottom: solid 1px #000;
}

.optional {
  text-align: center;
  color: #0000ff;
  border-bottom: solid 1px #000;
}

.contents {
  text-align: center;
  border-bottom: solid 1px #000;
  border-left: solid 1px #000;
}

表の行や列が増えてくるとHTMLからテーブルの構造が分かりづらくなる。
そこで各行にrowクラスを付与した親要素を追加してテーブルの行をまとめ、それぞれにCSSでdisplay: contentsを指定する。

<div class="table">

  <div class="row">
    <div class="required">必須</div>
    <div class="contents">必須項目の記載をここに行う</div>
  </div>

  <div class="row">
    <div class="required">必須</div>
    <div class="contents">必須項目の記載をここに行う</div>
  </div>

  <div class="row">
    <div class="optional">任意</div>
    <div class="contents">任意項目の記載をここに行う</div>
  </div>

  <div class="row">
    <div class="optional">任意</div>
    <div class="contents">任意項目の記載をここに行う</div>
  </div>

  <div class="row">
    <div class="required">必須</div>
    <div class="contents">必須項目の記載をここに行う</div>
  </div>

</div>
/* 追加 */
.row {
  display: contents;
}

display: gridを指定したはじめの状態では、各行が縦並びになっているが、grid-template-columns: repeat(2, auto)を指定することで、2列のグリッドラインができ、rowクラスの要素がグリッド上に並ぶ。
その後、グリッドアイテムとなっていたrowクラスにdisplay: contentsを指定することで、子階層の各要素がグリッドアイテムに変化し、デザイン通りのレイアウトとなる。

display: contentsを指定することで、グリッドコンテナ(tableクラス)の影響を受けずレイアウトができる。

inserted by FC2 system