前回の記事(「実務で使うGridレイアウト【環境構築編(gulp)】」)では、最新版のAutoprefixerの導入と、Grid機能を有効にする設定について解説しました。今回は【機能編】として、IE11への対応を踏まえた上でGridレイアウトを利用するために気をつけなければならないポイントを解説します。
※なお、Gridレイアウトそのものの基本的な使い方については既に習得している前提となりますので、Gridレイアウト自体の使い方を知りたい方はGoogle先生などにお尋ねください。
【機能編】目次
アイテムの配置にはgrid-areaを使う
Gridレイアウトにおける各セルへのアイテムの配置方法は複数ありますが、IE11対応も考えるのであれば基本的に「grid-area」一択です。grid-columnやgrid-rowでのアイテム配置は、Autoprefixerによるアイテムの配置が正しく行われないのでやめましょう。
アイテムの配置にgrid-areaを使うということは、grid-template-areaまたはgrid-templateによって各セルに名前をつける必要があるということになります。
以下はgrid-areaによるアイテム配置の例になります。
<div class="grid"> <header>ヘッダー</header> <main>メイン</main> <aside>サイドバー</aside> <footer>フッター</footer> </div>
.grid { display: grid; height: 100vh; gap: 20px; grid-template-columns: 1fr 4fr; grid-template-rows: 100px 1fr 100px; grid-template-areas: "header header" "sidebar main" "footer footer"; /*grid-templateによるショートハンドの場合はこちら grid-template: "header header" 100px "sidebar main" 1fr "footer footer" 100px / 1fr 4fr; */ } header { grid-area: header; background: tomato; } main { grid-area: main; background: skyblue; } aside { grid-area: sidebar; background: gold; } footer { grid-area: footer; background: pink; }
.grid { display: -ms-grid; display: grid; height: 100vh; grid-gap: 20px; gap: 20px; -ms-grid-columns: 1fr 20px 4fr; grid-template-columns: 1fr 4fr; -ms-grid-rows: 100px 20px 1fr 20px 100px; grid-template-rows: 100px 1fr 100px; grid-template-areas: "header header" "sidebar main" "footer footer"; /*grid-templateによるショートハンドの場合はこちら -ms-grid-rows: 100px 20px 1fr 20px 100px; -ms-grid-columns: 1fr 20px 4fr; grid-template: "header header" 100px "sidebar main" 1fr "footer footer" 100px / 1fr 4fr; */ } header { -ms-grid-row: 1; -ms-grid-column: 1; -ms-grid-column-span: 3; grid-area: header; background: tomato; } main { -ms-grid-row: 3; -ms-grid-column: 3; grid-area: main; background: skyblue; } aside { -ms-grid-row: 3; -ms-grid-column: 1; grid-area: sidebar; background: gold; } footer { -ms-grid-row: 5; -ms-grid-column: 1; -ms-grid-column-span: 3; grid-area: footer; background: pink; }
このように、IE11ではgapも一つのセルとなるように行列を引き直し、grid-areaで指定されたセルに対して-ms-grid-row/-ms-grid-columnによる番号指定でアイテムを再配置してくれます。
これを手作業でやることを考えたら、GridのIE対応を手動でやるのがいかに現実的でないか分かりますね(;´Д`)
display: inlneの要素はGridアイテムにならない
さて、上記のHTML/CSSを各ブラウザで表示するとこうなります。
……できてないじゃーん!!!!
と、思うかもしれません。ええ、私も最初はそう思いました。
ただ、これはAutoprefixerのせいではありません。IEではdisplay:inlineの要素はGridアイテムの対象にならないバグ(仕様?)があるのです。そして、IE11ではmain要素はデフォルトでdisplay:inlineになってしまいます。なので、main要素をGridアイテムにしたい場合にはmain {display: block;}を明示的に記述してやる必要があるのです。main要素をdisplay:blockにして再度IE11で表示したものがこちらです。
はい、無事できました。(ホッ)
ちなみにdisplay:inlineの要素がGridアイテムの対象にならないということは、main要素に限らずa要素やらspan要素やらもそのままではGridレイアウトにできないということです。なのでこれらの要素を対象にGridレイアウトを作りたい場合には、忘れずにdisplay: blockを指定するようにしましょう。
IE11での限定的自動配置機能とその制限事項
Gridレイアウトにはアイテムの「自動配置」の仕組みがありますが、中でも
・repeat() (auto-fill または auto-fit)
・minmax()
といった関数を利用するとメディアクエリなしでレスポンシブレイアウトを実現できたりするなど、非常に柔軟なレイアウトが簡単に実現できます。
(デモ付きでわかりやすい解説がありましたので詳細は以下のブログを参照してください。)
[参考]
・「CSS GridとFlexboxを使ってメディアクエリなしでレスポンシブにレイアウトする方法」
・「CSS Gridを使うならマスターしておきたいauto-fillとauto-fitの違い」
Gridレイアウトはこうした「同じサイズのボックスが複数行並び、画面幅に応じてカラム数が柔軟に変わるレイアウト」でこそ普段使いのレイアウト手法として威力を発揮すると個人的には思っているので、実務で使うとしたらまずこのようなレイアウトの箇所から導入したいと思っているのですが、残念ながらIE11には「自動配置」の仕組み自体が存在しません。
したがって、上記のブログで紹介されているようなauto-fillやminmax()を活用した柔軟なレイアウトの実装はIE11では物理的に不可能となります。
ただし、ボックスを指定回数繰り返し配置するrepeat() については、v9.4.0のAutoprefixerから限定的に再現可能となっていますので、シンプルなものであればfloatやflexboxの代わりに活用することができるかもしれません。以下にIE11で自動配置機能を利用するための設定と制限事項をまとめましたので参考にしてください。
●自動配置機能を使うための設定
AutoprefixerでIEでの自動配置機能をONにするためには、css(scss)に
というコメントを記述する必要があります。
autoprefixerを使う場合にはsassも同時に利用していることが多いと思いますが、
この機能のON/OFFは.scssファイルごとに個別に設定する形となります。
(test1.scssとtest2.scssという2枚のscssファイルがあった場合、test1.scssにだけ前述のコメントを記述すれば、test1.scssに書かれたCSSにだけ自動配置機能が適用される、ということです。パーシャルファイルに記述した場合も同様です。)
2019.6.4追記
AutoprefixerでIE向けに自動配置機能をONにする方法は、css(scss)にコメントで指定する方法以外に、gulpfile.js内で以下のように指定することでも実現できることが分かりました。
const gulp = require("gulp"); const postcss = require("gulp-postcss"); const autoprefixer = require("autoprefixer"); gulp.task("default", function () { return gulp.src("src/style.css") .pipe(postcss([ autoprefixer({ grid: "autoplace" //←★trueではなく"autoplace"にする }) ])) .pipe(gulp.dest("dist")); });
この方法であればcss(scss)ファイルごとに個別に指定する必要はないので、こちらの方が効率的と思われます。
詳細はこちら。
●制限事項1:行と列の両方を明示しなければならない
AutoprefixerではIEの仕様の範囲内で擬似的に再現しているだけであるので、あらかじめ表示したいアイテム数に応じてそれを全て配置できるだけの行と列を事前に明示しておく必要があります。列の指定は良いとして、行数もあらかじめ指定しておかなければならないというところがこの機能を使う上での最大の難点となります。
これはつまり、「動的に要素を増減させたい場面では利用できない」ということを意味します。
CMSなどから動的にアイテムを出力しており、アイテム数が可変となるような場面では使えないので、実際問題使える場面はかなり限られてしまうと思われます。JSでなにかゴニョゴニョすればできるのかもしれませんが、そこまでやるくらいならfloatなりflexboxなりで頑張ったほうがマシなのではないかと思います。
●制限事項2:レスポンシブさせたい場合はメディアクエリで列数/行数を指定し直す
たとえアイテム数が固定であったとしても、レスポンシブのサイトで画面幅によってカラム数が変更になれば、当然必要となる行数も変わってきます。通常であればこのような時にはGridは暗黙のグリッドを作成して自動的に行数をよしなにしてくれますが、IE11ではこれができません。したがってメディアクエリを使って画面幅ごとにその都度Gridの列数/行数を指定し直す必要があります。
●制限事項3:auto-fit, minmax()などの機能は再現できない
既に言及したとおり、本来のGridレイアウトでrepeat()を活用する際に利用できるauto-fit,auto-fill,minmax()といった便利な機能は全て使用できません。再現できるのはボックスの単純な繰り返し配置のみです。諦めましょう。
●制限事項4:精神衛生上、出力されたCSSは見ない方がいい(苦笑)
IE11のGridレイアウトは、本来エリア名による配置も、gapの指定も、repeat()配置も全て非対応です。IE11にできることは、とにかく行と列を必要な分だけ区切って、行番号・列番号でアイテムをひたすら手動で配置することだけです。この不毛な作業を、Autoprefixerは人間の代わりに行ってくれているだけです。なので、出力されるIE向けのCSSは実に力技です(苦笑)。特にアイテム数が多くなるrepeat()を使った場合、CSSは :nth-child(n)の嵐となることでしょう…。(20個のアイテムをrepeat()で自動配置して、更にメディアクエリで段階的にカラム数・行数が変わるように書いた場合は、20×分岐数分だけの:nth-child(n)が羅列されることになります。)
とりあえず、実際書いたらどうなるのか以下に置いておきますので、本当に使うのかどうかは各自判断してください。
<ul class="container"> <li>1アイテム</li> <li>2アイテムアイテムアイテムアイテムアイテムアイテムアイテム</li> <li>3アイテム</li> <li>4アイテム</li> <li>5アイテムアイテムアイテムアイテムアイテム</li> <li>6アイテム</li> <li>7アイテムアイテムアイテムアイテム</li> <li>8アイテム</li> <li>9アイテムアイテム</li> <li>10アイテム</li> <li>11アイテムアイテム</li> <li>12アイテム</li> <li>13アイテム</li> </ul>
.container{ max-width: 960px; margin: auto; display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(7, 1fr); gap: 20px; } @media (max-width: 768px) { .container { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(7, 1fr); } }
.container { max-width: 960px; margin: auto; display: -ms-grid; display: grid; -ms-grid-columns: 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr; grid-template-columns: repeat(5, 1fr); -ms-grid-rows: 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr; grid-template-rows: repeat(7, 1fr); grid-gap: 20px; gap: 20px; } .container > *:nth-child(1) { -ms-grid-row: 1; -ms-grid-column: 1; } .container > *:nth-child(2) { -ms-grid-row: 1; -ms-grid-column: 3; } .container > *:nth-child(3) { -ms-grid-row: 1; -ms-grid-column: 5; } .container > *:nth-child(4) { -ms-grid-row: 1; -ms-grid-column: 7; } .container > *:nth-child(5) { -ms-grid-row: 1; -ms-grid-column: 9; } .container > *:nth-child(6) { -ms-grid-row: 3; -ms-grid-column: 1; } .container > *:nth-child(7) { -ms-grid-row: 3; -ms-grid-column: 3; } .container > *:nth-child(8) { -ms-grid-row: 3; -ms-grid-column: 5; } .container > *:nth-child(9) { -ms-grid-row: 3; -ms-grid-column: 7; } .container > *:nth-child(10) { -ms-grid-row: 3; -ms-grid-column: 9; } .container > *:nth-child(11) { -ms-grid-row: 5; -ms-grid-column: 1; } .container > *:nth-child(12) { -ms-grid-row: 5; -ms-grid-column: 3; } .container > *:nth-child(13) { -ms-grid-row: 5; -ms-grid-column: 5; } .container > *:nth-child(14) { -ms-grid-row: 5; -ms-grid-column: 7; } .container > *:nth-child(15) { -ms-grid-row: 5; -ms-grid-column: 9; } .container > *:nth-child(16) { -ms-grid-row: 7; -ms-grid-column: 1; } .container > *:nth-child(17) { -ms-grid-row: 7; -ms-grid-column: 3; } .container > *:nth-child(18) { -ms-grid-row: 7; -ms-grid-column: 5; } .container > *:nth-child(19) { -ms-grid-row: 7; -ms-grid-column: 7; } .container > *:nth-child(20) { -ms-grid-row: 7; -ms-grid-column: 9; } .container > *:nth-child(21) { -ms-grid-row: 9; -ms-grid-column: 1; } .container > *:nth-child(22) { -ms-grid-row: 9; -ms-grid-column: 3; } .container > *:nth-child(23) { -ms-grid-row: 9; -ms-grid-column: 5; } .container > *:nth-child(24) { -ms-grid-row: 9; -ms-grid-column: 7; } .container > *:nth-child(25) { -ms-grid-row: 9; -ms-grid-column: 9; } .container > *:nth-child(26) { -ms-grid-row: 11; -ms-grid-column: 1; } .container > *:nth-child(27) { -ms-grid-row: 11; -ms-grid-column: 3; } .container > *:nth-child(28) { -ms-grid-row: 11; -ms-grid-column: 5; } .container > *:nth-child(29) { -ms-grid-row: 11; -ms-grid-column: 7; } .container > *:nth-child(30) { -ms-grid-row: 11; -ms-grid-column: 9; } .container > *:nth-child(31) { -ms-grid-row: 13; -ms-grid-column: 1; } .container > *:nth-child(32) { -ms-grid-row: 13; -ms-grid-column: 3; } .container > *:nth-child(33) { -ms-grid-row: 13; -ms-grid-column: 5; } .container > *:nth-child(34) { -ms-grid-row: 13; -ms-grid-column: 7; } .container > *:nth-child(35) { -ms-grid-row: 13; -ms-grid-column: 9; } @media (max-width: 768px) { .container { -ms-grid-columns: 1fr 20px 1fr; grid-template-columns: repeat(2, 1fr); -ms-grid-rows: 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr; grid-template-rows: repeat(7, 1fr); } .container > *:nth-child(1) { -ms-grid-row: 1; -ms-grid-column: 1; } .container > *:nth-child(2) { -ms-grid-row: 1; -ms-grid-column: 3; } .container > *:nth-child(3) { -ms-grid-row: 3; -ms-grid-column: 1; } .container > *:nth-child(4) { -ms-grid-row: 3; -ms-grid-column: 3; } .container > *:nth-child(5) { -ms-grid-row: 5; -ms-grid-column: 1; } .container > *:nth-child(6) { -ms-grid-row: 5; -ms-grid-column: 3; } .container > *:nth-child(7) { -ms-grid-row: 7; -ms-grid-column: 1; } .container > *:nth-child(8) { -ms-grid-row: 7; -ms-grid-column: 3; } .container > *:nth-child(9) { -ms-grid-row: 9; -ms-grid-column: 1; } .container > *:nth-child(10) { -ms-grid-row: 9; -ms-grid-column: 3; } .container > *:nth-child(11) { -ms-grid-row: 11; -ms-grid-column: 1; } .container > *:nth-child(12) { -ms-grid-row: 11; -ms-grid-column: 3; } .container > *:nth-child(13) { -ms-grid-row: 13; -ms-grid-column: 1; } .container > *:nth-child(14) { -ms-grid-row: 13; -ms-grid-column: 3; } }
まとめと今後の課題
IE11の対応もする前提でGridレイアウトを使おうと思うと、何かと制限はありますが
・各セルに明示的にエリア名をつけて運用することが可能なレイアウト
・固定数のボックスを単純に繰り返し配置するレイアウト
であればIE11でも問題なく再現できることが確認できました。
今回はあくまで機能面での再現性の確認でしたが、今後の課題としては、実際の案件で活用していくにあたり、ベストな使い方のノウハウ(サイト全体のレイアウト制御orパーツ単位での制御のどちらが良いか、どのようにグリッド線を構築するのがベストなのか、等)を検討できればな、と考えております。
この辺は一人でウンウン言っていても拉致があかないと思うので、同じように受託の現場での活用を考えている方と率直な意見交換ができればいいなーと思っています。
既に活用していて、「こんな使い方してるよ!」とか「こういうのはうまくいかないよ!」といった経験談を聞かせていただけると嬉しいです!
* * * * * * * * * * * * * * * * * * * * *
【PR】書籍が発売されました♪
2013年の初版、2015年の改訂版に続き、2回目の改訂第2版となる『HTML5&CSS3標準デザイン講座』が2019年5月24日に発売されました♪ヨロシクー!
- タイトル:「HTML5&CSS3標準デザイン講座 【第2版】」
- ISBN:978-4798158136
- 出版社:翔泳社
- 版型・ページ数:B5変・400P・フルカラー
- 定価:本体2,580円+税
- 刊行:2019年5月24日(金)