CSSのmargin-trimの使い方とgapや:last-childとの使い分け



Webデザインやコーディングにおいて、レイアウトの微調整や余白の扱いには工夫が必要になったりします。

特にカード型のブロックやサイドバーの枠、お知らせ一覧、記事本文などをマークアップする際、最後の子要素の下余白(margin-bottom)が親要素のpaddingと被って余分な隙間が生まれてしまったり、上下の余白が干渉して意図しないレイアウト崩れに繋がったりすることがあります。

FlexboxやGridの登場によって、一律の隙間であれば gap プロパティで手軽に制御できるようになりましたが、要素ごとに異なる余白を設定したい場面などでは、子要素側に :last-child を指定して、末尾の余白を打ち消す処理が必要です。

このコンテナ末尾の余白処理を、親要素側の1行で制御できるようにするのがCSSのmargin-trimプロパティです。

主要ブラウザでのサポートも進みつつあり、実践で使える選択肢となってきています。


最新のブラウザサポート状況は Can I use (margin-trim) にて確認できます。



ここでは、margin-trimの基礎的な仕様と使い方、実際のWeb制作における余白に関係するプロパティの使い分けについてお話しします。

margin-trimの基本構造と使い方

margin-trimは、コンテナ(親要素)側に指定することで、その内部にある子要素が持つ外余白(margin)を自動的にトリムするプロパティです。

これまでは子要素側に :last-child などを指定して余白を消去することが多かったのですが、margin-trimを使えば親要素側のスタイル定義だけで、一括で制御できるようになります。

シンプルなカード構造を例にその使い方をご紹介します。
まずはHTML構造です。

HTML

<div class="card">
  <h2>margin-trim の使い方</h2>
  <p>親要素に <code>margin-trim: block-end;</code> を指定することで、末尾の子要素の下余白だけが自動的にカットされます。</p>
  <a href="#" class="btn">詳細を見る</a>
</div>

よくあるカードデザインの構造です。
コンテナ(親要素)の中に子要素として、コンテンツに必要な要素を配置しています。

CSSでは親要素にmargin-trim: block-end;を追加します。

CSS

/* 親要素 */
.card {
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  background-color: #eee;
  max-width: 480px;
  margin: 1.875rem auto;

  /* コンテナ末尾にある子要素の余白(margin-bottom)を自動カット */
  margin-trim: block-end;
}

/* 子要素には個別の余白を設定 */
.card h2 { margin-bottom: 1.25rem; }
.card p  { margin-bottom: 0.75rem; }
.card .btn { margin-bottom: 1rem; }


margin-trim未指定時では、.btnに設定されたmargin-bottom (1rem) がそのまま残ります。

Safariのデベロッパーツールで.btnのボックスモデルを確認した画面。margin-bottomに16(1rem相当)が残っている状態。
margin-trim未指定時:margin-bottomがそのまま適用される



margin-trim: block-endを指定すると、親要素で一括トリムされ、.btnのmargin-bottomが「-」と削除され処理されます。

Safariのデベロッパーツールで.cardにmargin-trim: block-endを指定後、.btnのボックスモデルを確認した画面。margin-bottomが「-」と表示されている状態。
margin-trim: block-end指定時:親要素で一括カットされ、margin-bottomが「-」と無効化される



margin-trimには、レイアウトの向きや方向に応じた値が用意されています。

  • block-end
    ブロック軸の末尾(通常のWebレイアウトでは最後の子要素のmargin-bottom)をトリム

  • block-start
    ブロック軸の先頭(最初の子要素のmargin-top)をトリム

  • inline-end / inline-start
    インライン軸(横並びレイアウト時)の先頭・末尾余白をトリム

  • all
    コンテナの上下左右すべての端に接している子要素の外余白をまとめてトリム



上から下へ要素を配置していく通常のWebサイト制作では、今回紹介したblock-endを指定してコンテナ末尾の下余白を消す使い方がメインになります。状況に応じてblock-startやallを使い分けることで、コンテナ外周の余白を一括して綺麗に管理できます。

display: blockやFlexbox / Gridでの動作挙動


margin-trimはW3Cの最新仕様において、通常のブロックコンテナ(display: block)だけでなく、Flexbox(display: flex)やGrid(display: grid)のブロック軸(縦方向)に対しても標準で適用されるプロパティです。

ただ、ブラウザやバージョンごとの実装段階(特にChromium系)によっては、マージンの相殺計算の有無やコンテナ構造の違いによって、レンダリング挙動に若干の差異が生じるケースがあります。

