段組みのCSS。

ページレイアウトに段組みはつきもの。Webデザインでは、CSSで段組みを行います。ちょっと前までは“よこ並び”も“段組み”もfloatプロパティひとつでまかなってました。けれど今は、シチュエーションごとにいろんなプロパティが用意されて、うまく使い分けることで、より効率よくページレイアウトができるようになってきました。
そんなわけでここでは「段組みするためのCSS」を、従来いにしえの方法から最新イマドキの方法まで、順番に見ていくことにします:Dこの記事は、よこ並びのCSS。という記事の続きになります。

以下は目次です。クリックするとそのセクションへ移動します。

段組み?

段組とは、“段”で組むレイアウトのこと。ページの内容を“カラム”で区切って並べるレイアウトのことをいいます。
ただし、レイアウトするのが、紙媒体の時と、Webページの時とで、ちょっと意味合いが変わってきます。

紙の段組、Webの段組み

新聞や雑誌などのデザイン(エディトリアルデザイン)で段組というと、文章を読みやすくするために、1行あたりの文字数を適度に区切って、複数の列に分割するレイアウトのことをいう場合が多いです。
一方、Webデザインで段組みというと、Webサイトを使いやすくするために、機能や役割ごとにエリアを仕分けるレイアウトのことをいいます。
エディトリアルデザインでは可読性のためだけれど、Webデザインでは操作性のため、というふうに目的が違うんですね。なので、Webデザインで“段組みレイアウト”というと、文章まわりに限らず、ページ全体のレイアウトを指すことが多いです。

新聞や雑誌の段組と、Webの段組み。

とはいえ、Webでも、文章を読みやすくする目的のレイアウトを組むこともできる(※詳しくは後述)ので、ごっちゃになるといけないから、この記事では、可読性の方を“段組だんぐみ”、操作性の方を“段組みカラム”と呼び分けることにします:)(※Webの方だけ送り仮名を付けて、心の中で「カラム」と読みます。)

Webの段組みレイアウト

Webで段組みレイアウトといえば「2段組みレイアウト」が、いわゆるいちばん普通なレイアウトです。もっぱら、「メニューの段」と、「コンテンツの段」に分けられることが多いです。
企業サイトやECサイトみたく、紹介するサービスや情報が多くサイトの構造が複雑になっちゃいそうなサイトでよく採用されてますねー。

2カラムレイアウト、最もWebなレイアウト。

目次に戻る

つくるレイアウト

この記事では、右図のようなデザインを作ってゆくことにします。

一番上のヘッダーにはロゴとナビゲーションがあって、メインビジュアルの下のコンテンツ部分が2段組みになっていて、コンテンツの途中にも2段組みのバナーとか、3段組みの商品一覧があったりして、フッターには多段組みのサイトマップが配置されてる。
割とよくあるタイプのレイアウトを詰め合わせた感じとなっております。

ヘッダーのナビゲーション商品一覧は、「よこ並びのCSS。」でやったのと同じですね。段組みとは、つまり要素を並べることなので、「よこ並びのCSS。」と同じことなのですけれど、ページレイアウトなりの勘所があるので、おさらいしながら順番に見ていくことにします。

下準備

HTMLは以下のようにマークアップしました。
ページ全体を、ヘッダー(header要素)と、コンテンツ(#content要素)と、フッター(footer要素)のエリアに分けて、コンテンツの中に、メインコンテンツ(main要素)と、サイドメニュー(aside要素)が入っていて、メインコンテンツとサイドメニューの中に、商品一覧や記事一覧などのセクションがあります。

レイアウトを作るにあたって、以下のルールを決めます。横幅に対してレスポンシブなレイアウトになる想定です:)なので、スマホで見ている人にはわけわかめかもしれません、ごめんなさい…X(

  • 2段組みレイアウトになるのは、ウィンドウ幅が768px以上の時。最大幅は1200pxで中央揃え。
  • 1200px未満はウィンドウ幅に合わせて、メインコンテンツとサイドメニューを同じ比率で伸縮。
  • 768px未満(=767px以下)の時には、1段組みレイアウト

つまり下図のようなことになります! その他の細かなところは、コーディングしながら決めてゆきます。:D

作るレイアウトのルール。

デザインは決まってるので、段組みレイアウト以外のスタイルだけ先に作っちゃっときます:D! サイトのタイトルをロゴっぽくしたり、リンクを推しやすくしたり、画像が親要素からはみ出ないようにしたり、角を丸くしたり、フォントサイズを調整したり…。

ぜんぶ縦に並んでるだけですけれど、768px未満の時はもともと1段組みの予定なので、このままでもほとんど完成してますね…。はてさて、前提条件はこんなところで、早速レイアウトしてまいりましょー!X)

目次に戻る

フロートで2段組みレイアウト。

floatプロパティは本来、特定の要素を左右に寄せて配置するためのプロパティですけれど、ここではページレイアウトのために使用します。ページ内の段組みするところと、よこ並びするところを、floatプロパティを使ってレイアウトしてゆきます:)

ヘッダーは2段組み、ナビゲーションはよこ並び

サイトタイトルはleftを指定して左へ寄せて、ナビゲーションはrightで右へ寄せます。ナビゲーションボタンはすべてleftでよこ並びにして、ボタンとボタンの境をわかりやすいように、li要素の左側にボーダーを引きます。
2段組みになるのは768px以上の時に決めたので、最初はなからメディアクエリで限定しておけば良いですね。
clearfixは、前回の記事に引き続き、.cfというクラスに適用することにします。

もうちょっとヘッダーの高さを広げて、サイトタイトルとナビゲーションの高さも揃えたいな…。
サイトタイトルもナビゲーションも改行しそうにない、こんな状況なら、line-heightプロパティで調整するのが手っ取り早くてよいです。nav要素にline-height: 80pxと指定すれば、サイトタイトルとナビゲーションもろとも、行の高さが80pxになって、テキストが中央に揃います。;)
となると.nav-list aに指定してるパディングが余計なので、上下のパディングだけ0にしちゃいます。

line-heightをpx指定で、文字サイズに関わらず行高が揃う。

767px以下になるとナビゲーションボタンも縦に並ぶけれど、ボタンはまだ、よこ並びのままでいいかなと思います。もうひとつメディアクエリを用意して、ナビゲーションボタンのよこ並びだけ、415px以上の時に適用するように移動することにします。これでナビゲーションボタンがたて並びになるのは415px未満(414px以下)の時になります。

むむ、767px以下の時、ナビゲーションが左に片寄ってます…。フロートすると、要素の横幅は、その内容に準拠した大きさになるんでした…。さらにメディアクエリを用意して、767px以下の時には5つのボタンが横幅いっぱい均等に並ぶように、li要素の横幅を20%に指定します。この時、一番左側のボーダーはいらないので、ひとつめのli要素はborder-left: 0と指定しておきます。

画面幅を狭くしてゆくと、だんだんテキストが見切れちゃいます…。テキストを中央配置してるのだから、左右のパディングはなくてもいいくらい。なので0にしちゃいます。
414px以下の時にも、li要素に横幅20%が適用されちゃってるので、さらにさらにメディアクエリを用意して、414px以下の時には、li要素の横幅をautoにしておきます。
これにてヘッダー落着!

目次に戻る

メインコンテンツとサイドメニューの2段組み

メインコンテンツを左にフロート、サイドメニューを右にフロートします。フロートするだけでは、要素の内容に合わせて横幅が広がったまま、よこ並びにならないので、横幅を指定しないといけません。
ここでは、メインコンテンツの横幅をcalc(75% - 20px)、サイドメニューの横幅をcalc(25% - 20px)と指定することにしました。これで、メインコンテンツとサイドメニューが「3対1」の割合で、間に40pxの隙間を持った2段組みになるって寸法です;D例によって、メディアクエリで768px以上の時に限定しておきます。

メインコンテンツと、サイドメニューの横幅

続いて、それぞれのセクションを段組みしてゆきます!

メインコンテンツのバナーを2段組み

