もっと知りたい! CSS Grid 前編 minmax()関数の使い方
2016年にCodeGridで連載された「これからのグリッドレイアウト」の続編です。前回紹介できなかったトピックのひとつmixmax()関数。これをプロパティの値にを使うと、レスポンシブな画面に対応することができます。
はじめに
CSS Gridの記事は2016年のはじめに一度書かれています。ですが、現在では古い情報もあります。また、前回のシリーズでは解説をしていない機能もありました。
- 「これからのグリッドレイアウト」シリーズ(CodeGrid)
そこでこのシリーズでは、前回のシリーズから変更があった仕様や、紹介しなかった機能にもフォーカスして解説を進めます。
まずは、CSS Gridの最新状況を見てみましょう。
CSS Gridの最新状況
執筆現在、CSS Gridに関する仕様書は次のとおりです。
- CSS Grid Layout Module Level 1 W3C Candidate Recommendation, 14 December 2017
- CSS Grid Layout Module Level 2 W3C Working Draft, 27 April 2018
- CSS Grid Layout Module Level 1 Editor’s Draft, 21 June 2018
- CSS 格子レイアウト — CSS Grid Layout Module Level 1 編集者草案 — 2018 年 6 月 11 日
前回の記事で参照していたのは、2015年の仕様書です(CSS Grid Layout Module Level 1 W3C Working Draft, 17 September 2015)。それから2年経っているため、ブラウザの実装状況や、仕様の一部に変更がありました。それらについて確認していきましょう。
ブラウザの対応状況
ブラウザへの実装状況は、大きく進みました。IE11以外の最新ブラウザでCSS Gridを利用することができます。IE11は古いCSS Gridの仕様を参照しているため、一部の機能を使うことができないので注意が必要です。
また、モバイル環境でいうと、iOS 10.2のSafariと、Android 4.4の標準ブラウザでは対応しておらず、使えません。
grid-gapプロパティがgapプロパティに変更
変更されたプロパティを紹介します。
グリッド間の行や列の隙間を定義するためのgrid-gap
・grid-column-gap
・grid-row-gap
プロパティが削除されました。
仕様書に記載されている変更履歴を見ると次のようにあります。
Removed grid-row-gap and grid-column-gap from the list of properties reset by the grid shorthand. (Issue 1036) Removed grid-row-gap, grid-column-gap, and grid-gap properties, replacing with row-gap, column-gap, and gap which are now defined in CSS Box Alignment. (Issue 1696)
ですが、それらの置き換えとして、CSS Grid Layout ModuleではなくCSS Box Alignment Moduleにgap
・column-gap
・row-gap
プロパティが追加されました。
CSS Box Alignment 3 §8 Gaps Between Boxesを見ると
Applies to: multi-column elements, flex containers, grid containers
と記述されていることから、CSS Gridだけでなく、Flexboxなどほかのレイアウト系のプロパティでもgap
プロパティを使えるようにする目的があり、grid-gap
をgap
へと変更することになったようです。
使用方法や機能は変わっていませんが、古いものと新しいものを並べて、おさらいしておきましょう。
<div class="Grid -old">
<div class="Grid_Item"></div>
<div class="Grid_Item"></div>
<!-- 以下繰り返し -->
</div>
<div class="Grid -new">
<div class="Grid_Item"></div>
<div class="Grid_Item"></div>
<!-- 以下繰り返し -->
</div>
.Grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.Grid.-old {
grid-row-gap: 10px;
grid-column-gap: 25px;
/* grid-gap: 10px 25px; と同じ意味 */
}
.Grid.-new {
row-gap: 10px;
column-gap: 25px;
/* gap: 10px 25px; と同じ意味 */
}
このプロパティ名の変更は、筆者が確認したところ、Chrome 67とFirefox 61で実装を確認できました。後方互換として古いgrid-gapプロパティにも対応していました。現在grid-gapプロパティが使われていたとしても、この変更によって表示が崩れたりすることはないでしょう。
subgrid
入れ子状のグリッドを定義できるsubgrid
については、CSS Grid Layout Module Level 2へ見送りになっています。まだ実装しているブラウザはありません。
グリッドトラックのさまざまなサイズ指定
ここからは、前回のシリーズでは触れなかった、CSS Gridをより活用するための機能を紹介します。
まず最初は、グリッドトラックのサイズを指定するための値に使えるminmax()関数についてです。
minmax()関数は、その引数に最小値と最大値を指定することで、トラックの最小幅と最大幅を定義することができます。
minmax()関数の文法
minmax(最小値, 最大値)
どちらの引数も、次の値を取ることができます。
<length>
(例:100px)<percentage>
(例:50%)<flex>
(例: 1fr)*auto
max-content
min-content
*注:fr単位
後述しますが、現在の仕様ではfr
を最小値の値として指定することができません。
それぞれの値は見慣れた値がほとんどです。しかしmax-content
やmin-content
はあまり見ない値です*。この2つの値については後述しますので、今はこういった値が使えるということを覚えておきましょう。
*注:min/max-contentとmin/max-widthの違い
似たような表記なので混乱しがちですが、min/max-content
はプロパティに指定できる値です。min/max-width
はご存じのとおり、プロパティです。ですからmin-width: min-content
などという指定も理論的には可能です。それぞれサイズの指定に関わるものではありますが、根本的に違うものです。
まずは、mimmax()関数を使用したデモを見てみましょう。
minmax()関数の使用例
.Grid {
display: grid;
grid-template-columns: minmax(200px, 1fr) 1fr;
}
適用するHTML
<div class="Grid">
<div class="Grid_Item">
最小サイズ:200px<br>
最大サイズ:1fr
</div>
<div class="Grid_Item">
サイズ:1fr
</div>
</div>
画面幅が広いときは、2つの.Grid_Item
のサイズは1frとなります。ですが画面幅が狭いときには、1つめの.Grid_Item
は最小幅200px
となり、それ以下のサイズにはなりません。
最小サイズと最大サイズを指定できるminmax()関数は、リストやページのレイアウトに活躍するでしょう。
minmax()関数を活用したリスト
minmax()関数を活用したリストを、その引数の値の種類を変えて紹介していきます。
px指定
まずはpx
(<length>
)を指定した場合です。HTMLとCSSは次のようになります。
<div class="List">
<div class="List_Item"></div>
<div class="List_Item"></div>
<!-- 以下繰り返し -->
</div>
.List {
display: grid;
grid-template-columns: minmax(30px, 100px) 100px 100px;
}
1つめのグリッドトラックのサイズが最小30px
で最大100px
となっているので、画面サイズを変更するとその最小最大サイズの中で可変になります。
%指定
次に%
(<percentage>
)を指定した場合です。
.List {
display: grid;
grid-template-columns: minmax(10%, 50%) 100px 100px;
}
1つめのグリッドトラックのサイズが最小10%
で最大50%
となっているので、画面サイズを変更すると、その中で可変になります。
fr指定
さらに、fr
(<flex>
)*を指定した例も続けて見てみましょう。
*注:fr単位
fr
という単位については、次の記事に詳しく解説されています。
.List {
display: grid;
grid-template-columns: minmax(200px, 1fr) 1fr 1fr;
}
1つめのグリッドトラックのサイズが最小200px
で最大1fr
となっているので、画面サイズを変更すると、その中で可変になります。2つめと3つめのグリッドトラックは1fr
なので、全体幅から1つめのグリッドトラックの幅を引き、そのあまりの幅を2つめと3つめのグリッドトラックで均等に割り振った幅になります。
広い画面では、それぞれのグリッドトラックは同じサイズになります。ですが狭い画面になると、1つめのグリッドトラックだけは最小200px
としているので、それ以上狭くなることはありません。
【ワンポイント】指定によっては無効になる場合
次のような指定をした場合、ブラウザは正しく解釈できなくなってしまいます。
.List {
display: grid;
grid-template-columns: minmax(1fr, 2fr) 1fr 1fr;
}
仕様書によれば、minmax()関数の最小値にfr
による値指定をすると、その指定は無効(invalid)になります(仕様書のNote:によると将来的にこの仕様が変更になる可能性もあるようですが)。
DevToolsで見てみると、図のように値が無効になっていることがわかります。
min-contentとmax-content
これまで紹介してきたminmax()
に指定できる値として、min-content
とmax-content
があります。
min-content
はグリッドトラックに含まれるもっとも幅が狭い要素と同じ幅になるように指定されます。逆にmax-content
はグリッドトラックに含まれるもっとも幅が広い要素と同じ幅になるように指定されます。
値 | 説明 |
---|---|
min-content |
overflowを起こさない範囲で要素を縮めた最小の幅。そのボックス内にある一番文字数の多い単語や、一番長いインラインアイテムまで縮める |
max-content |
その中のインライン要素やテキストが改行を起こさない範囲で伸ばした最小の幅 |
min-content
の動きをデモで確認してみましょう。HTMLは前述のリストに画像を加えたものです。
<div class="List">
<div class="List_Item">
<img class="List_Img" src="./img/banner.png" alt="">
</div>
<div class="List_Item"></div>
<!-- 以下繰り返し -->
</div>
追加した画像の幅は500px
ですが、CSSでは幅100%
かつ最小幅を250px
としています。
.List {
display: grid;
gap: 10px;
grid-template-columns: minmax(min-content, min-content) 1fr 1fr;
/* grid-template-columns: min-content 1fr 1fr; と同じ意味 */
}
.List_Img {
display:block;
width: 100%;
min-width: 250px;
}
デモを見るとわかりますが、1つめのグリッドトラックの幅は、最小のコンテンツになるので、ここではCSSで指定された画像幅の250px(min-width: 250px
)がグリッドトラックの幅となります。
max-content
の動きもデモで確認してみましょう。
.List {
display: grid;
gap: 10px;
grid-template-columns: minmax(max-content, max-content) 1fr 1fr;
/* grid-template-columns: max-content 1fr 1fr; と同じ意味 */
}
.List_Img {
display:block;
width: 100%;
min-width: 250px;
}
1つめのグリッドトラックの幅は、最大のコンテンツになるので、画像の最大幅500pxがグリッドトラックの幅となります。
min-contentとmax-contentとの組み合わせ
これだけですと、どう活用すればいいのかがわかりにくいですが、2つの値を組み合わせると次のようになります。
.List {
display: grid;
gap: 10px;
grid-template-columns: minmax(min-content, max-content) 1fr 1fr;
}
.List_Img {
display:block;
width: 100%;
min-width: 250px;
}
1つめのグリッドトラックのサイズを、minmax(min-content, max-content)
としたことで、最小が「最小コンテンツの幅」となり、最大が「最大コンテンツ幅」になるため、幅が可変するようになります。
auto
minmax()関数に使うauto
は次のような振る舞いをします。
- minmax()関数の最小(第一引数)に指定された場合は
min-content
と同じになる - minmax()関数の最小(第二引数)に指定された場合は
max-content
と同じになる
つまり、先ほどのリストで紹介したCSSは、auto
を使い、次のように書き換えることができます。
.List {
grid-template-columns: minmax(auto, auto) 1fr 1fr;
/* grid-template-columns: minmax(min-content, max-content) 1fr 1fr; と同じ意味になる */
/* grid-template-columns: auto 1fr 1fr; とも同じ意味になる */
}
筆者は、auto
がmin/max-content
と同じ振る舞いをするなら、auto
だけで良いのでは?という疑問がありました。しかし、次のようなことをしたい場合に、最小値にmax-contentを指定することがあるかもしれません。
.List {
grid-template-columns: minmax(max-content, 1fr) 1fr 1fr;
}
こうすれば、最小はコンテンツの最大幅になり、画面幅が広いときは1fr
になるといったことが指定ができます。
minmax()を活用したページレイアウト
ここまで個別にminmax()関数に指定できる値を解説してきましたが、まとめとして、このminmax()をページのレイアウトに使用した例を紹介します。
このデモでは、ヘッダーは画面幅いっぱいに配置され、コンテンツ部は指定した最大幅以上にならず、左右に均等な余白を持って、画面の中央に配置されます。
HTMLは次のとおりです。
<div class="Grid">
<div class="Grid_Header">
ヘッダ
</div>
<div class="Grid_Body">
メインコンテンツ
</div>
</div>
CSSでは、どういった枠を作り、その枠にどの要素を当てはめるか、という指定をしています。
.Grid {
display: grid;
gap: 10px;
grid-template-columns: minmax(10px, 1fr) minmax(0, 980px) minmax(10px, 1fr);
grid-template-rows: auto auto;
}
.Grid_Header {
grid-row: 1 / 2;
grid-column: 1 / 4;
}
.Grid_Body {
grid-row: 2 / 3;
grid-column: 2 / 3;
}
この実装の要になるのはgrid-template-columns
の指定です。
grid-template-columns: minmax(10px, 1fr) minmax(0, 980px) minmax(10px, 1fr);
このgrid-template-columns
プロパティ値の意味を図解すると次のようになります。
- 1つめと3つめのグリッドトラックは、最小
10px
、最大は1fr
- 2つめのグリッドトラックは、最小
0px
、最大は980px
ここに、.Grid_Header
と.Grid_Body
を配置します。抜粋したコードは次のとおりです。
.Grid_Header {
grid-row: 1 / 2;
grid-column: 1 / 4;
}
.Grid_Body {
grid-row: 2 / 3;
grid-column: 2 / 3;
}
このコードを図解すると次のようになります。
.Grid_Header
は画面幅いっぱいに配置される.Grid_Body
は中心の部分に配置され、左右に余白を持つようにする
CSS Gridを使用せずに、同様の振る舞いを実装しようとすると、ネガティブマージンを使用したり、.Grid_Body
に幅や左右の余白の指定をする必要があります(他にも方法はありますが)。
CSS Gridを使用すれば、グリッドコンテナである.Grid
でレイアウトを定義し、グリッドアイテム(.Grid_Header
と.Grid_Body
)をそのレイアウトに当てはめればいいので、CSSが簡潔になります。
ここまでのまとめ
今回はCSS Gridの仕様で変更があったgap
プロパティをはじめ、前回の「これからのグリッドレイアウト」シリーズで書ききれなかったプロパティの値を紹介しました。
次回はrepeat()関数などを中心にプロパティの値を紹介をしたいと思います。