実務でCSS Gridを使う

CSS Gridがほぼすべてのモダンブラウザでサポートされた、というニュースが流れたのは昨年半ば頃でしたでしょうか。このレイアウトモジュールを試用してみたレポートが次々と発表されましたし、このモジュールを実際に取り入れたサイトが徐々に出始めているようでもあります。

とはいえ、筆者自身は「実務で使用するのは…」と二の足を踏んでいました。ところがある日、一見フツーのレイアウトなのに、従来の方法ではどうしても実現できず、CSS Gridを使わざるを得ない案件に直面してしまったのです!

どんな案件か

CSS Gridを使用すると、フレキシブルなレイアウトが実現できるという点もさることながら、マークアップがシンプルになるという点が大きなメリットであると筆者は考えていますが、IE・Edgeでは基本的なプロパティしか使えないこともあり、実務で使うことには躊躇していました。

また、デザイナーの方がこのプロパティのことを熟知した上で、このプロパティを使ってこそ実現可能な「フレキシブルなレイアウト」のデザインを仕上げてくる可能性は、筆者のこれまで働いてきた現場においては著しく低いであろう、とも考えていました(なにしろデザイナーの方々のほとんどがコーディングにはホボ興味のなさそうだったので…)。ですので実務で使用する機会はまだまだ先かと考えていました。

今回関わった案件は、一見ごく普通にメインコンテンツとサイドバーで構成されるものであるように見えました。が、2つ目以降のセクションのヘッダーの背景が横方向に永遠に広がっています。サイドバーがなければよくあるデザインで、何も悩むことなく実現できますよね。

セクションのヘッダーのデザインは背景画像が異なるだけでいずれも似たようなものでしたが、1つ目のセクションはサイドバーがあるためか、背景は横方向に伸びておらず、メインコンテンツの領域に収まっています。

今回実現すべきレイアウト

従来の方法で実現を試みる

まず安易に思いついたのが、1つ目のセクションとサイドバーをタグで囲んで一つのブロックとし、残りのセクションをその後に続けるというもの。これでデザイン通りのレイアウトは実現できますが、セクションの間にページ全体のaside要素たるべきサイドバーが挟まれてしまい、コンテンツの記述順序が気持ち悪いことに。

<div>
  <section>セクション1</section>
  <aside>サイドバー</aside>
</div>
<section>セクション2</section>
<section>セクション3</section>
1つ目のセクションとサイドバーをタグで囲む

また、小さなデバイスでは1カラムになるレスポンシブサイトなので、サイドバーはコンテンツの最後に表示させなければならず、やはりコレでは拙いです。見た目の順序の方を操作することもできなくはないですが、そんな帳尻合わせをするよりは、そもそもコンテンツの順序をキレイにしておくべきと考えました。

次に、コンテンツの記述順序はきちんと保ったまま、絶対配置でなんとかしようとしてみました。見た目は整ったものの、セクションのレイヤーとサイドバーのレイヤーが重なってしまい、リンクボタンが機能しなくなってしまうなどの不具合がでてしまいました。

仮にコンテンツの記述順序がおかしくても、デザイン通りのレイアウトが実現されていれば、おそらくクライアントは何も指摘してこなかったと思います。ですが、適切なマークアップを行うことは、最終的にはエンドユーザーの利便性を担保することにつながります。誰に指摘されずとも、自分が関わる案件においては最低限実施しなければならないと心得ておくべきでしょう。

従来の方法では実現不可のようなので、CSS Gridを使用する

これはもう、これまで避けてきたCSS Gridを持ち出すしかない…!

IE・EdgeではCSS Gridの基本的なプロパティしかサポートしていないということだったので、果たしてクロスブラウザ対応ができるのかどうか、その点が不安でした。懸念していたのは、トラックの幅を定義するminmax()という記法が使えるかどうか。

