fit-content, min-content, max-contentの便利な使い方、CSSでコンテンツに依存してサイズを決める
Post on:2020年2月14日
CSSで要素やレイアウトのサイズを指定する方法には、幅や高さを固定値にサイズを定義する方法とその中のコンテンツに依存してサイズを決める方法があります。
この2つの方法それぞれのメリットと使い分け方、特にレスポンシブで効果的なコンテンツに依存してサイズを決める方法を使ったテクニックについて紹介します。
Intrinsic Sizing In CSS
by Ahmad Shadeed
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- CSSでのサイズ指定方法とは
- 外因性サイジング
- 内因性サイジング: min-content
- 内因性サイジング: max-content
- 内因性サイジング: fit-content
- ブラウザのサポート状況
- 実際の使用例
- 終わりに
CSSでのサイズ指定方法とは
CSSには、内因性と外因性の2つのサイズ指定方法があります。一般的な方法は外因性で、要素の幅や高さに固定値を使用します。内因性は、要素内のコンテンツのサイズに依存して要素のサイズが決まります。
ここでは内因性と外因性の2つのサイズ指定方法についてそれぞれの価値を探り、それらのメリットがどのように得られるのかを見ていきます。また、CSS Gridやその他のプロパティと組み合わせて使用する方法についても解説したいと思います。
外因性サイジング
外因性サイジングとは、明示的な値を使用して要素のサイズ(幅や高さ)を設定することです。簡単な例を見てましょう。
1 2 3 |
.c-button { width: 100px; } |
ボタンの幅は100pxに設定されており、これを外因性サイジングと呼びます。他の例として、<div>要素があります。デフォルトではブロック要素で、その幅は親の100%です。
場合によっては、コンテンツに基づいて要素のサイズを決定したいことがありますが、その場合には外因性サイジングを使用しても役に立ちません。内因性の値でどのようにサイズを設定すればよいか見てましょう!
内因性サイジング: min-content
min-content値は内因性の最小幅で、要素のコンテンツで最も長い単語の幅に等しくなります。
ボックス内で自動改行される場合、そのコンテンツを収納するインラインサイズ。
CSS Working Group (CSSWG)
正直なところ、私はCSSWGのこの定義をよく理解していませんでしたが、要素の周りにボックスを配置すると、すべてのコンテンツが折り返され、ボックスの幅がその要素の中で最も長い単語になることを意味すると思います。もし間違えていたら、ご指摘ください。
見出しを例に見てましょう。
1 |
<h2>A title for an awesome article</h2> |
1 2 3 |
h2 { width: min-content; } |
上: 通常、下: min-content
min-contentをwidthの値として定義した場合、要素の幅は最も長い単語の幅に等しくなります。上記の例では「awesome」と同じ幅になります。
See the Pen
Intrinsic Sizing by Ahmad Shadeed (@shadeed)
on CodePen.
内因性サイジング: max-content
max-content値は内因性の優先幅で、コンテンツの幅に等しくなります。
さきほどと同じ、見出しを例に見てましょう。
1 2 3 |
h2 { width: max-content; } |
上: 通常、下: max-content
要素の幅がコンテンツ(テキスト)に等しくなったことに注目してください。この幅は動的なので、テキストが変更されるとそれに応じて幅が変更されます。
内因性サイジング: fit-content
fit-contentは、min-contentとmax-contentを組み合わせたものです。
fit-contentはmax-contentを使用します。利用可能領域 < max-contentでない限り利用可能領域を使用し、利用可能領域 > min-contentでない限りmin-contentを使用します。
Stackoverflow
言葉だと分かりにくいですね。利用可能領域・max-content・min-contentのどれになるかフローにしてみました。
利用可能領域、min-content、max-contentのフロー
利用可能領域(available)は、ビューポートで使用可能なスペースのことです。
実際にどのように機能するか見てみましょう。
さきほどと同じ、見出しを例にします。
1 2 3 |
h2 { width: fit-content; } |
ビューポートのサイズを変更するとどうなるかは、下記をご覧ください。
widthにfit-contentを定義した場合
fit-contentを定義すると、利用可能領域がmax-widthよりも大きいかどうかチェックをして、widthがmax-contentに等しいかチェックします。利用可能領域がmax-contentより小さい場合、widthは利用可能領域に等しくなります。そして最後に、利用可能領域がmin-contentより小さい場合、widthはmin-contentに等しくなります。
内因性サイジングの値の基本を説明したので、実際の使用例を見てましょう。
ブラウザのサポート状況
Edgeを除くすべての主要なブラウザが内因性の値をサポートしているため、サポートは良好です。ちなみに、chromiumベースのEdgeはサポートしています。
実際の使用例
画像とキャプション
figure要素はブロック要素のため、その幅は親の100%になります。
1 2 3 4 |
<figure> <img src="blueberry-cheesecake-x.png" alt=""> <figcaption>..</figcaption> </figure> |
figure要素で実装した画像とキャプション
期待する動作は、figure要素が画像の幅に合わせたサイズになることで、キャプションも画像の幅に折り返されます。これは、max-contentの出番です!
figure要素にmax-conentを与えることにより、figure要素の幅がコンテンツと等しくなります。
1 2 3 4 5 |
figure { width: max-content; margin-left: auto; margin-right: auto; } |
figure要素にmax-conentを加える
ただし、画像の幅がビューポートより小さい場合は問題ありませんが、大きい場合には横スクロールが表示されてしまいます。
画像がビューポートより大きいと、横スクロールが表示される
この問題を解決するには、fit-contentを使用する必要があります。fit-contentを使うと、画像の幅はビューポートを超えません。
1 2 3 |
figure { width: fit-content; } |
See the Pen
Figure Caption - 2 by Ahmad Shadeed (@shadeed)
on CodePen.
タイトル付き区切り線
「Top Stories」というタイトルがあり、このテキストは2行で表示させたいとします。区切り線の幅は動的で、タイトルが何であれ2行にする必要があります。
タイトル付き区切り線
これを実現するには、min-contentが役立ちます。
1 2 3 |
span { width: min-content; } |
See the Pen
Separator With Text by Ahmad Shadeed (@shadeed)
on CodePen.
アンダーライン付きタイトル
アンダーライン付きタイトルは、コンテンツと同じ幅のボーダーを持つ見出しです。
アンダーライン付きタイトル
見出しはブロックレベルの要素であることに注意してください。これを実現するには、<span>要素でコンテンツを内包し、その<span>要素にボーダーを適用します。
1 |
<h2><span>A title for an awesome article</span></h2> |
1 2 3 |
h2 span { border-bottom: 2px solid #e2deed; } |
さらによくするために、fit-contentを使用できます。fit-contentにより、コンテンツの長さ分だけタイトルの幅が広がります。
1 2 3 4 5 6 |
h2 { width: fit-content; margin-left: auto; /* For centering */ margin-left: auto; /* For centering */ border-bottom: 2px solid #e2deed; } |
See the Pen
Title With Underline by Ahmad Shadeed (@shadeed)
on CodePen.
コンテンツに基づいたナビゲーション
ナビゲーション
コンテンツに基づいた幅をもつナビーションが必要な場合があります。max-contentを使用することで、簡単に実現できます。
1 2 3 |
.c-nav { width: max-content; } |
See the Pen
Intrinsic Header by Ahmad Shadeed (@shadeed)
on CodePen.
コンテンツに基づいたTODOリスト
内因性の値について使用例を考えていた時に見つけたのが、この記事です。
TODOリストを例に見てみましょう。
TODOリスト
ヘッダ、リスト、フッタの各要素を含むTODOリストです。高さはTODOリストのアイテム数に関係なく、ヘッダとフッタを含めて100%でなければなりません。
これを実現するには、ラッパーにCSS Gridとmin-contentを使用します。
1 2 3 4 5 |
.c-todo { display: grid; grid-template-rows: min-content auto min-content; height: 100vh; } |
ヘッダ、リスト、フッタ、3つの要素で高さ100%
ちなみに、min-contentを使用しない場合は、下記のようになります。
min-contentを使用しない場合
ヘッダとフッタはコンテンツを考慮せずに使用可能なスペースまで拡張されます。ただし、min-contentが追加されると、ヘッダとフッタの高さはそれぞれのコンテンツを超えることはありません。
コンテンツに基づいたチャット
メッセージのシステムを持つアプリを構築することを想像してみてください。下記の例では、ヘッダとチャットとフッタがあり、前述のTODOリストとレイアウト構造がよく似ています。チャットの数が少なく、min-contentもない場合、レイアウトが壊れます。
コンテンツに基づいたチャット
See the Pen
Intrinsic Test - 2 by Ahmad Shadeed (@shadeed)
on CodePen.
コンテンツに基づいたヒーローセクション
ヒーローセクション内にヘッダを配置することを想像してみてください。期待するのは、ヒーローコンテンツが利用可能なスペースをすべて使用できるようにする動的なレイアウトです。
コンテンツに基づいたヒーローセクション
1 2 3 4 |
.c-section { display: grid; grid-template-rows: min-content 1fr; } |
このレイアウトは2つの行を定義し、最初の行はmin-contentに基づいて高さを決め、2番目の行は使用可能なスペースを占めるように拡張できます。
See the Pen
Intrinsic - Hero by Ahmad Shadeed (@shadeed)
on CodePen.
コンテンツに基づいたサイドバー
私はなぜ固定幅のサイドバーがあるのかいつも不思議に思います。幅がコンテンツベースの場合は、どうなりますか? 例えば、コンテンツに基づいた最小幅と最大幅があるとします。実際に試してみましょう。
1 2 3 4 |
<div class="wrapper"> <aside></aside> <main></main> </div> |
1 2 3 4 |
.wrapper { grid-template-columns: fit-content(150px) 1fr; grid-gap: 1rem; } |
CSS Gridでfit-content関数を使用することで、サイドバーの幅が150pxを超えないようにし、コンテンツが短い場合はそれに合わせて縮小することができます。
コンテンツに基づいたサイドバー
サイドバーから長い単語(Dashboard)を削除してみましょう。
コンテンツが短い場合、サイドバーも短くなる
見出しと説明文
見出しと説明文があるとします。説明文の幅は、それに対応する見出しの幅を超えないようにしてください。どのように実装しますか?
私はこの実装がCSSで可能だとは思いませんでした。しかし、min-contetnとmax-contetnを使用すると実装できます。
見出しと説明文
これを実装するには、ラップするセクションの幅にmin-contentを追加し、見出し要素の幅としてmax-contentを追加することです。
1 2 3 4 5 6 7 8 9 |
section { width: min-content; margin: 0 auto; text-align: center; } h2 { width: max-content; } |
スマホでの調整が必要になることに注意してください。ビューポートよりテキストが長いと、水平スクロールが発生します。
See the Pen
Intrinsic - Test... by Ahmad Shadeed (@shadeed)
on CodePen.
終わりに
ここまでお読みいだたき、ありがとうございます。意見や提案があれば、@shadeed9に気軽に連絡してください。
リソース
sponsors