「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で箱をなくせないかな?」
と考えてみると、意外とスッキリ解決できるかもしれません。