ここも前述の2段組みと同じですねー。最初のli要素を左へ、ふたつめのli要素を右へフロート。間に16pxの隙間を空けるとして、li要素の横幅を50% - 8pxと指定すればいっちょあがり。
ここは画面幅が狭い時でも、ずっと2段組みでいいかなと思うので、メディアクエリには入れないでおきます。

目次に戻る

商品一覧と記事一覧をよこ並び

よこ並びにするところは、まとめてレイアウトしちゃいます!
商品一覧も、記事一覧も、li要素はすべてfloat: leftで並べて、隙間はパディングで空けるようにします。商品一覧は横幅を33.333333%で、左側に32pxのパディング。記事一覧は横幅を50%で、左側に16pxのパディングを指定します。このままだとパディング分、一覧全体が右に片寄ってしまうので、ul要素の左側に、パディングと同じ分のネガティブマージンを指定することで、一覧全体を元の位置へ戻しています。
※行の先頭の要素には、clearプロパティを指定するのも忘れずに(詳しくは「よこ並びのCSS。」という記事を参照のこと)。

ネガティブマージン分、ul要素が右側に伸びる

box-sizing: border-boxを指定してあるので、widthプロパティの値は、パディングも含めた値として適用される。

商品一覧は、画面幅が狭い時に3列のままだと商品が小さくなりすぎるので、414px以下の時を境に2列になるようにしたいと思います。

画面幅が狭い時は、サイドメニューの最後のバナーもよこ並び。

逆に、記事一覧は、1段組みになった時に2列のままだと大きく感じるので、767px以下の時には4列にしちゃいます。ついでに、サイドメニューの最後のバナーも、767px以下の時にはよこ並びになるようにします。

あらら、414px以下の時に商品一覧がぐちゃっちゃいますね…。414px以下の時にまで:nth-child(3n+1)に指定したクリアが適用されてしまってるので、この指定は415px以上の時用のメディアクエリを新設して、移動しておきます。

改行される要素のところで、フロートをクリア。

記事一覧のところも、767px以下の時にまで:nth-child(2n+1)のクリアが適用されてしまっているので、この指定は768px以上の時だけにしないといけません。
ただ、414px以下の時に4列のままだと小さすぎちゃうので、414px以下になったら2列に戻したい…。つまり、4つ並べるのは767px以下〜415px以上の時という事なので、メディアクエリでもそのように限定します!なので、クリアするのはその逆の768px以上、もしくは414px以下の時ということになりますねー。そしてついでの、サイドメニューの最後のバナーも、414px以下の時には2列にすることにします。

767px以下〜415px以上の時というメディアクエリ
  1. @media (max-width: 767px) and (min-width: 415px) {}
768px以上、もしくは414px以下の時というメディアクエリ
  1. @media (min-width: 768px), (max-width: 414px) {}

あと、画像サイズに対して、隙間が広く感じるので、画面幅が狭い時には列の隙間も狭くしたいです。ここでは767px以下の時、商品一覧のところは16px、記事一覧とバナー一覧では8pxになるようにします。414px以下の時には、商品一覧も8pxにします。

そんなこんなで、バナー一覧、商品一覧、記事一覧が整いました!

目次に戻る

文章を画像に回り込ませる

商品一覧の下の、文章中に画像があるところは、floatプロパティの専売特許ですね!
画像を左右に寄せたらば、右に寄せた画像には左側にマージン、左に寄せた画像には右側にマージンを、ここでは24px空けました。

画面幅が狭くなると回り込んでるテキストが窮屈になってくるので、414px以下の時には画像の横幅を50%となるようにして、画像とテキストの隙間もちょっと狭く、16pxにします。
あと、画像の上辺が文章に比べて、ちょっと上気味なのが気になるので、ちょちょっと調整して、できあがり。

お知らせ一覧を2段組み

ここは、前述の画像を回り込ませるのと同じ方法で、内容(dd要素)に日付(dt要素)を回り込ませるってことをします。なので、floatプロパティを指定するのは日付に対してだけ。そしてdt要素の横幅を、日付が入り切るくらいちょっと余裕を持って指定します。ここでは9.6文字分9.6emとしました。

dd要素自体は、dt要素の下に入り込んだまま。

