margin 付きの全幅ボタンは width: 100% ではなく width: stretch にする
width: stretch は「margin を引いた残りの幅」いっぱいに広がるので、margin を付けた全幅ボタンがカードからはみ出さない。
どんな時に使う?
カードの下部に「購入する」のような横幅いっぱいのボタンを置き、周りに margin で余白を取りたいとき。width: 100% は親の幅そのものを要素の幅にするため、そこに左右の margin が足されて右側にはみ出す。calc(100% - 32px) と書けば直せるが、margin を変えるたびに計算も直す必要がある。
stretch は要素の margin box を親(包含ブロック)の幅に合わせる指定なので、margin の値が変わっても自動で残りの幅に収まる。
コード
css
.card button {
display: block;
margin: 16px;
/* 古い Safari / Chrome 向けの接頭辞版 */
width: -webkit-fill-available;
/* Firefox 向けの接頭辞版 */
width: -moz-available;
/* 標準。対応ブラウザではこれが勝つ */
width: stretch;
}| 指定 | 幅の決まり方 | margin 16px のとき |
|---|---|---|
width: 100% | 親の幅そのもの(box-sizing の基準の箱に適用) | 親より 32px 広くなり、はみ出す |
width: calc(100% - 32px) | 手計算で margin 分を引く | 収まるが、margin を変えると壊れる |
width: stretch | margin を除いた残りの幅いっぱい | 自動で収まる |
flex アイテムに付けると、内容の幅ではなく使える幅いっぱいに広げることもできる(height: stretch も同様)。
注意点・対応状況
- 標準の
stretchは Chrome / Edge 138+(2025-06)、Safari 27+(2026-09)。Firefox は標準キーワード未対応で、Baseline には未到達(Limited availability)。 - そのため上の例のように
-webkit-fill-available→-moz-available→stretchの順で重ねて書くのが実用的。ブラウザは理解できない値の宣言を捨て、最後に理解できたものを使う。 display: blockの要素はwidth: autoでも margin を引いた幅に広がる。stretchが効いてくるのは、buttonやinline-block・flex アイテムのように auto だと内容の幅に縮む 要素。
出典
- @sanyampunia(2026-11-07、css tip)
- 対応状況: Web features explorer - stretch、MDN width