display: gridの覚書き 〜media query不要のレスポンシブデザインも作れる!
CSS3から追加されたdisplay: gridというプロパティについての覚書きです。
便利便利だと聞いてはいたものの、はじめは仕組みを理解するのにややとっつきにくく、再度自分の言葉で、理解しなおすためにnoteにまとめることにしました。
また、display: gridを理解して、うまく活用するとmedia queryなしでレスポンシブにも対応できるデザインが作れたので、そちらもまとめ書き。
もし記述に誤認が会ったりする場合はコメントで指摘していただけたら幸いです。
グリッドレイアウトの基本
グリッドとは
MDNの説明では、グリッドとは、行と列を表した領域のことであると説明されています。このグリッドの中に要素を好きなように配置して、グリッドレイアウトを実現します。
グリッドコンテナーを作る
要素を自由に配置するためには、まずグリッドコンテナーを作成します。配置したい要素の親要素となる要素に、display: grid;を指定します。
(以下は.wrapperに対してdisplay: grid;を指定したので、直接の小要素である「A」「B」「C」がグリッド要素になりました。)
<div class="wrapper">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
.wrapper {
display: grid;
}
グリッドトラックを定義する
作成したグリッドコンテナーの中で、要素をどのように配置していくのかを決めるために、grid-template-columnsとgrid-template-rowsを使って、行と列を定義します。
例えばgrid-template-columns: 300px 300px 300px;と指定すると、横に300px幅の列が3つ出来ます。
.wrapper {
display: grid;
grid-template-columns: 300px 300px 300px;
}
grid-template-rowsは行、縦幅を指定します。
.wrapper {
display: grid;
grid-template-rows: 100px 50px 50px;
}
repeat()記法を使ってグリッドトラックを定義する
また、上の記述はrepeat()記法を使って簡単に書くこともできます。
repeat( 繰り返す回数, 指定したいサイズ )の順に記述するだけ。上記を例に書くと以下のようになります。
.wrapper {
display: grid;
grid-template-columns: repeat(3, 300px);
grid-template-rows: 100px repeat(2,50px);
}
display: grid;で使えるプロパティを使ってより自由な指定をしよう!
ここまでは、簡単なグリッドレイアウトについて説明してきました。
ここからは、display: girdの魅力である柔軟性の高い実装の方法について紹介していきたいと思います。
fr単位
柔軟な長さの単位を示すために生まれたfr単位。MDNでは、グリッドコンテナー内の利用可能な空間の分数 (a fraction) を表すと説明されているのですが非常に分かり辛いので実際の表示を見てみましょう。
.wrapper_A {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.wrapper_B {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
}
Aでは、定まっていない幅に応じて、3分割されたトラックを作成します。
Bでは、幅が4分割されますが、4分割された中でもはじめのトラックに対して、2frが与えられるので同じ3分割に見えても図のような差が生まれます。
ちなみにこのfr単位と繰り返し記法を使うと、作られたトラックの並び方向(特に指定しない場合は左から右)に準じて適用されるので、以下のようなコードを書いた場合には、1fr トラックと 2fr トラックの並びを 5 回繰り返したパターンからなる、10 のトラックが作られます。
.wrapper {
display: grid;
grid-template-columns: repeat(5, 1fr 2fr);
}
minmax()関数
トラックの横・縦幅の最小値・最大値を指定できる関数です。
()の中は、minmax(最小値, 最大値);で記述します。
<div class="wrapper">
<div>A</div>
<div>B
<p>つれづれなるまゝに、日暮らし、硯にむかひて、心にうつりゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。</p>
</div>
<div>C</div>
<div>D</div>
<div>E</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
}
repeat(auto-fillまたはauto-fit)
media query無しでレスポンシブ対応した実装を可能するプロパティです。
横いっぱいにBOXを並べられるだけ並べたいけど、スマートフォンの時は縦に1列になってほしい。こういう場合に、 repeat(auto-fill | auto-fit)を使います。
.wrapper {
display: grid;
text-align: center;
}
.graph11 {
grid-template-columns: repeat(auto-fit,minmax(200px,1fr));
}
grid-column, grid-row
作ったグリッドの指定を越えて、表示したいアイテムの幅を指定することもできます。
<div class="wrapper">
<div class="box1">A</div>
<div class="box2">B</div>
<div class="box3">C</div>
<div class="box4">D</div>
<div class="box5">E</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: repeat(3, 100px);
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 2;
}
.box2 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 3;
grid-row-end: 4;
}
grid-row-start と grid-clomn-startで、表示開始位置、grid-row-end と grid-clomn-endで表示終了位置を指定します。
BのボックスがHTMLの並び順序をスルーして、一番下に置かれているのは、表示させたい位置の開始をrow3に指定しているためです。
更に、横の表示終了位置をcolumn3に指定しているために、横幅いっぱいには表示されず、グリッドの2つ目終了位置までの領域で表示されています。
また、grid-row,grid-clomnを使うと、スタート位置とエンド位置を一括で指定することもできます。
上記であれば、こんな書き方。
.box1 {
grid-column: 1/4;
grid-row: 1/2;
}
.box2 {
grid-column: 1/3;
grid-row: 3/4;
}
実践編:フレキシブルに対応した実装法 1 バッジ編
before要素,after要素が不要です。absolute指定よりレスポンシブに操作しやすいかも・・!
実践編:フレキシブルに対応した実装法 2
文章がある程度可変しても、パーツそれぞれの高さは変わらず実装できる方法です。
参考リンク:
https://developer.mozilla.org/ja/docs/Web/CSS/CSS_Grid_Layout
https://parashuto.com/rriver/development/responsive-layout-with-css-grid-and-flexbox
ありがとうございます! twitterでもマイペースに活動中です。https://twitter.com/mmaki_algiz