これだけでも大丈夫そうですけれど、画面幅を狭めていくと、内容の3行めが、日付の下に回り込んじゃうので、内容の左側に日付の幅と同じ分だけのパディングを指定。そしたら、dt要素の横幅は指定しなくてもよくなりますね…¦(、とっちゃいます。

あまり画面幅が狭いと、内容が改行しすぎなので、日付と内容を横に並べるのは415px以上の時だけにすることにします。
すると、414px以下の時には、日付と内容が縦に並ぶことになるので、dt要素には上だけ、dd要素は下だけにパディングを指定して、できあがり!

目次に戻る

フッターのサイトマップを多段組み

サイトマップを5列並ぶようにレイアウトします。
まずは、.sitemap-list .groupという要素をよこ並びにして、横幅を20%に指定します。例によって768px以上限定です。

マークアップ上「Lopan Cafeについて」、「メニュー」、「店舗検索」、「お知らせ」、「企業情報」と「その他(プライバシーポリシーとか)」の6つにグループ分けしてるので、よこ並びにするだけじゃデザイン通りにはならないのですね…。「お知らせ」を「店舗検索」の下にレイアウトしたいのだけれど…。

そこで、「お知らせ」のグループにだけ、左側にグループひとつ分のネガティブマージン-20%を指定します。

これでデザイン通り5列になったけれど、「お知らせ」と「店舗検索」が重なっちゃったので、「お知らせ」の上にパディングを指定して、いいくらいの位置まで下げます。となりの「会社案内」と揃うといいかなと思います。となると、「店舗検索」の高さ分パディングを指定すれば、「会社案内」と同じ高さまで下がるはず。
「店舗検索」の高さは、「行の高さ + 上下のパディングとマージンの値」で算出できそうです。行の高さは、「文字サイズ × line-heightプロパティの値」なので、つまり1.3rem * 1.4 + .9emということ!これをそのまま上パディングとして指定します。

「店舗検索」の高さ

あと、リンクの矢印が隣のグループと引っ付いて見えるので、グループとグループの間に隙間を空けたいです。商品一覧とかと同じように、li要素の左側にパディングを指定して、ズレたul要素をネガティブマージンで元の位置に戻したら、できあがりー!

目次に戻る

テーブルレイアウトで2段組みレイアウト。

続いて、displayプロパティの値tabletable-cellを利用して、レイアウトを作ってゆきたいと思います。
と言っても、floatプロパティを使ったレイアウトの項で、メディアクエリの細かいポイントは整理できたので、あとは、フロートしてたところを、テーブルレイアウトで置き換えてゆくだけ、なはずです!

ヘッダーとナビゲーション

ひとまず、フロートの時のメディアクエリはそのままに、フロートしていた要素をテーブルレイアウトに置き換えます。
nav要素とナビゲーションにdisplay: table(テーブル)を指定して、サイトタイトルとナビゲーションボタンにはdisplay: table-cell(テーブルセル)を指定します。
ナビゲーションは、415px以上の時にはtableが適用されますが、768px以上の時にはtable-cellに上書きされることになります。

うん、中央に寄っちゃいました。テーブル要素は、特に横幅の指定がないと、その内容にぴったりなサイズになってしまうので、nav要素をヘッダー内いっぱいに広げるために、nav要素の横幅を100%に指定します。
それから、767px以下の時にはナビゲーションが横幅いっぱいになるよう、ナビゲーションの横幅を100%に指定。

縦方向の位置が、今はbaselineに揃っている状態なので、これを中央揃えにするため、table-cellを指定している要素にvertical-alignプロパティmiddleを指定します。

横スクロールバーが表示されるようになっちゃいました…
実は、nav要素に、最大幅を1200pxにしつつ、両脇に16pxのパディングをつけるために、box-sizingプロパティcontent-boxを指定してたんでしたXp。なので、ヘッダーいっぱいに広げるためにはcalc(100% - 32px)と指定しなくちゃいけません…。なんだかヤなので、nav要素へ横幅を指定するのはやめて、サイトタイトルの横幅を大きめに指定することで、テーブル要素を内側から広げるようにしたいと思います後述

あと、767px以下の時ナビゲーションボタンが均等になるところは、せっかくテーブルレイアウトなのでtable-layoutプロパティの値をfixedとすることで均等に割り付けるようにします。
テーブルレイアウトのヘッダー完成ー:D

目次に戻る

メインコンテンツとサイドメニュー

続いて、コンテンツエリアをテーブルレイアウトで2段組みです。
さっそく、#contents要素にtable、メインコンテンツとサイドメニューにtable-cellを指定します。
ただし、前述の自動テーブルレイアウトアルゴリズムの所為で、テーブルセルに横幅を指定しても思い通りの横幅にはならないため、メインコンテンツには75%、サイドメニューには25%を指定して、メインコンテンツとサイドメニューの隙間は、それぞれの内側にパディングで空けることにします。

メインビジュアルもいっしょくたに横に並んでしまいました…。テーブルセルはみなよこ並びになってしまうんです…。
そこで、メインビジュアルにはdisplay: table-captionを指定します。テーブルキャプションならテーブルの上部に鎮座してくれるはずです。

ただし、テーブルキャプションはテーブル要素に指定してるパディングは無視して鎮座してしまうので、テーブル要素(#contents要素)に指定している左右のパディングをもう一度、メインビジュアルにも指定してやります。
あとは、メインコンテンツとサイドメニューの縦方向の位置を上辺で揃えるために、table-cellを指定した要素にvertical-align: topを指定すれば、いっちょあがり。

メインコンテンツのバナー

ここも、コンテンツエリアの2段組みと同じ要領で、テーブルレイアウトに置き換えればよいですねー。
ul要素にはtable、li要素にはtable-cellを指定して、横幅は50%に指定します。隙間を16px空けるために、ひとつめのli要素は右側に、ふたつめは左側に8pxずつパディングを指定します。767px以下の時は8pxなので、4pxずつにすればできあがり。

目次に戻る

商品一覧と記事一覧

これらもひとまず、フロートしてた部分をテーブルレイアウトに書き換えてゆきます!
それぞれ、ul要素にはtable、li要素にはtable-cellを指定して、フロートの時と同じように、li要素の左側にパディングで隙間を空けて、ul要素のズレをネガティブマージンで戻します。
案の定、こんな感じになります。やっぱり、ひどく申し訳ない気持ちになりますね…。X(

商品一覧みたく、複数行に渡る一覧はテーブルレイアウトには向いてないです(「よこ並びのCSS。」参照のこと)

どうしてもテーブルレイアウトじゃなきゃいやだ、という場合には、水平にスクロールするコンテンツにしちゃう手があります。
テーブルセル(li要素)には、横幅を指定しても、親要素の横幅に合わせて調整されちゃうので、一定サイズより小さくならないように、最小幅を指定しておくことにします。
ul要素には、ちょっと横着して、display: tableを指定しません。ブロック要素のままにしておくことで、明示的に横幅を指定してoverflow: autoを指定した時に、横スクロールバーが表示されるようになります。同じように、サイドメニューの記事一覧とバナー一覧も、スクロールバーが出るように指定してます。
どうせスクロールするやつなので、li要素の横幅は固定にしちゃって良いかもしれません。

一覧をスクロールすると、左側の見切れる位置が、セクションエリアからはみ出しちゃってますね…。ul要素を左にズラすと、見切れる位置ごとズレちゃうので、ul要素にネガティブマージンは指定しない方が良さそうですね…。代わりに、li要素の最初のパディングを0にします。

最初の画像だけ大きくなっちゃいましたね。content-boxプロパティでborder-boxが指定されてるため、パディングがない最初のli要素だけ、横幅が広がっちゃうんです…。なので、li要素にはcontent-boxを指定して、widthプロパティの値にパディングを含めないようにすれば万事解決:)
li要素の隙間をちょちょっと調整したら、できあがり!

フッターのサイトマップ

画像の回り込みのところとお知らせ一覧は、テーブルレイアウトではどうしても難しそうなのでパス…。
最後に、フッターの多段組みを、テーブルでレイアウトします。ここもひとまず、フロートしてたところをテーブルレイアウトに置き換えるカタチで、.sitemap-listtable、横幅を100%に指定して、.grouptable-cellを指定します。

やっぱり、テーブルセルにはマージンが適用されないから、全部よこに並んで、最後のグループが潰れちゃいました…。5列は諦めて、6列にするしかないかな…。せめて、グループに横幅を指定するのはやめて、table-layout: fixedで自動的に均等に割り付けるようにしましょう。
テーブルレイアウトで2段組みレイアウト、おしまーい!

目次に戻る

インライン・ブロックで2段組みレイアウト。

続いて、displayプロパティの値inline-blockを使って、ページをレイアウトしてゆきます。テーブルレイアウトの時と同じく、フロートしてたところを、インライン・ブロックに置き換えながら、調整するだけのかんたんな作業です。

ヘッダーとナビゲーション

ひとまず、フロートの時のメディアクエリはそのままに、サイトタイトルとナビゲーション、ナビゲーションボタンにdisplay: inline-blockを指定してみます。

妙な隙間をなくすには、letter-spacingプロパティで文字間を調整すれば良いんでした。それから、縦方向の位置をvertical-alignプロパティでmiddleに揃えます。※詳しくは「よこ並びのCSS。」という記事を参照のこと。

インライン・ブロックな要素を右側に寄せるには、その親要素にtext-align: rightを指定すれば、右揃えになるのですけれど、それだとサイトタイトルごと右へ寄ってしまいます。なのでここでは、ul要素をヘッダーの右側いっぱいにまで広げて、li要素を右揃えにすることで、ナビゲーションボタンだけ右側へ寄せることにします。
そのために、まず、サイトタイトルの横幅を200pxに固定。ul要素にはその残りの幅100% - 200pxを指定することで、サイトタイトルとナビゲーションが、ヘッダーにみっちり配置されるはずです。

サイトタイトルとナビゲーションをヘッダー内にみっちり並べて、ナビゲーションボタンを右揃えに。

ナビゲーションの上にほんのちょっと隙間ができちゃってるので、縦方向の位置はtopに揃えることにします。

横幅が狭い時のレイアウトは、フロートの時と同じままで問題なさそうですねー。ヘッダー落着!

目次に戻る

メインコンテンツとサイドメニュー

ひとまず、#contents要素に、妙な隙間を消すためのletter-spacingを指定して、main要素とaside要素をインライン・ブロックにします。それぞれ横幅を指定して、メインコンテンツとサイドメニューの隙間は、テーブルレイアウトの時と同じ要領で内側にパディングで空けて、vertical-align: topで上揃えにすれば、整いました!

バナーと商品一覧と記事一覧

バナーのところは前述の方法と同じでうまくいきそうです。
妙な隙間を消す術を施しつつ、li要素をインライン・ブロックに。横幅を50%にして、ひとつめのli要素は右側にパディング、ふたつめは左側にパディングを指定で、できあがり。

商品一覧と記事一覧も同じく、妙な隙間を消す術を施しつつ、li要素をインライン・ブロックに。隙間の空け方は、フロートの時と同じように、li要素の左側にパディングで隙間を空けて、ul要素のズレをネガティブマージンで元に戻せば、あっというまに整いました!XD

お知らせ一覧

インライン・ブロックもやっぱり、画像の回り込みは難しいのでパスして、お知らせ一覧をレイアウトします。
ひとまず、日付と内容をインライン・ブロックにして。例によって、妙な隙間を埋める術も施します。
あとは、ヘッダーと同じ要領で、dl要素の中に、日付と内容をみっちり並べるように、日付(dt要素)の横幅を9.6em、内容(dd要素)の横幅を100% - 9.6emという風に指定します。

綺麗に並んだけれど、ボーダーが途中で途切れちゃってますね…。フロートの時はdd要素が日付の下に入り込んでたので、日付の下までボーダーが引かれてたのだけれど、インライン・ブロックはdd要素ごと隣に並んでるだけなので、ボーダーが内容の下にしか引かれないんですね。
フロートした時と同じ状況を作るべく、dd要素にネガティブマージンを指定して、dt要素の範囲までdd要素を伸ばして、そのあとパディングで元の位置に戻す、という風にしてみます。

うまくいくかなと思ったけれど、ぐちゃぐちゃ…。ネガティブマージンを指定した分、右側に空きができてしまったので、そこに日付が並んでしまって、次の内容がdl要素の先頭にきちゃったもんだから、そこからネガティブマージンで枠の外へハミ出しちゃって、大変なことになってます。X(

ネガティブマージンとパディングの状態

内容の横幅は100%にすれば良いということ。できました!

フッターのサイトマップ

フロートでのレイアウトと同じ要領で、フロートしてた要素.groupをインライン・ブロックに変えるだけ(もちろん妙な隙間を埋める術も施しつつ)で、なんともはやできちゃいました…!
インライン・ブロックで2段組みレイアウト、完成ー!

目次に戻る

フレキシブルボックスで2段組みレイアウト。

displayプロパティの値flexは、フレキシブルな要素の配置が得意なレイアウトモード。本来はコンポーネント単位で使用するプロパティですけれど、ここではページレイアウトに使用してみます。
フレキシブル(柔軟な)レイアウトは、レスポンシブ(反応性)デザインとも相性が良いのです:)

ヘッダーとナビゲーション

フレキシブルボックスレイアウトでは、displayプロパティの値をflexと指定した要素(コンテナ)の、直接の子要素(アイテム)が、フレキシブルにレイアウトできるようになる、というものでした。※詳しくは「よこ並びのCSS。」という記事を参照のこと。
ここでは、サイトタイトルとナビゲーションを2段組みにするため、その親要素の「nav要素」と、ナビゲーションボタンをよこ並びにするため、その親要素の「ul要素」に、それぞれdisplay: flexを指定します。

すると、あっという間にすべてよこ並びになりました。あとは、サイトタイトルとナビゲーションを左右に寄せるだけですが、これも、フレキシブルボックスレイアウトでは、親要素への指定だけでレイアウトできちゃいます。justify-contentプロパティは、アイテムの並ばせ方を調整することができるプロパティ。ここでは、アイテムを端から端へ均等に並べるためのspace-betweenという値を指定します。
それから、767px以下の時のナビゲーションボタンの横幅は、widthプロパティでなく、flex-basisプロパティで指定することにします。すると、414px以下の時にフレキシブルな要素でないナビゲーションボタンにこの指定は影響しないので、414px以下のメディアクエリは不要になりますね!
ヘッダーできあがり!

メインコンテンツとサイドメニュー

メインコンテンツとサイドメニューをよこ並びにするために、#contents要素にdisplay: flexを指定。それぞれの横幅は、flex-basisプロパティで指定します。ここでは、フロートの時と同じように、メインコンテンツの横幅をcalc(75% - 20px)、サイドメニューの横幅をcalc(25% -20px)という風に指定することにします。
それから、ヘッダーの時と同じように、アイテムを両端に寄せて並べるために、justify-contentプロパティも指定します。

ぜんぶよこ並びになっちゃいました!フレキシブルボックスレイアウトはデフォルトの状態では、複数行に折り返さないようになってるんです。親要素にflex-wrapプロパティwrapと指定することで、折り返しを解禁してあげます。メインビジュアルが横幅いっぱいの大きな画像なので、メインコンテンツとサイドメニューが改行して、レイアウトされるようになります。

続いて、それぞれのセクションをレイアウトしてゆきます!

バナーと商品一覧と記事一覧

バナーのとこも前述と同じ要領で、フレキシブルボックスにして、justify-contentプロパティで両端に寄せて並べて、アイテムの横幅をflex-basisプロパティで指定、すればよいですねー。

商品一覧と記事一覧は、それぞれ、ul要素をフレキシブルボックスにして、アイテムの横幅を、隙間の分を差し引いたサイズに指定すればいっちょあがりです!フレキシブルボックスなら、justify-contentプロパティで、両端に揃えて均等に配置することができるので、パディングで隙間を空けてネガティブマージンで戻すなんてことしなくて良いんですね!

ただ、3つ以上よこ並びする時、今までと同じ隙間にするためには、ちょっと計算が必要です…。
商品一覧の隙間を、32pxずつ空けたい場合、アイテムの横幅はcalc(33.333333% - 32px)じゃダメで、calc(33.333333% - 21.3px)にしないといけません。隙間は全部で64px空くことになるので、これを3つのアイテムの横幅から均等に差引かなきゃいけないということなんですねー(下図参照)

隙間の合計を、アイテムの数で分配した分を、横幅から差し引く。

目次に戻る

お知らせ一覧

フレキシブルボックスレイアウトでもやっぱり、画像の回り込みは難しいのでパスして、お知らせ一覧をレイアウトします。
インライン・ブロックの時と同じく、日付と内容をみっちり幅で横に並べてレイアウトすることになります。
フレキシブルボックスなら、並べた要素(ここでは日付と内容)の高さを揃えることができるので、仕切りのボーダーは、dt/dd要素それぞれに指定することにします。
ただし、最後のdt/dd要素にはボーダーは引かないように、:not(:last-of-type)という書き方でもってボーダーを指定します。

フッターのサイトマップ

よこ並びにする要素の親要素の.sitemap-listをフレキシブルボックスにして、justify-contentプロパティで両端に寄せて並べます。アイテムの横幅は、商品一覧の時と同じく、隙間の合計を均等に差し引いた分を指定します。アイテムは6つあるけれど、5列にするので、隙間の合計は16px * 4で、アイテムの横幅は20% - 64px / 520% - 12.8pxってことになります。

ちょっと「店舗検索」と「お知らせ」がズレちゃいましたね…。「お知らせ」のグループの左側に指定するネガティブマージンは、グループひとつ分にしなきゃいけません。
グループひとつ分の横幅は、20% - 12.8pxと思いきや、この横幅の要素が16pxの隙間を空けつつ、端から端まで均等に並んでるのだから、20% - 12.8px + 16pxということになります。ネガティブマージンなので-(20% - 12.8px + 16px)、つまり-20% + 12.8px - 16px、すなわち-20% - 3.2pxを、左側のマージンに指定すれば良いってことですねー⁑|

グループひとつ分の横幅。

目次に戻る

カラムレイアウト。

ここまで、“floatプロパティ”と、“displayプロパティを使った3つのレイアウトモードtableinline-blockflex”を使って、2段組みレイアウトをしてきました。次は、冒頭でも書いてた、文章を読みやすくする目的のレイアウトを組むために用意された、“段組”のためのプロパティで、2段組みレイアウトしてみたいと思います!

段組のためのCSS

CSSで、文章を読みやすくするレイアウトを作るために、columnsプロパティが用意されています。これを使えば、Webでもエディトリアルデザインでいうところの“段組”を作ることができます。
例えばcolumnsプロパティに任意の整数を指定すれば、その要素の内容を指定した数に分割して、段組でレイアウトされます。
ここでは“2段組”で、段の間隔column-gapを2文字分空けて、段の間に1pxの仕切り線を入れてみました。仕切り線は、段の隙間のちょうど真ん中を通るように引かれます。

  1. columns: 2;
  2. column-rule: 1px solid #cdcdcd;
  3. column-gap: 2em;

上の例では画面幅を狭めてもずっと2段組でレイアウトされ続けるのですけれど、単位付きの値を指定すれば、その要素の内容をその幅が入り切るように分割するようになります。試しにここでは、ひとつの段の幅を12文字分12emとなるように指定してみました。画面幅に合わせて、1段あたり12文字を目安に、段数がいい具合に切り替わるようになってると思います。

  1. columns: 12em;
  2. column-rule: 1px dotted #cdcdcd;
  3. column-gap: 3em;

columnsプロパティには、段数段の幅を同時に指定することもできて、下記のように、2つの値を半角スペースで区切って指定します。ここでは、段数は2段に制限しつつ、段の幅が12文字未満になると1段に切り替わるようになってるはずです。完全に成り行きですけれど、「これぞWeb」って感じがしますよねー:D

  1. columns: 2 12em;
  2. column-rule: 1px dashed #cdcdcd;
  3. column-gap: 4em;

ただし、columnsプロパティは、上で見てきたように、段を等分することしかできないので、ページ全体のレイアウトには不向き。なのですが、ここではちょっと無理して、ページレイアウトに使ってゆきたいと思います:D
※この記事では、columnsプロパティを使ってページレイアウトすることを、“カラムレイアウト”と表記することにします。

目次に戻る

ヘッダーとナビゲーション

まずは、ヘッダー部分です!
おもむろに、nav要素に対してcolumns: 2を指定、ナビゲーションにはcolumns: 5を指定します。※メディアクエリなどはフロートの時の指定をそのままです。

なんだかいい感じにレイアウトされたかもしれないですね(無理してる割に)。ナビゲーションボタンの間に妙な隙間ができてるのと、テキストが中央に揃っていないのが惜しいです…!妙な隙間はcolumn-gapプロパティのデフォルトの値が関係しているのかな、と思うので、column-gap: 0にしてみます。あとは、a要素の左右のパディングを無くして、テキストを中央揃えにしたら、いい感じになりました。

767px以下の時にボタンが小さくなりすぎるのは、どうやらナビゲーションボタンの横幅に20%を指定しているのが原因のようです。li要素の中で20%の横幅になっちゃうみたいですね。横幅の指定を削除したら、整いました!

メインコンテンツとサイドメニュー

ここも一旦おもむろに、#contentsに対してcolumns: 2を指定します。なんと、コンテンツエリアの内容が全部そのまま2段組に流し込まれてるんですね、おもしろい。けど、メインビジュアルだけは横いっぱいに広げたいところ。テーブルレイアウトでいう“テーブルキャプション”みたいなことができたらいいんだけれど…。

column-spanプロパティを使えば、カラムレイアウトにおいて、特定の要素を、列をまたぐように配置することができます。ここでは、allという値を指定して、すべてのカラムをまたぐように配置します。※値にはallnoneしか用意されてません。。
メインコンテンツとサイドメニューの間隔は、column-gapプロパティで指定します。

コンテンツエリアが等幅ではありますが、なんとなくレイアウトできていることとして、次へ進みたいと思います…!

メインコンテンツの内容がサイドメニュー側に流れ込んでしまってますが、お知らせ一覧はメインコンテンツの側に配置しておきたいところ…!
そんな時にはbreak-insideプロパティで調整します。これはカラムレイアウトした時の、改列(?)を制限するためのプロパティ。ここでは、main要素と、aside要素に対して、avoid(避ける)という値を指定します。これで、メインコンテンツとサイドメニューでは、その要素の最中で改列されることがなくなるはずです。
うん、ちゃんとお知らせ一覧がメインコンテンツの一番下に配置されるようになりましたね!

しかし、ここまでChromeでしか確認してませんでしたが、Firefoxで見てみると、メインビジュアルが横いっぱいに広がってないし、メインコンテンツとサイドメニューもごっちゃになったままだし…、最初のレイアウトから何も解決できてないじゃないですか…XOFirefoxは、column-spanプロパティbreak-insideプロパティもサポートしていないのですね…(2017年12月現在)
どうしてもcolumnsプロパティじゃなきゃいやだ、という場合には、マークアップで調整するしかないです…。

なので、ここでは、列をまたぐレイアウトは諦めて、メインビジュアル含めて2段組みのレイアウトで進めてゆこうと思います。ということで、column-spanプロパティとbreak-insideプロパティの指定はなくします。それから下準備の時に指定していた、メインビジュアルの高さを200pxより小さくしないための指定もなくしておきます。
こざっぱりしちゃいましたね。

とはいえ、商品一覧のあとの文章が、途中からメインコンテンツ側とサイドメニュー側をまたいでしまうのは、とても読みにくいので避けたいですね…。
Firefoxでは、break-insideプロパティはサポートされてないけれど、似たプロパティのpage-break-insideプロパティはサポートされてるので、このプロパティで代用してみようと思います。
page-break-insideプロパティは主に印刷時の改ページを制限するためのプロパティ。ここでは、section要素に対して、さっきと同じくavoidという値を指定します。

コンテンツエリアのレイアウトが落ち着いたので、それぞれのセクションを段組みしてゆきます!

目次に戻る

バナー一覧と商品一覧と記事一覧

ひとまず、よこ並びするul要素にcolumnsプロパティを指定して、li要素の隙間はcolumn-gapプロパティに置き換えてゆきます。

商品一覧の並び順が他のレイアウトと違うのは、やはりあくまで“段組”だから。なんたって成り行きなので、横方向の画像の位置を揃えるのは難しそうですね…。
けれど、商品一覧の商品説明が、文章の途中で次の列に分割されるのは避けたいです。ということで、ここでもpage-break-insideプロパティの出番です。商品一覧のli要素の途中では改ページしないように指定します。

サイドメニューの横幅が広くなったので、記事一覧は最初から4つ並びにして、li要素の隙間も狭めに調整します。最後のバナーも最初からよこ並びでよいかも。

記事一覧が、画面幅によって、2つめで改列したり改列しなかったりしてます。商品一覧みたく、li要素の途中で改列されちゃっているわけではないので、break-insideプロパティではなくて、break-afterプロパティというのを使って、li要素のの改列具合を制限することにします。この値にcolumnという値を指定すれば、その要素の後で、必ず改ページするようになるはずです。

一方Firefoxでは、商品一覧の改列する位置がいざこざしてます。li要素に加えて、li要素の子要素にもpage-break-inside: avoidを指定してみます。

いろいろ不具合もあるし、成り行きゆえに微調整が効かないのが難点ですね…。そもそもページレイアウトするためのプロパティではないことを忘れてはいけません…X|

文章中に画像があるところとお知らせ一覧

フロートで画像を回り込ませてたところと、お知らせ一覧にcolumnsプロパティを指定してみると、下のサンプルのようになりました。
お知らせ一覧は案の定という感じだけれど、フロートしてたところは、文章量のおかげもあるかもしれませんけれど、ちょうどいい感じに2列に分けられてるので、この際、画像回り込みはやめて、2段組レイアウトにしちゃおうと思います。お知らせ一覧はやっぱり見にくいので元に戻します。

画像は各列の横幅いっぱいに広げて、画像と文章の間に余白をつけて、列と列の間には仕切り線を入れてみようと思います。column-ruleプロパティでかんたんに仕切り線を入れられるのが、カラムレイアウトの素敵ポイントですよね。メインコンテンツの最初の文章のところも、同じ2段組に合わせておきましょう。
414px以下の時には2段組だと余計読みづらいからcolumns: 1にして、できあがり!

フッターのサイトマップ

ここも例によって、単純に、ul要素にcolumnsプロパティを指定して、隙間をcolumn-gapプロパティで空けるようにします。

なんだかとっても綺麗にレイアウトされましたね…!あとは改列する位置を制限すれば、全部うまくいきそうです。.sitemap-list .groupにpage-break-insideプロパティを指定します。
すると下のサンプルのように、なんの問題もなくレイアウトできちゃいました!

目次に戻る

グリッドレイアウト。

「グリッド」は、市松模様とか碁盤目みたいな“格子”を表す言葉で、グリッドレイアウトとは、縦線と横線で区切られた格子状のマス目を使って要素を配置するレイアウト手法のこと。CSSでマス目を作って、そのマス目に任意の要素を割り当てていく感覚で、画面をレイアウトしてゆくことができます。
フレキシブルボックスレイアウトが要素を柔軟にレイアウトするための仕様だとすれば、グリッドレイアウトは、要素を自由にレイアウトするための仕様ということになります!

グリッドレイアウトの方法

グリッドレイアウトは、displayプロパティの値に用意されたレイアウトモードのひとつ。
なので、使い方は、テーブルやフレキシブルボックスと同じように、displayプロパティでgridという値を指定すれば、その要素でグリッドが利用可能になります。また、gridを指定した要素は「コンテナ」と呼ばれ、その直接の子要素が「アイテム」と呼ばれる点は、フレキシブルボックスと一緒ですね。
ただし、それ以外はフレキシブルボックスと異なるどころか、CSS的にも全く新しいアプローチになるので、他のCSSのことはいったん忘れた方が良いかもしれません¦‹

グリッドレイアウトを行うには、まず、コンテナをグリッドに仕切るところから始まります。
コンテナを、縦横のラインで仕切って、仕切られてできたマス目の横の並びを行トラック、縦の並びを列トラックと呼びます。行トラックと列トラックが交わるひとつひとつのマス目のことを「セル」、セルをいくつか繋げてつくる区画を「エリア」と呼びます。
このエリアに、アイテム要素を割り当てることで、レイアウトを組み立てていく、という流れになります。
フロートや、フレキシブルボックスでは、要素を“流し込む”感覚でレイアウトしていたと思いますけれど、グリッドレイアウトでは、ちゃんとレイアウトすることができるレイアウトモードなんですね:o

CSSのグリッド構造と、各要素の呼び名

いろいろ機能があるので、プロパティがすごく大変そうですけれど、「できること」でいうと、フレキシブルボックスよりも少なめです(2017年12月現在)。大きく以下の3つの性質を決めるプロパティに分けられます。

セルのサイズ(横幅と高さ)を決めるプロパティ
grid(grid-template, grid-auto-rows / grid-auto-columns / grid-auto-flow, grid-gap)
grid-template(grid-template-rows / grid-template-columns, grid-template-areas)
セルとセルの隙間を指定するプロパティ
grid-gap(grid-row-gap / grid-column-gap)
アイテム要素を配置するエリアを決めるプロパティ
grid-area(grid-row-start / grid-column-start / grid-row-end / grid-column-end)

そのうち最初の2つは、コンテナとなる要素に指定するプロパティで、最後のはアイテム要素に指定します。
rowが行(上下方向の並び)で、columnが列(左右方向の並び)に対するプロパティを表します。

グリッドレイアウト関連のプロパティ相関図。

グリッドレイアウトの準備

例えば、以下のようなHTMLを用意して、グリッドレイアウトを適用すると要素がどう変化するのか、見ていきたいと思います。div要素の中にむっつのdiv要素が入っていて、コンテナとなる親要素にはcontainer、アイテムとなる子要素にはitemというclass名をつけてます。:)

HTML
  1. <div class="container">
  2. <div class="item">ひとつめのアイテム</div>
  3. <div class="item">ふたつめのアイテム</div>
  4. <div class="item">みっつめのアイテム</div>
  5. <div class="item">よっつめのアイテム</div>
  6. <div class="item">いつつめのアイテム</div>
  7. <div class="item">むっつめのアイテム</div>
  8. </div>

.container要素にグリッドレイアウトを適用すると、中のアイテムは以下のようになります。
見たところ特に何も変化がないように見えますけれど、ちゃんとグリッドは作られてます!いまはまだ、なにも仕切りを指定してないので、直接の子要素(アイテム)の数だけ自動的にグリッドが引かれて、縦1列のグリッドが作られている状態です。

CSS
  1. .container {
  2. display: grid;
  3. }

ここから、さらにグリッド関連のプロパティを使って、コンテナにグリッドを作って、レイアウトの基礎を用意します。
CSSで“グリッドを作る”といっても、ピンと来ないですよね…。ちょっと意味がわからないので、さっそく実際にグリッドを作ってゆきます!

グリッドをつくる

グリッドをつくるには、grid-templateプロパティを使います。例えば、ここでは100px / 100px 200px autoという値を指定します。すると下のサンプルのように、要素のレイアウトがガラッと変化しちゃいました!

  1. .container {
  2. display: grid;
  3. grid-template: 100px / 100px 200px auto;
  4. }

指定の仕方も何やら複雑ですね…、落ち着いて、ひとつずつ見ていきます。
上の指定では、最初の100px(縦方向の並び)の間隔、スラッシュを挟んで、100px 200px autoが、(横方向の並び)の間隔を表しています。これで、「1行めは高さ100px、2行め以降は指定がないので高さは成り行き」で、「1列めは横幅100px、2列めは200px、3列めはautoなので成り行き幅」というグリッドが作られることになります。

指定する順番は、rowが先

かんたんに言うと、grid-templateプロパティは「行の間隔と、列の間隔を指定して、グリッドを用意するプロパティ」ということになります。

それぞれ、値を半角スペースで区切って列挙することで、列の数、行の数が決まります。つまり、以下のように指定すれば、縦に2行、横に6列のグリッドが作られることになります。

  1. .container {
  2. display: grid;
  3. grid-template: 100px 200px / 100px 200px 100px 200px 100px 200px;
  4. }

アイテム要素が6つしかないので、2行めには、アイテム要素は何も配置されません。こんな場合、行に指定しているふたつめの値200pxはどうなるのかというと、レイアウト予定地として、スペースだけ確保された状態になります。
他のCSSプロパティは要素ありきで指定するのに対して、グリッドレイアウトは、要素がなくても、レイアウトのための骨格として余白を作っちゃうんですね:o

配置する要素がなくてもグリッドは用意されちゃう。

ここまでで、コンテナにグリッドを作って、レイアウトの基礎が用意できました。続いて、アイテム要素を、任意の場所に配置してゆきます。
今はアイテムの初期値autoによって、グリッドエリアに自動的に割り当てられた状態になってます。

アイテムを配置する

アイテムを任意のグリッドエリアに割り当てるには、grid-areaプロパティを使います。ここでは、以下のように、よっつめのアイテムに対して2 / 4という風に指定してみました。

  1. .item:nth-child(4) {
  2. grid-area: 2 / 4;
  3. background: yellowgreen;
  4. }

これもひとつずつ、詳しく見ていきましょう。
grid-areaプロパティの最初の値2は、グリッドの上から2本めのグリッドラインを指定していることを表します。スラッシュを挟んで、4は、グリッドの左から4本めのグリッドラインを指定していることを表します。
「2行め4列めのグリッドセル」という風に考えることもできるんですけれど、そうじゃなくて、グリッドラインを基準に数えるんですね。なんでこんな考え方をするのかというと、以下のような指定の仕方もできるからなんです。

  1. .item:nth-child(4) {
  2. grid-area: 2 / 2 / 3 / 7;
  3. background: yellowgreen;
  4. }

ひとつめの2は上から2本めのグリッドラインで、ふたつめの2は左から2本めのグリッドライン。そして、みっつめの3は上から3本めのグリッドライン。よっつめの7は左から7本めのグリッドラインを表します。わぁーややこやしい!

指定したグリッドラインで囲まれたエリアにアイテム要素を配置する。

つまり、grid-areaプロパティは、「指定したグリッドラインに囲われたエリアにアイテムを配置する」ためのプロパティ、なんですね!グリッドエリアはグリッドラインで囲って指定するってことです。;D
なので、最初の2 / 4という指定も、実は2 / 4 / 3 / 5という風に解釈されてたということです。

目次に戻る

ヘッダーとナビゲーション

さてさてそれでは、そんなグリッドレイアウトを使って、ページレイアウトを行って参りましょう!まずはヘッダーのところを、フレキシブルボックスレイアウトの時のスタイルをもとに、グリッドレイアウトに差し替えてゆきます。
まずはnav要素と、ナビゲーションにdisplay: gridを指定します。nav要素とナビゲーションがコンテナとなって、その直接の子要素がアイテムとなります。
見た目は何にも変わってないけれど、中の要素はしっかりグリッドに備えてる状態になったはずです。

nav要素には、左側にサイトタイトル、右側にはナビゲーションが並ぶので、つまり、行は1行、列は2列です。高さも横幅も成り行きで構わないので、auto / auto autoという風に指定、ちょっと冗長ですね。ナビゲーションは、1行5列なのでauto / auto auto auto auto auto、767px以下の時にはauto / 20% 20% 20% 20% 20%…、冗長が過ぎますね…。
アイテムの配置は自動的に割り当てられたままでも良さそうです。

行はどちらも1行なので、特別にグリッドを用意する必要はなくて、どちらも列方向のみグリッドを仕切ればよいので、grid-template-columnsプロパティで指定し直すことにします。
また、同じ値が繰り返されるような時にはrepeat()関数を使った書き方ができます。括弧の中には、繰り返す回数と、繰り返す値を指定します。例えば、nav要素は2つautoが続くので、repeat(2, auto)という具合。
同じように、ナビゲーションにはrepeat(5, auto)、767px以下の時はrepeat(5, 20%)と指定し直します。

それから、ナビゲーションが左に伸びちゃってバランスが悪いです…。ここは、フレキシブルボックスの時と同じく、justify-contentプロパティで調整することができますspace-betweenという値を指定することで、サイトタイトルとナビゲーションが、両端に寄せて配置されるようになりました:D※その他フレキシブルボックスでおなじみの、align-itemsプロパティalign-selfプロパティitem-contentプロパティorderプロパティも、グリッドレイアウトでも有効です。

メインコンテンツとサイドメニュー

コンテンツエリアに作るグリッド。

コンテンツエリア#contentsに、グリッドレイアウトを適用して、グリッドを作ります。
コンテンツエリアには、上部にメインビジュアルが鎮座してて、その下にメインコンテンツとサイドメニューがあるレイアウトなので、右図のようにグリッドラインを引くことにしました。

行の高さは成り行きでよいので、列だけ、grid-template-columnsプロパティ75% 25%と指定します。
セルとセルの隙間の指定にはgrid-gapプロパティを使います。けど、ここも列と列の隙間だけ指定すればよいのでgrid-column-gapプロパティで、40pxと指定することにします。

これでグリッドが作られました。あとは、アイテム要素である、メインビジュアルと、メインコンテンツとサイドメニューを、グリッドに配置し直してゆきます。
メインビジュアルは、1行めのグリッドセルをまたぐように配置なのでgrid-areaプロパティで、1 / 1 / 2 / 3という風に指定します。メインコンテンツとサイドメニューは2行めのグリッドセルにそれぞれ配置、なのでそれぞれ、2 / 12 / 2ということになります。

サイドメニューが右側にハミ出しちゃってますね…。どうやら40pxの隙間の分、右にズレちゃってるみたい。grid-templateプロパティで指定する値には、隙間は含まないのですね…。メインコンテンツの幅をcalc(75% - 20px)、サイドメニューの幅をcalc(25% - 20px)とすれば大丈夫なはず。
綺麗に収まりました。:)

