CSSのdisplay: contentsが便利!CSSでスマホだけ要素の順番を入れ替える方法

スマホだけ順番を変えたい!

「PCでは、左にタイトルと文章、右に画像を置きたい!」

「でもスマホでは、タイトル → 画像 → 文章の順番にしたい!」

こんなレイアウトを作ることがあります。

完成イメージ

PC

スマホ

まずは普通にFlexboxで作ってみる

HTMは以下です。

<div class="content">
  <div class="text">
    <h2>タイトル</h2>
    <p>ここに文章が入ります。</p>
  </div>

  <div class="image">
    <img src="https://placehold.jp/150x150.png" alt="" />
  </div>
</div>

まず、PCでは横並びにします。

.content {
  display: flex;
}

これで、

テキスト  画像

というレイアウトになります。

スマホでは縦積みにしたいので、

@media (max-width: 767px) {
  .content {
    flex-direction: column;
  }
}

とします。

すると、

タイトル
文章
画像

になります。

「タイトル → 画像 → 文章にしたいのに、文章が先に来ちゃう!」

ここでorderを使いたくなります。

orderを使いたいけど、うまくいかない!

orderを使うことで、要素の並び順を指定できます。

しかし、今回のHTMLでは、タイトルと文章を.textというdivで囲んでいます。

そのため、orderを使っても、「.text」「.image」というグループ単位でしか順番を変更できません。

「タイトルだけを画像の上に出したい!」

これが普通のFlexboxだと少しやりにくいところです。

そこでdisplay: contents

ここで登場するのが、

display: contents;

です。

スマホの時、.textに指定してみます。

.text {
  display: contents;
}

すると、.textというレイアウト上の箱がなくなり、その中にあるh2とpが親のFlexboxに直接参加できるようになります。

つまり、レイアウト上は、

.content
├ h2
├ p
└ .image

のように扱えるイメージです。

「.textの箱をなくして、中身だけ使う!」

と考えると分かりやすいです。

orderを組み合わせる

あとはorderを使えばOKです。

.content {
  display: flex;
}

@media (max-width: 767px) {
  .content {
    flex-direction: column;
  }

  .text {
    display: contents;
  }

  h2 {
    order: 1;
  }

  .image {
    order: 2;
  }

  p {
    order: 3;
  }
}

これでスマホでは、

タイトル
↓
画像
↓
文章

という順番にできます。

やったー!

HTMLの順番を変更しなくても、CSSだけでスマホの表示順を変更できました。

実際のコード

今回の例をまとめると、HTMLはこれです。

<div class="content">
  <div class="text">
    <h2>タイトル</h2>
    <p>ここに文章が入ります。</p>
  </div>

  <div class="image">
    <img src="https://placehold.jp/150x150.png" alt="" />
  </div>
</div>

CSSは、

.content {
  display: flex;
}

@media (max-width: 767px) {
  .content {
    flex-direction: column;
  }

  .text {
    display: contents;
  }

  h2 {
    order: 1;
  }

  .image {
    order: 2;
  }

  p {
    order: 3;
  }
}

display: contentsは「箱をなくす」と覚える

display: contentsは、名前だけ見るとちょっと分かりにくいですよね。

ざっくり、

その要素の箱をなくして、中身を親のレイアウトに参加させる

と覚えておけばOKです。

今回なら、

.text {
  display: contents;
}

とすることで、.textというグループをなくして、

h2
p
image

をFlexboxで個別に扱えるようにしました。

display: contentsを使うときの注意

便利なdisplay: contentsですが、何でもこれにすればいいわけではありません。

例えば、

.text {
  display: contents;
  background: #eee;
  padding: 20px;
}

のように、.text自体に背景色やpaddingを付けていた場合です。

display: contentsによって.textのレイアウト上の箱がなくなるため、.textに設定していた背景やpaddingなどが期待したように表示されなくなります。

そのため、

この要素自体の箱をなくしても大丈夫?

と考えてから使うのがおすすめです。

まとめ

今回のように、divが邪魔して順番を変えられないときは、display: contentsが便利です。

これによって、中にあるh2やpを親のFlexboxで直接扱えるようになります。

そしてorderと組み合わせれば、スマホだけ順番を変更できます。

「orderを使いたいのに、親要素のせいでうまく順番を変えられない!」

そんなときは、

「このラッパー、display: contentsで箱をなくせないかな?」

と考えてみると、意外とスッキリ解決できるかもしれません。

おとうふ

田舎で働くWebエンジニア

毎日少しずつ成長中🌱
仕事・学習・暮らしの中で、自分が実際に経験したことを発信