PR

display: grid;を使ってレスポンシブ時に要素の順番が変わるレイアウトを攻略する

HTML/CSSを学ぶ

こんにちは。今回は、今までは再現するのに手間のかかった「レスポンシブで要素の順番が変わるレイアウト」をgridを使って上手く攻略していこうという内容です。grid自体の解説はあまり詳しく行わないので、以下の記事を参考にしてください。

grid - CSS: カスケーディングスタイルシート | MDN
grid は CSS のプロパティで、一括指定プロパティとして明示的・暗黙的なすべてのグリッドプロパティを単一の宣言で設定します。
CSS Grid Layout を極める!(基礎編) - Qiita
0. はじめにCSS Grid Layout(グリッドレイアウト)は、2次元レイアウト を、HTML/CSS を使って簡単・自由に操作できる、CSSの新しい機能です。格子状のマス目のグリッドに好…

「レスポンシブで要素の順番が変わるレイアウト」が例えばどんなレイアウトかというと、

  • 文章とアイキャッチ画像が含まれている
  • PCでは横並び、SPでは縦並びになる
  • PC版では見出し→テキスト→画像の順番だったのがSP版では見出し→画像→テキストになる

というパターンです(下図)。

PC版の場合
SP版の場合

このように順番が入れ替わってますから、普通にコーディングしようとするとちょっと面倒ですね。

これをgridを使って上手くやってみましょう。

結論

前提としてdestyle.css(https://nicolas-cusan.github.io/destyle.css/)というリセットCSSと次のdefault.cssを読み込んでいます。

default.css
img {
  display: block;
  width: 100%;
  height: auto;
}

a {
  display: block;
}

*:before,
*:after {
  display: block;
}

サンプルコード

index.html
<main class="Main">
  <div class="Main__Inner">
    <section class="Section">
      <h2 class="Section-Headline">見出し</h2>
      <img src="./images/dummy.jpg" alt="" class="Section-Image" />
      <p class="Section-Text"
        >ダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキスト</p
      >
    </section>
    <section class="Section2">
      <h2 class="Section-Headline">見出し</h2>
      <img src="./images/dummy.jpg" alt="" class="Section-Image" />
      <p class="Section-Text"
        >ダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキスト</p
      >
    </section>
  </div>
</main>
style.css
.Main {
  width: 100%;
  padding: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.Main__Inner {
  width: 100%;
  max-width: 800px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.Section {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 20px 1fr;
  grid-template-areas:
    "a b"
    "c b";
  gap: 20px;
}

@media screen and (max-width: 768px) {
  .Section {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
    grid-template-areas:
      "a"
      "b"
      "c";
  }
}

.Section2 {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 20px 1fr;
  grid-template-areas:
    "b a"
    "b c";
  gap: 20px;
}

@media screen and (max-width: 768px) {
  .Section2 {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
    grid-template-areas:
      "a"
      "b"
      "c";
  }
}

.Section-Headline {
  grid-area: a;
  font-size: 20px;
  font-weight: bold;
}

.Section-Image {
  grid-area: b;
}

.Section-Text {
  grid-area: c;
  line-height: 1.5;
  font-size: 14px;
}

解説

セクションは2つありますが、左右を入れ替えただけのパターンなので基本的に同じです。

まず、HTMLを見ていきましょう。

<section class="Section">
  <h2 class="Section-Headline">見出し</h2>
  <img src="./images/dummy.jpg" alt="" class="Section-Image" />
  <p class="Section-Text"
    >ダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストダミーテキスト</p
  >
</section>

見出し、画像、テキストを並列に配置します。またこの時点での順番はSP準拠にした方がちょっとだけ楽かなと思います。

さて、レイアウトの発想ですが

  • PC版のレイアウトを2×2のグリッドになっていると考える
  • そのうち見出しは左上のエリア、テキストは左下のエリア、画像は右の列全域を割り当てる(1つ目のセクションの場合)
  • PC/SPではグリッドの構造を組み替えることで配置を制御する

と考えています。

デベロッパーツールでPC版におけるグリッドの枠を見てみるとこのようになっています。

紫の部分はgapで指定した余白で、水色の部分が各セルです。

PC版のレイアウトを2×2のグリッドになっていると考える

コードを見ていきましょう、該当部分は以下です。

.Section {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr; //列を指定
  grid-template-rows: 20px 1fr; //行を指定
  grid-template-areas:
    "a b"
    "c b";
  gap: 20px;
}

まずはgridの標準的な書き方を使って2×2の枠を指定します。1frの「fr」という単位はgrid特有のもので、横幅あるいは縦幅に対して余った分を埋めるように領域を確保します。複数ある場合は余った分を均等に分け合います。

margin: auto;の挙動に近いイメージかもしれません。詳しく解説している記事もあるので、合わせて読んでみてください。

そのうち見出しは左上のエリア、テキストは左下のエリア、画像は右の列全域を割り当てる

枠を作ったら、各エリアに名前をつけます。grid-template-areas(https://developer.mozilla.org/ja/docs/Web/CSS/grid-template-areas)がそれを指定するプロパティで、CSS上でも格子状に値を記述します。

grid-template-areas:
  "a b"
  "c b";

これによって、左上の1行1列目はa、左下の2行1列目はc、右側の2列目全域はbと名前が割り当てられました。今回はサンプルとしてa/b/cと名付けましたが、もっと具体的にheadline/image/textでも良いかもしれませんね。

今度は子要素側の指定です。自分がどのエリアに該当するかを記述する形です。

.Section-Headline {
  grid-area: a;
  font-size: 20px;
  font-weight: bold;
}

.Section-Image {
  grid-area: b;
}

.Section-Text {
  grid-area: c;
  line-height: 1.5;
  font-size: 14px;
}

こうすることで見出しはa、画像はb、テキストはcにそれぞれ配置されます。

PC/SPではグリッドの構造を組み替えることで配置を制御する

それでは問題のレスポンシブです。これは.Sectionのグリッドの定義を変えることで対応しましょう。

@media screen and (max-width: 768px) {
  .Section {
    grid-template-columns: 1fr; //1列
    grid-template-rows: auto auto auto; //3行
    grid-template-areas:
      "a"
      "b"
      "c";
  }
}

まず、2×2から3行1列のグリッドに変更します。そしてエリア名の設定も3行1列の形に変えます。

こうすることでSP版では意図した通りに表示されます。

この方法であれば、並列になっている要素なら順番は自由に調整できます。

まとめ

というわけでgridを使ったスマートなレイアウトの方法でした。今回のようなデザインパターンはそこそこ出会いますし、他にもこの方法が適したデザインもあるかもしれません。ぜひ覚えてみてください。

コメント

タイトルとURLをコピーしました