目次に戻る

バナーと商品一覧と記事一覧

ひとまず、ul要素にグリッドレイアウトを適用して、あとは、flex-basisプロパティで指定してた横幅をそのまま利用すれば、フレキシブルボックスの時と同じレイアウトのグリッドが引けそうです。
あとは、justify-contentプロパティでspace-betweenを適用すれば、できあがり!

もうちょっとグリッドレイアウトらしくレイアウトするなら、隙間は、grid-gapプロパティを使って空けたいです。複数行になるアイテムの上下の隙間も、マージンじゃなくて、grid-gapプロパティで指定した方がスマートですよね。:D

あと、grid-template-columnsプロパティの値が、repeat()関数の中にcalc()関数が入ったりしてごちゃごちゃしてるので、もっとシンプルにしたい…。そこで、グリッドレイアウトで使える「fr」という単位を使って、指定し直すことにします。「fr」は“fraction(比率)”を表す新しい単位。fr単位でサイズを指定した要素には、親要素内の余分なスペースが均等に分配されて、親要素を綺麗に埋めることができるんです。
商品一覧ならば、grid-template-columnsプロパティの値に、repeat(3, 1fr)という風に指定すれば、3列のグリッドセルが等幅で用意されるはずです。

グリッドレイアウトにすることで、CSSを大分スッキリ書くことができましたね;D