そのため、どのブラウザで表示しても安定したレイアウトを保つためには、サポート環境を意識した余白の使い分けとフォールバック設計がポイントになります。

余白設計の使い分けとフォールバック実装


margin-trimを取り入れる際は、コンポーネントの仕様や対象ブラウザに応じて実装方法を使い分けることになります。

※横にスクロールして確認できます

構造・デザイン別の実装パターン:余白設計における使い分け
デザインの状況 現在の推奨パターン 今後の理想パターン
余白が一律(均等) Flex / Grid + gap Flex / Grid + gap
要素ごとに余白が異なる margin-trim + 非対応環境向けフォールバック margin-trimで一括指定


ここからは、想定される2つのケースに分けて解説します。

パターンA:要素間の余白が一律の場合

見出しや本文、ボタン同士の間隔がすべて1remのように統一されているコンポーネントであれば、margin-trimや:last-childを使う必要はありません。gapプロパティで指定すれば十分です。

CSS

.card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.5rem;
  background-color: #eee;
  max-width: 480px;
  margin: 1.875rem auto;
}


gapは要素同士の間にだけ余白を作る仕様のため、最後の子要素の下に不要な余白が発生しません。一律の余白で完結するレイアウトであれば末尾の余白を消す処理が要らないため、コードの記述量も最小限で済みます。

パターンB:要素ごとに余白が異なる場合(フォールバックの書き方)

見出しの下は広め(1.25rem)、本文の下は少し狭く(0.75rem)、ボタンの下は普通(1rem)といったように、要素ごとに異なる余白を設定したいケースではgapだけでの制御が難しくなります。

このようなケースでは親要素側でmargin-trim: block-endを指定しつつ、@supports not を使用して未対応環境へのフォールバック(:last-childによるリセット)を記述します。

CSS

.card {
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  background-color: #eee;
  max-width: 480px;
  margin: 1.875rem auto;

  /* 親要素で末尾の余白を一括カット */
  margin-trim: block-end;
}

.card h2 { margin-bottom: 1.25rem; }
.card p  { margin-bottom: 0.75rem; }
.card .btn { margin-bottom: 1rem; }

/* 未対応ブラウザ向けのフォールバック */
@supports not (margin-trim: block-end) {
  .card > *:last-child {
    margin-bottom: 0 !important;
  }
}

● フォールバック記述のポイント

親要素側のmargin-trim: block-endで基本ルールを定義しつつ、margin-trimが非対応のブラウザでは @supports not 内のスタイルが適用されます。

子要素側(.card .btn など)の個別指定に対する優先度(詳細度)を確保するため、フォールバック側には !important を付与して確実にmargin-bottom: 0へ上書きリセットさせています。

ブロック要素(display: block)で構築する場合

コンポーネントの構造によっては、display: flexやflex-direction: columnを使わず、デフォルトのブロック要素(display: block)のまま要素を並べたい場面もあります。

その場合も、コードの書き方は同じです。

CSS

/* 親要素(通常のブロックコンテナ) */
.card {
  padding: 1.5rem;
  background-color: #eee;
  max-width: 480px;
  margin: 1.875rem auto;

  /* コンテナ末尾にある子要素の余白(margin-bottom)を自動カット */
  margin-trim: block-end;
}

/* 子要素には個別の余白を設定 */
.card h2 { margin-bottom: 1.25rem; }
.card p  { margin-bottom: 0.75rem; }
.card .btn {
  margin-bottom: 1rem;
  display: block;
  width: fit-content;
}

/* 未対応ブラウザ向けのフォールバック */
@supports not (margin-trim: block-end) {
  .card > *:last-child {
    margin-bottom: 0 !important;
  }
}


親要素はFlexboxでなくても、ブロック構造のまま綺麗にレイアウトできます。
margin-trimに対応しているブラウザでは親要素側で余白が削られ、未対応のブラウザでは @supports not 内の:last-childが効くため、表示が崩れる心配もありません。

余白指定の使い分けと注意点


デザインの余白が一律ならgapを使います。そもそも末尾の余白を打ち消す指定が不要なため、手軽でレイアウト崩れも起きません。

見出しや本文など、要素ごとに余白を変えたい場面ではmargin-trimが活きてきます。未対応のブラウザを考慮する場合は、今回紹介した @supports not のフォールバック(:last-child)をセットで書いてカバーします。

なおmargin-trimは、ブラウザ側(特にChromeやEdge)の実装が進んでいる段階のプロパティですので、今後のブラウザアップデートで挙動や判定が変わる可能性もあります。 実案件で導入する際はフォールバックの動きまで実機やデベロッパーツールで確認しておくといいでしょう。