その箱の大きさはどれくらいですか? CSSレイアウトでのサイズ設定を理解する
公開: 2022-03-10Flexboxとグリッドレイアウトの重要な機能は、グリッドとフレックスアイテムの間、周囲、および内部で使用可能なスペースを分散できることです。 多くの場合、これはうまく機能し、非常に努力することなく、期待していた結果が得られます。 これは、仕様がデフォルトで最も可能性の高いユースケースにしようとしているためです。 ただし、場合によっては、なぜ何かがそのサイズになってしまうのか疑問に思うかもしれません。 または、デフォルトの動作とは異なることをしたい場合があります。 そのためには、基礎となるアルゴリズムがスペースを分散する方法をどのように理解するかを知る必要があります。
この記事では、CSSでのボックスのサイズ設定に関するいくつかの興味深い点を紹介します。 その箱の大きさを正確に理解する上で非常に重要であると私が信じる仕様からいくつかのことを選びました。 時間をかけて読んでください。グリッドでのサイズ設定の方がはるかに不思議ではないことがわかると思います。
BFCを詳しく見る
CSSを使用してレイアウトを作成したことがある場合は、おそらくBFCが何であるかを知っているでしょう。 なぜそれが機能するのか、そしてそれを作成する方法を理解することは有用であり、CSSでレイアウトがどのように機能するかを理解するのに役立ちます。 関連記事を読む→
長さの単位
最も馴染みのあるサイジングから始めることができます。 CSS値と単位モジュールの仕様で説明されている長さの単位。 <length>
がCSSプロパティの許可された値として表示されている場合は、ここにリストされている値の1つを意味します。 これらの値はすべて距離であり、通常は整数とユニット識別子( 12px
や1em
など)で構成されます。 値が0
の場合、ユニット識別子は省略できます。 また、長さの単位は相対長と絶対長に分割されます。
相対的な長さ
相対的な長さは、他のものと比較してサイズが大きくなるため、相対的な長さを使用して定義されたものの最終的なサイズは、相対的なものが変更された場合に異なる場合があります。
相対単位の完全なセットは次のとおりです。 最初の4つの単位はフォント相対であり、最後の4つの単位はビューポート相対です。
-
em
-
ex
-
ch
-
rem
-
vw
-
vh
-
vmin
-
vmax
これらの値は何かに関連しているため、それらが何に関連しているかを正確に識別することが重要です。 フォント相対単位rem
の場合、これは常にHTMLドキュメントであるルート要素のサイズに相対的です。これはhtml
要素です。
以下の最初の例では、 html
要素のフォントサイズを20ピクセルに設定しました。 したがって、 1rem
は20ピクセルです。 次に、要素に10rem
の幅を指定すると、幅は200ピクセルになります(20pxに10を掛けると200になります)。
他のフォント相対単位( em
、 ex
、およびch
)が要素の長さに使用される場合、それらはその要素に適用されるフォントサイズに相対的です。 2番目の例(ボックスの幅は10em
)では、 em
ユニットは、サイズ設定している要素に適用されているフォントを調べ、それに基づいて計算します。 したがって、ボックスのフォントサイズが30px
であるため、このボックスの幅は300ピクセルになります。
フォントの相対単位がフォントサイズから計算される場合、ビューポートの相対単位は、初期の包含ブロックと呼ばれる長方形に関連して計算されます。 画面上では、これはビューポートの寸法になります。 vw
単位は、ビューポートの幅の1/100、高さのvh
/ 100です。 幅が50vw
、高さが50vh
のボックスは、ビューポートの幅と高さの半分にする必要があります。
vmin
およびvmax
単位は、ビューポートの大きい方または小さい方の寸法に応じてサイズを変更できるので便利です。 これは、たとえば、ビューポートの最も長い側の50%を作成できることを意味します。 これは、誰かがデバイスを横向きまたは縦向きモードで保持している可能性がある場合に特に役立ちます。 vmin
ユニットは常に小さいまたはvw
またはvh
に解決され、 vmax
はvw
またはvh
の大きい方に解決されます。 したがって、幅を常にデバイスの最長辺の20%にしたい場合は、 20vmax
を使用できます。 デバイスがポートレートモードで保持されている場合、 20vmax
は20vh
と同じになります。 デバイスがランドスケープモードで保持されている場合、 20vw
と同じになります。
以下の例では、 vw
およびvh
でサイズ設定されたブロックと、 vmin
およびvmax
を使用してサイズ設定されたブロックを比較しています。 デスクトップコンピュータ、またはランドスケープモードの電話では、両方のボックスが同じサイズで表示されます。 電話をポートレートモードに切り替えるか、ウィンドウをドラッグして幅が高さよりも小さくなるようにすると、2番目のブロックが計算の元となる寸法をどのように変更するかがわかります。
絶対単位
絶対単位は物理的な寸法にマッピングされ、画面上の他のものと比較して拡大縮小されません。 したがって、これらは出力環境がわかっている場合に最も役立ちます。
以下のリストは、CSSで許可されている絶対単位を示しています。
-
cm
-
mm
-
Q
-
in
-
pc
-
pt
-
px
ご覧のとおり、これらの多くは画面のコンテキストではほとんど意味がありませんが、印刷用のCSSを作成している場合は、用紙サイズがわかっているときにpt
またはin
を使用すると意味があります。
ピクセルは絶対長の単位として分類され、網膜デバイス用の画像を作成した人なら誰でも知っているように、長さの点でのピクセルはデバイスのピクセルと同じではありません。 CSSは参照ピクセルの概念を使用しており、仕様では、ピクセル単位が参照ピクセルに最も近いデバイスピクセルの整数を参照することを推奨しています。
参照ピクセルは、ピクセル密度が96dpiで、リーダーから腕の長さの距離にあるデバイス上の1ピクセルの視角です。 したがって、名目上の腕の長さが28インチの場合、視角は約0.0213度になります。 したがって、腕の長さで読み取る場合、 1pxは約0.26 mm( 1/96インチ)に相当します。 —「CSS値と単位モジュールレベル3」、W3C
パーセンテージ
ほとんどの場合、サイズには長さの単位ではなくパーセンテージを使用できます。 このパーセンテージは、相対的な長さの単位が解決されるのと同じ方法で、何かに関連して計算する必要があります。使用しているレイアウト方法の仕様は、パーセンテージが何パーセントであるかを示します。
<length-percentage>
が長さの許容値として表示される仕様では、これは、パーセンテージが使用される前に長さに解決されることを意味します。 次の例では、外側の要素の幅は400ピクセルで、最初の子要素の幅は50%です。 これにより、200ピクセル(400の50%)に解決されます。
2番目の子要素の幅はcalc
を使用して、50ピクセルを50%に追加し、そのブロックの幅を250ピクセルにします。 したがって、50%は長さに解決され、計算に使用されます。
レスポンシブデザインの時代を通してウェブに取り組んできた私たちの人々は、グリッド上に配置されているように見えるレイアウトを作成するためにパーセンテージを使用することに慣れています。 パーセンテージで作業することで、ある程度の制御が可能になります。GridとFlexboxの機能を十分に活用するには、あきらめ始める必要のある制御です。
CSSの固有および外部のサイジング
これまで、ボックスにサイズを指定する方法、さまざまな方法でボックスの幅と高さを設定する方法、および長さの単位とパーセンテージを使用する方法について説明してきました。 ただし、 Webページ上のボックスにはサイズがあります(ボックスを指定していなくても) 。 要素がページ上にどのように配置されるかを理解することが重要であり、フレックスボックスとグリッドレイアウトを使用する場合、そのサイズはますます重要になります。 グリッドとフレックスボックスに組み込まれている柔軟性の多くは、アイテムを表示するために必要なスペースよりも多くのスペースがある状況、またはスペースが無限である場合に占めるスペースよりも少ないスペースにアイテムを収める必要がある状況を管理するためです。
サイズを定義し、そのサイズを制御するための追加の方法を提供するモジュールは、CSS Intrinsic and Extrinsic SizingModuleです。 この次のセクションでは、このモジュールが何を定義するのか、そしてフレックスボックスとグリッドのレイアウトを理解するためにそれが重要である理由を見ていきます。
キーワードのサイズ設定
モジュールの要約は次のように述べています。
このモジュールは、コンテンツベースの「固有」サイズとコンテキストベースの「外部」サイズを表すキーワードを使用してCSSサイズ設定プロパティを拡張し、CSSがコンテンツまたは特定のレイアウトコンテキストに適合するボックスをより簡単に記述できるようにします。
キーワードは、通常は長さがかかるすべてのプロパティに使用できます。 たとえば、グリッドレイアウトのトラックのサイズ設定、およびフレックスボックスflex-basis
で使用するために指定されていることに加えて、 width
、 height
、 min-width
などです。 レベル3コア仕様の現在の編集者ドラフトで定義されているキーワード値は次のとおりです。
-
max-content
-
min-content
-
fit-content(<length-percentage>)
これらのキーワードのいくつかをdivの幅に使用した場合の動作を見てみましょう。 divはブロックレベルの要素であるため、幅を指定しないと、インラインディメンションで可能な限り広くなるように拡張されます。 ビューポートまたは包含ブロックの端に到達するまで。
テキストの文字列が許可されたスペースよりも長い場合、それはdiv内で折り返され、ボックスはそれを収容するために高くなります。 divに、包含ブロックで許可されているスペース以外の幅を与えるには、前述の長さの単位のいずれかを使用できます。 テキストは、その長さに達するとすぐに折り返され始めます。
長さを使用して、またはそれが含まれているブロックの端に当たることによってボックスを制約する代わりに、コンテンツがサイズを指示できるようにすることができます。 ここで、これらの新しいコンテンツベースのサイジングキーワードが登場します。
min-content
width: min-content
をdivで使用すると、divは必要なだけ大きくなり、コンテンツはインライン方向で可能な限り小さくなります。 テキストの文字列の場合、これは、テキストが可能なすべてのソフトラッピングの機会を利用することを意味します。
これは、この要素の最小コンテンツサイズです。 なんらかの方法でコンテンツがオーバーフローすることなく取得できる最小のもの。
max-content
width: max-content
を使用すると、逆の動作が発生します。 これで、ボックスは、インラインディメンションで可能な限り大きくなると、コンテンツを含むのに十分な大きさになります。 これで、テキストの文字列が引き伸ばされ、折り返されることはありません。 これにより、このdivが拡大する必要のある使用可能な幅よりも広くなると、オーバーフローが発生します。
これらのコンテンツキーワードはブラウザに出荷されており、Chromeで使用でき、Firefoxではwidth
とheight
の値としてプレフィックスとして使用できます。 以下で説明するように、グリッドレイアウトでのトラックのサイズ設定に使用できますが、フレックスボックスではflex-basis
では実装されていません。 ただし、FlexboxとGridでスペースがどのように分散されているかを確認し始めると、最小コンテンツサイズと最大コンテンツサイズを持つものが重要になるため、これらを今見る本当の理由は、最小min-content
とmax-content
が存在することを理解することです。
CSSグリッドレイアウトでのコンテンツベースのサイジング
CSSグリッドレイアウトには、グリッドトラックのサイズ設定に使用される、先ほど調査したコンテンツキーワードの確実な実装があります。 これは、コンテンツにグリッド上のトラックサイズを指示させることができることを意味します。 グリッドで覚えておくべき重要なことは、それが2次元のレイアウトモデルであるということです。 列トラックにmin-content
サイズにするように要求している場合、トラックはトラック内で最も幅の広いものに基づいてサイズが変更されます。
min-content
次の例では、3列のトラックグリッドがあります。 列のサイズは、 min-content
キーワードを使用して決定されます。 セルの1つにはより多くのコンテンツが含まれており、コンテンツが可能な場所でどのように折り返されるかを確認できます。 このコンテンツをmin-content
サイズで表示するために必要なサイズは、トラック全体のサイズになります。
max-content
min-content
の場合と同じ例を見て、列をそれぞれmax-content
を使用するように変更すると、テキストを多く含むアイテムを含むトラックが、テキストに対応するように成長したことがわかります。 これにより、トラックがグリッドを定義した要素のサイズよりも広くなり、オーバーフローしました。
フィットコンテンツ
まだ調べておらず、グリッドレイアウトに実装されているキーワードはfit-content
です。 このキーワードは、値として長さまたはパーセンテージを取ります。 トラックのサイズ設定にfit-content
を使用すると、渡した値のサイズに達するまで、トラックはmax-content
ように動作します。そのサイズに達すると、トラックの成長が停止し、コンテンツがラップされます。
以下の例の3つの列トラックはすべて、 fit-content(10em)
を使用してサイズ設定されています。 トラックが10emより狭い場合、 max-content
ように機能します。 長く走るセンタートラックは、10emに達すると成長を停止します。
注:これらのコンテンツサイズ設定キーワードを示すために、短いビデオチュートリアルを作成しました。
自動サイズのトラック
トラックサイジングのうさぎの穴を深く掘り下げる前に、トラックサイジングに使用するときにauto
が何を意味するかを理解することも重要です。 暗黙のグリッドトラックはauto
サイズ設定で作成されます。通常、グリッドの使用を開始すると、これを理解できます。 列トラックを指定しますが、明示的な定義なしでコンテンツを行に配置します。 auto
がコンテンツサイズを調べ、それを含むのに十分な高さのトラックを作成するため、行トラックはコンテンツを含むように成長します。
ただし、仕様ではauto
には特定の意味があります。 グリッドとフレックスボックスの場合、トラックサイズまたはflex-basis
の値としてauto
を使用すると、アイテム(またはグリッドの場合はそのトラック内のアイテム)にサイズがあるかどうかが確認されます。そのサイズをベーストラックサイズまたはflex-basis
の値として使用します。 以下のCodePenでこれが起こっているのを見ることができます。 最初の例はグリッドレイアウトで、2番目の例はフレックスレイアウトです。 グリッドレイアウトには3つの列トラックがあり、すべてauto
サイズ設定されています。フレックスレイアウトの各アイテムは、 auto
のflex-basis
から拡大および縮小できます。
どちらのレイアウトでも、最終的なアイテムの幅は200pxです。 トラックのサイズを決定するときに、その幅がどのように使用されているかを確認できます。 最後の項目としてflex-basis
になり、グリッドトラックのベースサイズになります。 他のグリッドトラックとフレックスアイテムには幅がないため、アルゴリズムはコンテンツサイズを使用します。
グリッドトラックのサイズを変更するさらに別の方法に移った後、 auto
の動作方法と、他のトラックサイズ設定方法と組み合わせてどのように役立つかについて説明します。
fr
単位
この記事の冒頭で説明したすべての長さの単位は、グリッドレイアウトでのトラックのサイズ設定にも使用できます。 fr
ユニットには追加のユニットもあります。 これはグリッドレイアウトにのみ適用されるため、サイズ設定に関連するモジュールではなく、グリッド仕様で詳しく説明されています。 fr
単位は、柔軟な長さまたは<flex>
であり、グリッドコンテナの残りのスペースの一部を表します。
fr
単位は長さではなく、パーセンテージまたは長さの単位と同じようにcalc()
で使用することはできません。
以下のようなデモがよく見られます。ここでは、 fr
ユニットを使用して3つの同じサイズのトラックを作成しました。 グリッドコンテナ内のスペースは3つに分割され、各トラックに均等に割り当てられています。
ここでのfr
ユニットは、 flex-basis
が0
の場合にFlexboxが動作するように動作します。 グリッドは、グリッドコンテナ内のすべてのスペースを使用し、各トラックに1つのパーツを渡します。 ただし、これを行う場合、グリッドによってトラックがオーバーフローすることはありません。 1fr
の3つのトラックが常に3つの同じサイズのトラックになるという印象を受けている場合、この動作は混乱を招く可能性があります。
スーパーカリフラジリスティックエクスピアリドーシャスのように、ソフトラップできない非常に長い単語をミドルトラックに追加すると、3つの等しい幅の列が得られません。
グリッドは、トラックがアイテムを含むのに十分な大きさであることを確認した後にのみ、使用可能なスペースを共有しています。 グリッドは、 min-content
を使用した場合のトラックのサイズを確認します。 そのサイズがfr
ユニットを介してトラックに渡されるサイズよりも小さい場合、コンテンツは考慮されません。 そのmin-content
サイズがトラックによって指定されるfr
ユニットよりも大きい場合、残りのスペースが共有される前に、 min-content
サイズがそのトラックに使用されます。
したがって、 fr
ユニットは、そのトラックのmin-content
サイズが大きくない限り、フレックスボックスが0
のflex-basis
で行うように機能し、その後、 auto
のflex-basis
を使用するフレックスボックスのように機能します。 前のセクションのauto
の例と同じです。 等しい幅のトラックがあまり等しく見えない場合は、これを覚えておく価値があります。 考えられる理由は、トラックの1つに、渡されるよりも小さいmin-content
サイズの何かがあることです。
ミニマックスで等しいトラックをminmax
これで、 fr
ユニットが必要以上に大きなトラックを作成する理由がわかりました。 ただし、別のグリッド固有のサイジング方法であるminmax()
関数を導入することで、これがどのように動作するかを制御できます。 上記の例(1つのトラックの長い単語がmin-content
サイズを大きくする)では、グリッドは次のトラックサイズ定義を使用しているかのように動作します。
.grid { display: grid; grid-template-columns: minmax(auto,1fr) minmax(auto,1fr) minmax(auto,1fr); }
グリッドは、 content
サイズに解決されるauto
サイズを確認し、残りのスペースを共有する前に、それをトラックの基本サイズとして使用します。
上記の例でグリッドを使用して、オーバーフローが発生した場合でも、グリッドコンテナ内の幅の同じ割合で中央のトラックを強制的に作成する場合は、 minmax()
の最初の値を0
にすることでこれを行うことができます。 次の例でわかるように、これによりオーバーフローが発生します。
仕様がデフォルトで動作する理由がわかります。 一般に、コンテンツを表示するスペースがある場合はオーバーフローが発生しないようにしますが、必要に応じて問題を強制し、オーバーフローを発生させることができます。
minmax()
関数は、行のサイズを変更して、空のときに行がゼロの高さまで折りたたまれないようにする場合にも非常に役立ちますが、コンテンツを追加できるサイズに拡大することもできます。 次の例では、 grid-auto-rows
をminmax(50px, auto)
設定しています。 暗黙的なグリッドのトラックの高さは常に50ピクセルですが、2番目の行の1つのセルのコンテンツの量が多いため、2番目の行の高さが高くなっていることがわかります。
グリッドレイアウトのパーセンテージ
グリッドレイアウトにはfr
単位、コンテンツベースのサイズ設定、および通常の長さの単位がありますが、一部のサイズ設定要件にはパーセンテージを使用することもできます。 ほとんどの場合、 fr
単位の方が適していますが、正確なパーセンテージサイズを自分で制御したい場合もあります。 その理由の1つは、グリッドを使用してレイアウトされた要素を、パーセンテージサイズに依存する他のレイアウト方法も使用するデザインに並べる場合です。
ほとんどの場合、パーセンテージサイジングは期待どおりに機能します。 パーセンテージを使用してサイズ設定されたグリッドトラックは、グリッドコンテナの幅からパーセンテージを計算します。 gap
プロパティにパーセンテージを使用することもできます。これらは、グリッドコンテナの幅に基づいて計算されます。 以下の例には、それぞれ30%の3つの列トラックと、トラック間の5%のグリッドギャップがあります。
注意が必要な場所は、垂直マージンとパディングにパーセンテージを使用する場合です。 FlexboxとGridの両方で、長年の問題は、垂直方向のパーセンテージマージンとパディングの計算方法がブラウザー間で異なることを意味します。
この問題の詳細については、私の投稿「グリッドとフレックスアイテムのマージンとパディングのパーセンテージをどのように解決する必要があるか」を参照してください。ただし、私のアドバイスと仕様のアドバイスは、マージンと上下のパディングにパーセンテージを使用しないようにすることです。結果に一貫性がなくなるためです。
グリッドレイアウトでの配置とサイズ設定
グリッドレイアウトでボックス配置プロパティを使用すると、グリッド内の領域のサイズも変更される可能性があります。 4つの100ピクセルの列トラック、3つの50ピクセルの行トラック、および20ピクセルのギャップがある次のレイアウトについて考えてみます。 グリッドトラックはグリッドコンテナの全領域を占めるわけではないため、両方の軸からstart
するように位置合わせします。 複数のトラックにまたがるアイテムは、それらがまたがるすべてのトラックとギャップの合計であるサイズになります。
Box Alignmentプロパティのalign-content
とjustify-content
をspace-between
値で使用すると、ギャップが増えるにつれてトラックが広がり、余分なスペースが吸収されます。 現在、複数のトラックにまたがるアイテムは、拡大されたギャップからのスペースが含まれているため、大きくなっています。
Flexboxとグリッドのスペース分布を比較
min-content
やmax-content
contentなどの概念を理解することがレイアウトを扱う上で非常に重要であると私が思う理由は、それらがレイアウトのより細かい詳細を掘り下げ始めることを可能にするからです。 この記事をその良い例で締めくくります。これは、アイテムをコンテナーに収める必要があるときにフレックスボックスとグリッドで何が起こるかを比較することでわかります。
この例は、4つのフレックスアイテムを持つフレックスコンテナを示しています。 その下には、4つのグリッドアイテムを含むグリッドコンテナがあります。 このコンテンツは同じですが、レイアウトはほぼ同等ですが、レイアウトは少し異なります。 フレックスアイテムはauto
のflex-basis
を持ち、縮小することができます。 グリッド定義は、すべてauto
のサイズの4つのトラックを定義します。
フレックスボックスの例では、短いアイテムはmin-content
サイズに折りたたまれており、大きいアイテムにはより多くのスペースが割り当てられています。
グリッドの例では、小さいアイテムはmax-content
サイズで表示されるため、長いアイテムは表示するスペースが少なくなります。 この振る舞いを最初に見たとき、私は戸惑いました。 違いの理由は、レイアウトメソッドのアイテムのサイズを計算するアルゴリズムにあります。 Flexboxでは、アイテムはmax-content
サイズで始まります。 flex-shrink
は正の値であるため、各アイテムからスペースが奪われ始めます。 小さいアイテムがmin-content
サイズに達すると、flexboxはスペースの奪取を停止して、アイテムが消えたりオーバーフローしたりするのを防ぎます。
ただし、グリッドはmin-content
サイズのアイテムから開始し、次にスペースを追加します。 アイテムはすぐにmax-content
サイズになり、残りのスペースを埋めることができる大きなアイテムがあるため、グリッドはスペースの割り当てを停止します。 min-content
とmax-content
について理解したので、トラックまたはアイテムがこのように表示されるタイミングを見つけることができます。これにより、何が起こっているのかを掘り下げて理解するための開始点が得られます。
サイズが重要!
物事を並べるためにパーセンテージサイズを計算することは決して楽しいことではありませんでしたが、それは少なくとも私たち全員が理解したことでした。 それは私たちがすべての仕事をしなければならなかったことを意味しましたが、それは私たちに多くのコントロールを与えました。 FlexboxとGridを使い始めたとき、期待したレイアウトが得られないことがあることに気付くと、イライラすることがあります。 自分で作業を行い、 flex-basis
またはトラックのサイズ設定にパーセンテージを使用することに戻って実行したくなる場合があります。
ただし、さまざまな状況で何が起こるかに慣れるまで、サイジングで遊んでいると、最終的には返済されます。 必要なメディアクエリが少なくて済み、レイアウト方法に固有の柔軟性に頼ることができます。
あなたがあなた自身の探求を始めるのを助けるために、私はあなたがそれらをフォークして実験できるように、この記事の例をできるだけ単純に保つように努めました。 この記事で私が共有したことのほとんどは、何か別のことを試してみるとどうなるのか、つまり、試してみて、なぜそれが機能するのかを理解した結果です。 したがって、回答よりも多くの質問が残っている場合は、デモへのリンクを含むコメントを投稿してください。仕様の説明の部分を指摘しようと思います。