お知らせ一覧

フレキシブルボックスレイアウトの時と同じように、日付と内容がよこ並びになるようにグリッドを引けば上手くレイアウトできそうです。grid-template-columnsプロパティで、日付の列は9.8em幅、内容の列は成り行き幅となるようにグリッドを作ります。

フッターのサイトマップ

これまでは「店舗検索」の下に「お知らせ」を配置するために、ネガティブマージンやらパディングやらを駆使してましたが、グリッドレイアウトではその必要はないです!グリッドを用意して、レイアウトすればよいのだから!
下図のようなグリッドを引きたいです。

サイトマップのためのグリッド。

まずは2行5列のグリッドを用意します。行の高さは成り行きで良さそうなので、列だけ、grid-template-columnsプロパティでrepeat(5, 1fr)と指定することにします。隙間はgrid-column-gapプロパティで16pxと指定。
grid-areaプロパティで、「店舗検索」のグループを1行めの3列め、「お知らせ」のグループを2行めの3列めに配置して、あとは成り行きにしちゃいます。

「店舗検索」と「お知らせ」以外は、1行めと2行めをまたいで配置しないとダメでしたね…。
ということで、.group要素には最初に、grid-rowプロパティ1 / 3と指定し、配置するエリアの、行だけを先に決めておくことにします。
並びは順番どおりなのだから、「店舗検索」と「お知らせ」も、行の位置を指定するだけで良さそうですね。grid-areaプロパティをやめて、grid-rowプロパティで指定し直します。

