CSSのbox-sizingにはないmargin-boxを疑似的に再現する小技

CSSのbox-sizingプロパティには、widthプロパティやheightプロパティなどで指定した幅を、要素のコンテンツ領域に適用するcontent-box (既定値) と、要素の境界 (border) まで適用するborder-boxがあります。

また、W3Cの草案に登場し、FireFoxにのみ先行実装された、要素の内側の余白まで適用するpadding-boxもあります (現在はFireFoxを含む全てのブラウザで使用できません)。

しかし、要素の外側の余白まで適用するmargin-boxというのはW3Cの草案にも登場しません。今回は、このmargin-boxを疑似的に再現する小技を紹介します。

margin-boxの再現にはborder-widthを使用する

いきなり結論ですが、border-widthプロパティをmarginプロパティの代わりに使用します。

.box {
  border: solid;
  border-color: transparent;
  border-width: 0 1rem;
  box-sizing: border-box;
  width: 50%;
}

余白の代わりとなる透明 (transparent) な境界線と、box-sizingプロパティのborder-boxによって、余白を横幅に含めることができます。

注意点として、marginプロパティには%値が使用できますが、border-widthプロパティには%値が使用できません。

margin-boxの再現と同時に背景を設定したい場合

背景色や背景画像などの背景 (background) を設定すると、境界線の下 (z-indexプロパティにおける下)、つまり設定した余白部分にまで表示されてしまいます。

境界線の下の背景を表示させなくするには、background-clipプロパティを使用します。

.box {
  background: #c0c0c0;
  background-clip: padding-box;
  border: solid transparent;
  border-width: 0 1rem;
  box-sizing: border-box;
  width: 50%;
}

background-clipプロパティにpadding-boxを設定することで、要素の内側の余白までが背景の表示領域となります。

margin-boxの再現と同時に境界線を設定したい場合

margin-boxを再現するためにborderプロパティを使用しているため、境界線を設定することができません。しかし、box-shadowプロパティとpaddingプロパティで境界線を再現できます。

.box {
  border: solid transparent;
  border-width: 0 1rem;
  box-shadow: inset 0 0 0 1rem #808080;
  box-sizing: border-box;
  padding: 1rem;
  width: 50%;
}

要素の内側にベタ塗りの影を設定し、影の幅と同じだけ内側の余白を設定します。

margin-boxの再現と同時に角丸や影を設定したい場合

透明の境界線を設定しているため、border-radiusプロパティによる角丸や、box-shadowプロパティによる影は、意図しない表示のされ方になってしまいます。

しかし、背面に配置した擬似要素に角丸や影を設定することで意図した通りの表示が再現できます。

.box {
  border: solid transparent;
  border-width: 0 1rem;
  box-sizing: border-box;
  position: relative;
  width: 50%;
}
.box:before {
  background: #c0c0c0;
  border: solid 1rem #808080;
  border-radius: 1rem;
  box-shadow:0 0 1rem #000;
  content: "";
  position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
  z-index: -1;
}

疑似的に再現したmargin-boxの使いどころ

ここまで、margin-boxの再現と様々な表示方法を紹介してきましたが、calc関数値を使用しても同様の表示方法は可能です。

.box {
  background: #c0c0c0;
  border: solid 1rem #808080;
  border-radius: 1rem;
  box-shadow: 0 0 1rem #000;
  box-sizing: border-box;
  margin-right: 1rem;
  margin-left: 1rem;
  width: calc(50% - 2rem);
}

しかし、全体の幅から余白の幅を引き算する必要があるため、全体の幅と余白の幅が決まっていなければなりません。

そのため、margin-boxが便利だと感じられる場面は、全体の幅と余白の幅を分けて設定する必要がある場合などでしょう。

margin-boxを疑似的に再現しなくても、大抵はcalc関数値でどうにかなっちゃいます。

関連記事