CSSマージンについて知っておくべきことすべて
公開: 2022-03-10 CSSを学んだときに私たちのほとんどが最初に学んだことの1つは、CSSボックスモデルと呼ばれるCSSのボックスのさまざまな部分の詳細でした。 ボックスモデルの要素の1つは、ボックスの周囲の透明な領域であるマージンです。これにより、他の要素がボックスの内容から押し出されます。 margin-top
、 margin-right
、 margin-bottom
、 margin-left
各プロパティは、CSS1で、4つのプロパティすべてを一度に設定するための省略形のmargin
とともに説明されていました。
マージンはかなり単純なもののようですが、この記事では、マージンの使用に関して人々をつまずかせるいくつかのことを見ていきます。 特に、マージンが互いにどのように相互作用するか、そしてマージンの崩壊が実際にどのように機能するかを見ていきます。
CSSボックスモデル
CSSボックスモデルの一部に関するすべての記事と同様に、それが何を意味するのか、CSSのバージョンを通じてモデルがどのように明確化されているのかを定義する必要があります。 ボックスモデルとは、ボックスのさまざまな部分(コンテンツ、パディング、境界線、マージン)がどのように配置され、相互に作用するかを指します。 CSS1では、ボックスモデルは、下の画像に示すASCIIアート図で詳細に示されていました。
ボックスの両側の4つのマージンプロパティとmargin
の省略形はすべてCSS1で定義されています。
CSS2.1仕様には、ボックスモデルを示すための図があり、さまざまなボックスを説明するために引き続き使用する用語も定義されています。 仕様では、 content box
、 padding box
、 border box
、およびmargin box
について説明します。それぞれ、コンテンツのエッジ、パディング、ボーダー、およびマージンによって定義されます。
現在、ワーキングドラフトとしてレベル3ボックスモデルの仕様があります。 この仕様では、ボックスモデルとマージンの定義についてCSS2を参照しているため、この記事の大部分で使用するのはCSS2の定義です。
マージンの崩壊
CSS1仕様では、マージンを定義しているため、垂直マージンが折りたたまれることも定義されています。 それ以来、この崩壊行動はマージン関連のフラストレーションの原因となっています。 マージンの折りたたみは、初期の頃、CSSがドキュメントの書式設定言語として使用されていたことを考えると理にかなっています。 マージンの折りたたみとは、下マージンのある見出しの後に上マージンのある段落が続く場合、それらのアイテム間に大きなギャップが生じないことを意味します。
余白が折りたたまれると、2つの要素間のスペースが、2つの余白の大きい方になるように結合されます。 小さい方のマージンは、基本的に大きい方のマージンの内側になります。
マージンは、次の状況で崩壊します。
- 隣接する兄弟
- 完全に空のボックス
- 親と最初または最後の子要素
これらのシナリオでマージンが崩壊するのを防ぐものを見る前に、これらのシナリオのそれぞれを順番に見てみましょう。
隣接する兄弟
マージンの崩壊についての私の最初の説明は、隣接する兄弟間のマージンがどのように崩壊するかを示すものです。 以下の状況を除いて、通常のフローで2つの要素が次々に表示される場合、最初の要素の下部マージンは、次の要素の上部マージンとともに折りたたまれます。
以下のCodePenの例では、3つのdiv
要素があります。 1つ目は、上下のマージンが50ピクセルです。 2番目の上下の余白は20pxです。 3番目の上下のマージンは3emです。 最初の2つの要素間のマージンは50ピクセルです。これは、上部のマージンが小さいほど、下部のマージンが大きいためです。 3emは2番目の要素の下部にある20ピクセルよりも大きいため、3emの2番目の2つの要素間のマージン。
完全に空のボックス
ボックスが空の場合、その上下の余白が互いに折りたたまれる可能性があります。 次のCodePenの例では、クラスが空の要素の上下の余白は50ピクセルですが、1番目と3番目の項目の間のスペースは100ピクセルではなく、50です。これは2つの余白が折りたたまれているためです。 そのボックスに何かを追加すると(パディングも)、上下の余白が使用され、折りたたまれません。
親と最初または最後の子要素
これは、特に直感的ではないように思われるため、最も頻繁に人々を捕らえるマージン崩壊シナリオです。 次のCodePenには、ラッパーのクラスを持つdiv
があり、そのdiv
に赤いoutline
を付けて、どこにあるかを確認できるようにしています。 3つの子要素はすべて50ピクセルのマージンを持っています。 ただし、最初と最後のアイテムはラッパーの端と同じ高さになります。 要素とラッパーの間に50ピクセルのマージンはありません。
これは、子のマージンが親のマージンとともに崩壊し、親の外側になってしまうためです。 DevToolsを使用して最初の子を検査すると、これを確認できます。 強調表示された黄色の領域はマージンです。
ブロックマージンのみが崩壊
最後の例では、マージンの崩壊についても強調しています。 CSS2では、折りたたむように垂直方向の余白のみが指定されています。これは、水平方向の書き込みモードの場合、要素の上下の余白です。 したがって、上の左右の余白は折りたたまれておらず、ラッパーの外側になってしまいます。
注:余白は、段落間など、ブロック方向にのみ折りたたまれることを覚えておく価値があります。
マージンの崩壊を防ぐもの
アイテムが絶対位置にある場合、またはフロートしている場合、マージンは決して崩壊しません。 ただし、上記のマージンが崩壊する場所の1つに遭遇したとすると、どのようにしてそれらのマージンが崩壊するのを防ぐことができますか?
崩壊を止める最初のことは、問題の要素の間に何かがある状況です。
たとえば、コンテンツが完全に空のボックスは、境界線やパディングが適用されている場合、上下の余白を折りたたむことはありません。 以下の例では、ボックスに1pxのパディングを追加しました。 ボックスの上下に50ピクセルの余白があります。
これには背後にロジックがあり、ボックスが完全に空で、境界線やパディングがない場合、本質的に見えません。 これは、CMSによってマークアップにスローされた空の段落要素である可能性があります。 CMSが冗長な段落要素を追加している場合は、余白が尊重されるため、他の段落の間に大きなギャップが生じないようにする必要があります。 ボックスに何かを追加すると、それらのギャップが生じます。
同様の動作は、親を介して崩壊する最初または最後の子のマージンで見ることができます。 親に境界線を追加すると、子の余白は内側に留まります。
繰り返しになりますが、動作にはいくつかのロジックがあります。 視覚的に表示されないセマンティック目的のラッピング要素がある場合は、おそらくそれらが表示に大きなギャップを導入することを望まないでしょう。 これは、Webがほとんどテキストである場合に非常に理にかなっています。 要素を使用してデザインをレイアウトするときの動作としてはあまり役に立ちません。
ブロックフォーマットコンテキストの作成
新しいブロックフォーマットコンテキスト(BFC)も、含まれている要素を介してマージンが崩壊するのを防ぎます。 最初と最後の子の例をもう一度見て、最終的にラッパーの外側にマージンをdisplay: flow-root
を表示して、新しいBFCを作成すると、マージンは内側に留まります。
display: flow-root
詳細については、私の記事「CSSレイアウトとブロックフォーマットコンテキストについて」をお読みください。 overflow
プロパティの値をauto
に変更すると、同じ効果があります。これにより、新しいBFCも作成されますが、一部のシナリオでは不要なスクロールバーが作成される場合もあります。
フレックスおよびグリッドコンテナ
FlexおよびGridコンテナーは、子のFlexおよびGridフォーマットコンテキストを確立するため、ブロックレイアウトに対して異なる動作をします。 それらの違いの1つは、マージンが崩壊しないことです。
「フレックスコンテナは、そのコンテンツの新しいフレックスフォーマットコンテキストを確立します。 これは、ブロックレイアウトの代わりにフレックスレイアウトが使用されることを除いて、ブロックフォーマットコンテキストの確立と同じです。 たとえば、フロートはフレックスコンテナに侵入せず、フレックスコンテナのマージンはその内容のマージンとともに崩壊しません。」
—フレックスボックスレベル1
上記の例を使用してラッパーをフレックスコンテナに作成し、 flex-direction: column
でアイテムを表示すると、マージンがラッパーに含まれていることがわかります。 さらに、隣接するフレックスアイテム間のマージンは互いに折りたたまれないため、フレックスアイテム間のマージンは100ピクセルになり、アイテムの上下に合計50ピクセルになります。
あなたのサイトのマージン戦略
マージンが崩壊するため、サイトのマージンを一貫して処理する方法を考え出すことをお勧めします。 最も簡単な方法は、要素の上部または下部にマージンのみを定義することです。 このように、マージンのある側は常にマージンのない側に隣接するため、マージンの崩壊の問題に頻繁に遭遇することはありません。
注:ハリー・ロバーツには、マージンの崩壊の問題を解決するためだけでなく、マージンを一方向にのみ設定することが良い考えである理由を詳しく説明した優れた投稿があります。
このソリューションでは、子が親を介して崩壊する際にマージンが発生する可能性がある問題は解決されません。 その特定の問題はあまり一般的ではない傾向があり、なぜそれが起こっているのかを知ることはあなたが解決策を考え出すのを助けることができます。 これに対する理想的な解決策は、 display: flow-root
、古いブラウザのフォールバックとして、 overflow
を使用してBFCを作成したり、親をフレックスコンテナに変えたり、1ピクセルのパディングを導入したりできます。 機能クエリを使用してdisplay: flow-root
サポートを検出できることを忘れないでください。そうすれば、古いブラウザだけが最適ではない修正を取得できます。
ほとんどの場合、マージンが崩壊する(または崩壊しなかった)理由を知ることが重要であることがわかります。 次に、ケースバイケースでその対処方法を理解できます。 何を選択する場合でも、必ずその情報をチームと共有してください。 マージンの崩壊は少し不思議なことがよくあるので、それに対抗するために何かをする理由は自明ではないかもしれません! コード内のコメントは非常に役立ちます。この記事にリンクして、マージンの崩壊に関する知識を共有することもできます。
この記事を、マージンに関連する他のいくつかの情報でまとめると思いました。
パーセンテージマージン
CSSでパーセンテージを使用する場合、それは何かのパーセンテージでなければなりません。 パーセンテージを使用して設定されたマージン(およびパディング)は、常に親のインラインサイズ(水平書き込みモードの幅)のパーセンテージになります。 これは、パーセンテージを使用する場合、要素の周囲全体に同じサイズのパディングがあることを意味します。
以下のCodePenの例では、幅200ピクセルのラッパーがあり、内部には10%のマージンがあるボックスがあり、マージンはすべての辺で20ピクセル、つまり200の10%です。
フロー相対世界のマージン
この記事全体を通して垂直方向のマージンについて話してきましたが、最近のCSSは、物理的な方法ではなく、相対的な流れで物事を考える傾向があります。 したがって、垂直方向のマージンについて話すときは、実際にはブロック寸法のマージンについて話します。 これらの余白は、水平書き込みモードの場合は上下になりますが、左から右に書き込まれる垂直書き込みモードの場合は左右になります。
論理的なフローの相対的な方向を操作すると、上下ではなく、ブロックの開始と終了について話しやすくなります。 これを簡単にするために、CSSは論理プロパティと値の仕様を導入しました。 これにより、フローの相対プロパティが物理プロパティにマップされます。
余白の場合、これにより次のマッピングが得られます(英語または左から右のテキスト方向のその他の水平書き込みモードで作業している場合)。
-
margin-top
=margin-block-start
-
margin-right
=margin-inline-end
-
margin-bottom
=margin-block-end
-
margin-left
=margin-inline-start
また、両方のブロックを同時に、または両方をインラインで設定できる2つの新しい短縮形があります。
-
margin-block
-
margin-inline
次のCodePenの例では、これらのフロー相対キーワードを使用してから、ボックスの書き込みモードを変更しました。余白が物理的な上、右、下、左に縛られるのではなく、テキストの方向に従う方法を確認できます。
MDNの論理プロパティと値の詳細については、SmashingMagazineの私の記事「UnderstandingLogicalPropertiesAndValues」を参照してください。
まとめる
これで、マージンについて知っておくべきことのほとんどを理解できました。 要するに:
- マージンの崩壊は問題です。 それが発生する理由と発生しない場合を理解することは、それが引き起こす可能性のある問題を解決するのに役立ちます。
- 一方向にマージンを設定することは、マージンに関連する多くの頭痛の種を解決するだけです。
- CSSの他のものと同様に、あなたが下した決定をチームと共有し、コードにコメントを付けます。
- 物理的な上、右、下、左ではなく、ブロックとインラインの寸法について考えると、Webが書き込みモードにとらわれない方向に進むときに役立ちます。