「お知らせ」グループの位置がもうちょっと上だとよいなぁ…。
グリッドの1行めの高さを明示的に指定しちゃいましょう!高さは、他のレイアウトの時に使ったcalc(1.3rem * 1.4 + .9em)にすればよいですね。

目次に戻る

IEでグリッドレイアウト

さて、Internet Explorerは、最新バージョンである「IE11」のサポート終了が2025年10月となっておりますので、まだまだ対応が必要です…。IE11ももちろんグリッドレイアウトには対応してるのですけれど、IE独自のちょっと古いタイプの仕様なので、別途、補足しないといけないんですねー。
※以下、前述までのグリッドレイアウトのことを「グリッドレイアウト」、IE11で使用できるグリッドレイアウトのことを「-ms-グリッドレイアウト」と表記し分けることにします。

CSSグリッドレイアウトの対応状況は以下のページを参照のこと。

CSS Grid Layout - Can I use...


グリッドレイアウトと、-ms-グリッドレイアウトで定義されている、グリッド関連の主なプロパティは下表の通り。

grid-ms-grid内容
grid-template grid-template-rows -ms-grid-rows 行トラックのサイズを指定する
grid-template-columns -ms-grid-columns 列トラックのサイズを指定する
grid-gap grid-row-gap - 行トラックの隙間の指定する
grid-column-gap 列トラックの隙間の指定する
grid-area grid-row -ms-grid-row アイテムを配置する行トラックを指定する
grid-column -ms-grid-column アイテムを配置する列トラックを指定する
grid-auto-rows - 行トラックのサイズを指定する
grid-auto-columns - 列トラックのサイズを指定する
grid-auto-flow - 自動配置の方法を指定する
justify-self -ms-grid-row-align グリッドエリア内の水平方向の配置を指定する
align-self -ms-grid-column-align グリッドエリア内の垂直方向の配置を指定する
- -ms-grid-row-span アイテムがまたがるグリッドセルの行数を指定する
- -ms-grid-column-span アイテムがまたがるグリッドセルの列数を指定する
グリッドレイアウトと-ms-グリッドレイアウトのプロパティ対応表

