この記事について
この記事は、スマートフォン時代のWebデザインスクール や スマートフォン時代のWebコーディングスクール 初回体験レッスンなどをお手伝いして頂いている「やのう まり絵」さんによる寄稿記事です。
フリーランスの「やのう まり絵(@maYrie86)」と申します。普段、Webサイト制作を行っておりWebデザインからコーディング、WP構築を行っています。
共著:世界一わかりやすい Dreamweaver 操作とサイト制作の教科書 CC対応
これから学ぶ方でも教科書通りに手を動かせば一つのサイトが完成する流れになっています。
この記事のターゲットとなる方
「marginって適用されたりされなかったりとよく分からなくて何となく使っている。」
そんな方もいるのではないでしょうか。
その原因の1つとして、marginの相殺がmarginへの理解の難易度を上げているのではないかと思います。
何となくコーディングして何となく作っている場合は、そこまで苦戦することはないかもしれません。
しかし、「何となく」から「しっかり」設計された制作にステップアップする際、きちんとmarginの仕様を把握しておかないと詰まることになるでしょう。
この記事では、marginの相殺についてどのような条件で起きるのか、また起きない条件や書き方について説明します。
オンラインのテキストエディター「CodePen」で自分で違いを比較しながら進めていくとより理解が深まります。
marginの役割
まず、marginとは、要素と要素の間の距離を調整するプロパティです。
2つの要素を並べて、左の要素にmargin-right: 50px; を設定すると下記画像のようになります。
このように、marginは要素の外側の領域(距離)を指定することができます。
ボックスモデル
marginを理解するためにボックスモデルについて理解する必要があります。
このモデルは、コンテンツ領域、margin、border、paddingの4つで領域部分から生成される矩形領域のことです。
paddingがコンテンツ領域の内側に余白を作り、境界線の色や太さをborderで指示することができ、marginは外側の領域の余白を設定できます。
margin、border、paddingは4辺すべての距離の指定ができ、1辺だけを指定することもできます。
marginの相殺
2つの要素にそれぞれ指定されたmarginの値は合算されず、大きい方の値に折りたたまれることをmarginの相殺と言います。 大きい方の値が適用されるため「marginは最低値を指定している」と考えると良いでしょう。
さまざまな回避方法があるため一概に「この条件で必ず発生する」とは断言できませんが、
「displayの値がblock」かつ「上下に隣接した要素」
の条件が重なるとmarginの相殺が起きます。 しかし、組み合わせたプロパティによってはmarginの相殺が起きないこともあります。
「さっきまで起きていなかったのになぜか起きてる。なぜ?」など原因を探るのに無駄に時間がかかることも。
そのような事態にならないためにも、どのような条件で起き、どのような条件で起きないのかきちんと把握することは大切です。
隣り合う兄弟要素の上下
隣接した兄弟要素の上下のmarginで相殺が起きます。
クラス名box02のmargin-topの値を20pxに変えても余白の大きさが変わらず、marginの相殺が起きていることが分かります。
親要素と子要素で起きるmarginの相殺
親要素と子要素との間が接しているときも、marginの相殺が起きます。
親要素と先頭の子要素
親要素と先頭の子要素の間でmarginの相殺が起きると、画像右側のように親要素のmargin-top: 10px; が無効になり子要素のmargin-topが適用されます。
marginが相殺され、親要素box02の背景色(薄黄色)が見えない状態になっています。相殺が起こっていなければ、子要素が指定した50px分の背景色が見えるはずです。
親要素と末尾の子要素
親要素と末尾の子要素の間でmarginの相殺が起きると、画像右側のように親要素のmargin-bottom: 10px; が無効になり子要素のmargin-bottomが適用されます。
空の要素
pタグやdivタグなど何も含んでいないブロック要素がある場合、marginの相殺が起きます。
空の要素もしくは隣接した上下の要素に設定した領域でmarginの相殺が起きます。
WordPressなどCMSで記事を書いていると自動的に空のpタグが挿入されることがあります。
そのようなときにmarginの相殺が起きるので覚えておくと良いでしょう。
marginの相殺が起きない書き方
どのような場合にmarginの相殺が起きるか説明しました。ここからはmarginの相殺が起きないケースを説明します。
左右のmargin
左右のmarginは相殺が起きず、合算されます。
ネガティブマージン
ネガティブマージンとは、marginの値にマイナスを指定することです。
隣り合った要素でどちらか片方でもネガティブマージンが指定された場合、合算値が適用されます。
例えば、50pxと-20pxの相殺は 50px-20px=30pxとなります。 大きい方の値(50px)が適用されることはありません。
上記codepenでは上の要素にmargin-bottom: 10px; を指定し、下の要素にmargin-top: -10px; を指定しています。
marginの相殺が起きているとしたら、大きい方の値10px分の余白が空くはずですが、合算されて0px(余白なし)の状態になっていることが分かるかと思います。
displayの値をinlineにする(インライン要素)
ブロックレベル要素とインライン要素
HTML5以降で廃止された概念で、すべての要素はブロックレベル要素とインライン要素に分けることができました。
例えば、span、a、smallタグなどのdisplayの初期値はinlineでインライン要素と呼ばれ、p、div、h1タグなどの初期値はblockでブロックレベル要素と呼ばれていました。
marginの相殺はブロックレベル要素で起きます。インライン要素の場合、上下のmarginの指定はできません。
HTML5以降ではこのブロックレベル要素とインライン要素という概念がなくなった代わりに、今までの概念を踏襲しさらに細分化した「コンテンツモデル」「カテゴリ」の概念が導入されました。
表示形式をインラインに変更
displayは要素の表示形式を変更するプロパティです。これでinlineを指定するとmarginの相殺は起きません。
1つ目の箱はそのまま(block)で、2つ目の箱にdisplay:inlineを適用させ、1つ目の要素にのみmarginが適用されています。
特定のプロパティを適用する
marginが指定されている方向と同じ方向に特定のプロパティが適用されている場合、maginの相殺は起こりません。
もちろん、回避するためだけに無理やり必要のないプロパティを適用させるのはコードのメンテナンス性も下がるのであまりよろしくありません。
特定のプロパティのあるなしで簡単にmarginの相殺が消えるので仕様を理解していない場合、混乱する可能性があります。
floatを使う
marginを指定している要素にfloatを適用させた場合はmarginの相殺は起きません。
上記では指定した両方の要素にfloatを適用させています。
本来、floatは左右に回り込ませる用途で使用しますが、左右のmarginは相殺しないため、分かりやすいようにここでは縦に並ぶようにしています。
絶対配置
positionの値をabsolute、fixedで絶対配置にした場合、marginの相殺は起きません。それどころかmarginすら効かないこともあります。
例えば、positionでleftの値を指定した場合、配置の起点は左上となり、margin-leftは効きます。
rightの値を指定した場合は右上になり、margin-rightの指定が効きます。
また、marginの値でautoを指定している場合、絶対配置にすると0になります。
クラス名box01のmargin-left: 20px; の値を変更するとbox01が動きます。
絶対配置でtop、left、bottom、rightの値を指定し位置を調整できます。シンプルにメンテナンス性を考えたコーディングをするならば、外側の余白は意識しなくて良いはずなのでmarginを併用することは頻繁にはなさそうです。
親要素と子要素が接しないようにする
親要素の中に文字を入れたり、borderやpaddingを使用するなどして子要素と隣接しないようにするとmarginの相殺は起きません。
borderを付けて親要素との間に隙間をつくる
このように、borderを付けることでmarginの相殺は起きません。
paddingを入れて親要素との間に隙間をつくる
borderと同様で、paddingを入れることでmarginの相殺は起きません。
収まりきらない内容を隠す
overflowの値、hiddenもしくはscrollを指定することで親要素と子要素の間でmarginの相殺は起きません。
クラス名box02のmargin-topの値を30pxにしても余白の大きさは変わらずmarginの相殺が起きていることが分かります。
親要素に高さを指定する
親要素に高さ、または最小の高さを指定すると末尾の子要素とのmarginの相殺は起きません。
クラス名box01のheight: 50px; を消すと薄黄色の背景色がなくなり下の箱との距離が20px分、折りたたまれます。
まとめ
marginの相殺について説明しましたが、いかがでしたでしょうか。
制作環境によってはmarginの相殺が起きないように、marginを指定する時は一定方向にするなど事前にルールを決めることで防ぐことができます。逆にmarginの相殺を利用した使い方もあるでしょう。
しかし、制作の環境はすべて自分でコントロールできるとは限りません。
どのような書き方をすれば防ぐことができるのか、どのような条件で起きるのかなど整理して理解しておくと手の付けやすさは違ってくるはずです。