というのも、受注案件はブレイクポイント600pxでPCとスマホの表示を切り分けているのですが、PC表示においてもコンテンツ幅は固定ではなく、画面幅に対してコンテンツとサイドバーの幅を%指定することになっており、いわばPC表示時もレスポンシブという珍妙な造りなのです。

が、危惧していた点は見事クリア!IE・Edgeよ!やればできるじゃん!

ということで、まずはグリッドコンテナを定義します。

その前に…CSS Gridを使用しない時は以下のCSSを記述するよう指定されています。

.main {
  float: left;
  max-width: 740px;
  width: 74%;
}
.side {
  float: right;
  max-width: 220px;
  width: 22%;
}

中央寄せされた1000pxのコンテナの中にメインコンテンツ740px、サイドバー220pxで配置されています。両者の間は40px。1000px以下の時は74%、22%が要素の幅になります(ホントはdisplay:flexトカ使いたいけど、ココの記述は変えるなって言われている…マークアップの精度を気にしない割には古いやり方に固執するクライアントさん(^_^;))。

CSS Gridを使用しない場合のレイアウト

グリッドコンテナは次のように定義しました

.grid {
  display: grid;
  grid-template-columns: 1fr minmax(444px, 740px) minmax(24px, 40px) minmax(132px, 220px) 1fr;
  grid-template-rows: auto auto auto;
}

2カラムレイアウトになるのは600pxまでなので、600pxの時の74%、22%の値をそれぞれ最小値として指定しています。

Gridの定義

このグリッドコンテナの中に、グリッドアイテムを配置していきます。

マークアップはとてもシンプル!

<div class="grid">
 <section class="sec01">セクション1</section>
 <section class="sec02">セクション2</section>
 <section class="sec03">セクション3</section>
 <aside class="side">サイドバー</aside>
</div>

さしあたってIE・Edgeのことは無視して、次のようにCSSを記述しました(省略できるプロパティは極力省略しています)。

.sec01 {
  grid-column: 2;
}
.sec02 {
  grid-row: 2;
  grid-column: 1 / -1;
}
.sec03 {
  grid-row: 3;
  grid-column: 1 / -1;
}
.side {
  grid-column: 4;
}

すると次の図のようなレイアウトに!

グリッドアイテムを配置

次に、セクション2,3内のヘッダーとコンテンツの要素もグリッドコンテナとします。すなわちグリッドコンテナを入れ子にします。それぞれの中にグリッドアイテムを配置していきます。

マークアップはこんな感じ。グリッドコンテナのトラックの幅は先に定義したものと同じなので、gridというクラス名を再び使用します。

<section class="sec02">
  <header class="grid">
    <h2 class="grid_item">セクション2のヘッダー</h2>
  </header>
  <div class="grid">
    <div class="grid_item">セクション2のコンテンツ</div>
  </div>
</section>

グリッドコンテナ内の要素には先に定義したセクション1と同じルールセットを記述をすれば良さそうです。

.grid_item {
    grid-column: 2;
}

そしてセクションのヘッダーに背景色をつければ、横方向に永遠に広がってくれます。

グリッドコンテナを入れ子に

まとめ

ココまでのマークアップ、CSSをまとめてみました。IE・Edgeの対応もしてありますよ(^^)/

See the Pen grid02 by keiko (@kamekon) on CodePen.0

実は、案件作業中はグリッドコンテナを入れ子にすることを思いつけず、もうちょっと複雑なマークアップになっていましたが、今回ブログを書くにあたってよりシンプルな記述に改めました。案件終了後の復習って、意外と気づきがあるものですね。今後も新しいことにチャレンジしたら、なるべく日を置かずにまとめるよう努めます。なによりも、ジブン自身のために\(^O^)/

下記はブログを書くにあたって参考にした…というわけではないのですが、最近見つけたCSS Grid関連の実用例と、基本を学べる無料のレッスンサイト。

CSS Gridについてはまだまだ物にできていない気がするので、無料レッスンは後日一通り受けてみようと思っています。