グリッドを用意するためのプロパティ-ms-grid-rows-ms-grid-columnsとして用意されてて、アイテムを配置するためのプロパティ-ms-grid-row-ms-grid-columnとして用意されてます。グリッドレイアウトよりもプロパティ名は覚えやすいですね。
けれども、隙間を指定するためのプロパティは用意されてないです…。なので、グリッドを作る際に、隙間もグリッドで用意するということが必要になります(後述)

それから、アイテムの配置の仕方も違うので注意が必要です。
まず-ms-grid-row-ms-grid-columnで、起点となるグリッドセルを指定して、そこから、-ms-grid-row-span-ms-grid-column-spanで、またぐセルの数を指定して、グリッドエリアを作ります。
-ms-グリッドレイアウトには、グリッドラインという概念はないんですねー。

グリッドレイアウトは線、-ms-グリッドレイアウトは面。

それでは、以上を踏まえて、前述までのグリッドレイアウトの指定に、-ms-グリッドレイアウトのための指定を追記してゆきましょう!まずはヘッダーから。
nav要素とナビゲーションに、以下のように追記します。

IE11のためのグリッドレイアウトの指定
  1. display: -ms-grid;
  2. display: grid;

そして、-ms-グリッドレイアウトでは、-ms-grid-columnsプロパティでグリッドを用意します。
グリッドレイアウトで、repear()関数を使って「repeat(回数, 値)」という風に指定していたところは、-ms-グリッドレイアウトでは、「(値)[回数]」という風に書き換えられます。

IE11のためのグリッドを用意する指定
  1. @media print, (min-width: 415px) {
  2. .nav-list {
  3. /* ... 中略 ... */
  4. -ms-grid-columns: (auto)[5];
  5. grid-template-columns: repeat(5, auto);
  1. @media print, (min-width: 768px) {
  2. header nav {
  3. /* ... 中略 ... */
  4. -ms-grid-columns: (auto)[2];
  5. grid-template-columns: repeat(2, auto);
  1. @media screen and (max-width: 767px) {
  2. .nav-list {
  3. /* ... 中略 ... */
  4. -ms-grid-columns: (20%)[5];
  5. grid-template-columns: repeat(5, 20%);
IE11での表示(ブラウザで表示する

なんとぉ、サイトタイトルとナビゲーションが一箇所に固まってしまいました。-ms-グリッドレイアウトは、アイテムを自動的に割り付けてくれないんですね…。グリッドレイアウトはアイテムの初期値がauto(空いてるグリッドセルに順番に詰めて配置)だったのに対して、-ms-グリッドレイアウトはアイテムの初期値が1(1行め1列めに配置)ってことなんです。そして整数しか指定できません。
アイテムを列方向のグリッドセルに配置するには、-ms-grid-columnプロパティを使います。とても面倒臭いけれど、下記のように、アイテムをひとつずつ、グリッドセルに配置してゆきます。

IE11のためのアイテムを配置するための指定
  1. @media print, (min-width: 415px) {
  2. /* ... 中略 ... */
  3. .nav-list li:nth-child(2) { -ms-grid-column: 2; }
  4. .nav-list li:nth-child(3) { -ms-grid-column: 3; }
  5. .nav-list li:nth-child(4) { -ms-grid-column: 4; }
  6. .nav-list li:nth-child(5) { -ms-grid-column: 5; }
  1. @media print, (min-width: 768px) {
  2. /* ... 中略 ... */
  3. .nav-list { -ms-grid-column: 2; }
IE11での表示(ブラウザで表示する

無事、グリッドセルにアイテムが順番に配置されました。けれどナビゲーションが左に寄っちゃってますね…。どうやら、nav要素のグリッドのサイズが、アイテムの内容に準拠した幅になってるみたいです。グリッドのサイズをautoじゃなくて、1frに変えてみます。

nav要素のグリッドセルのサイズをautoじゃなくて1frに変える
  1. @media print, (min-width: 768px) {
  2. header nav {
  3. /* ... 中略 ... */
  4. -ms-grid-columns: (1fr)[2];
  5. grid-template-columns: repeat(2, auto);
IE11での表示(ブラウザで表示する

それでもまだちょっと左に寄り気味ですね。-ms-grid-column-alignプロパティを使えば、グリッドエリア内のアイテムの横方向の位置揃えを指定できます。ここでは、右側(並ぶ進行方向のお尻側)に寄せるために、endを指定します。

ナビゲーションのグリッドエリア内の配置を終端にする
  1. @media print, (min-width: 768px) {
  2. /* ... 中略 ... */
  3. .nav-list {
  4. -ms-grid-column: 2
  5. -ms-grid-column-align: end;
IE11での表示(ブラウザで表示する

整いましたX)
続いてコンテンツエリアにグリッドを用意です。
問題はメインコンテンツとサイドメニューの隙間ですが、この隙間も含めて、グリッドを用意しなくちゃいけません。つまり、下記のようにグリッドを引くことになります。

コンテンツエリアにグリッドを用意する。
  1. @media print, (min-width: 768px) {
  2. #contents {
  3. display: -ms-grid;
  4. display: grid;
  5. -ms-grid-columns: calc(75% - 20px) 40px calc(25% - 20px);
  6. grid-template-columns: calc(75% - 20px) calc(25% - 20px);
  7. grid-column-gap: 40px;
  8. }
  9. }

そして、メインビジュアルとメインコンテンツ、サイドメニューを、それぞれグリッドセルに配置します。
メインビジュアルは1行め1列めからの、3つセルをまたぐので-ms-grid-column-spanプロパティ3と指定。メインコンテンツは2行め1列め、サイドメニューは2行め3列め、ですね。
それぞれ、1行め1列めについては、初期値なので特に指定しなくてよいですから、以下のような指定になります。
※IE11は、main要素をサポートしていないため、ブロックレベル要素として認識されるように、別途display: blockを指定します。

コンテンツエリアにグリッドを用意する。
  1. @media print, (min-width: 768px) {
  2. /* ... 中略 ... */
  3. .visual {
  4. -ms-grid-row: 1;
  5. -ms-grid-column: 1;
  6. -ms-grid-column-span: 3;
  7. }
  8. main {
  9. display: block;
  10. -ms-grid-row: 2;
  11. -ms-grid-column: 1;
  12. }
  13. aside {
  14. -ms-grid-row: 2;
  15. -ms-grid-column: 3;
  16. }
  17. }
IE11での表示(ブラウザで表示する

うまくレイアウトできましたーXD
こんな調子で、じゃんじゃか-ms-グリッドレイアウトのための指定を追記してゆき…、できあがりIE11での表示

これにて、グリッドレイアウトでページレイアウト完了ー!

目次に戻る

レイアウトのまとめ。

いろいろな方法でページレイアウトしてきましたけれども、どれも一長一短あって、適材適所というのが、ちゃんとありますよね。
ここまで紹介してきたレイアウトの場合だと、下図のような使い分けが、一番よさげでした。

レイアウト方法の適材適所。

ヘッダーとナビゲーションみたいに単純なよこ並びには、フレキシブルボックスが扱い易いかなと思います。
コンテンツエリアや商品一覧、お知らせ一覧のような、複数行にわたる、文字どおり格子状のレイアウトには、グリッドレイアウトがぴったり。
フッターのサイトマップは、まぐれだと思いますけど、columnsプロパティで一番しっくりレイアウトできちゃいましたね。X)

とはいえ、文章中に画像を回り込ませるにはやっぱりfloatプロパティですし、テーブルレイアウトはやはり表組みのためのレイアウトモードでしょうし、インライン・ブロックは、レイアウト用途よりも、文字数幅に準拠させたいタイトルとか、ボタンの中のアイコンとか、もっとピンポイントな用法が相応しいと思います。

選抜レイアウト

なんだかんだ便利なグリッドレイアウトですけれど、他にもまだまだいろんな使い方があって、この記事中のサンプルでは、ぜんぜん本領発揮できていないでしょう。
グリッドレイアウトは、今回レイアウトしたような従来いにしえの段組みレイアウトなどではなくて、ゲーム画面やアプリ画面のような、かっちり決まったレイアウトや、もっと複雑で豊富な機能を画面内に整理整頓しなきゃならないような場面で重宝するレイアウトモードだな、と思いました;)

あとがき。

なんでこんなにたくさんの“やり方”があるのかというと、Webは日々進化して、どんどん良くなっているから。その時々での最良のやり方が蓄積されてきた結果なのですね。当然、最新のやり方が、その時のいちばん最良な方法なのだけれど、文章に画像を回り込ませるためにfloatプロパティは残るだろうし、表組みを作るためにテーブルも残るし、要素を並べるためにフレキシブルボックスは使われてゆくと思います。
そんな風に、適材適所のプロパティが増えていった先に、いずれオールマイティに使えるプロパティが登場したりして、また僕らを困惑させるんでしょう。

てなもんで、最後まで読んでいただきありがとうございました!「段組みのCSS。」でした!

Comment & Pingback

1 Comment for 段組みのCSS。

  1. Pingback:気になった記事まとめ(1月8日〜1月12日) | tz_blog

コメントを残す