質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

3回答

2431閲覧

overflow:hiddenとmarginの関係性

olaf

総合スコア17

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2017/09/04 11:51

初歩的な質問でごめんなさい。

html

1 2<div class="parent"> 3 <div class="child">demo</div> 4</div> 5 6<style type="text/css"> 7 .parent { 8 margin:30px 0; 9 overflow:hidden; 10 } 11 .child { 12 margin:10px 0; 13 } 14</style>

とした場合、なぜ親要素が子要素のmarginを相殺しないのかが分かりません。
どのような構造になっているのか教えていただければ幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

CSSの仕様書のmarginの相殺の部分に以下のように記述してあります。

Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.

marginが相殺されるパターンは、水平方向では起こらず、垂直(oriental)方向で行われます。
また、その他にも条件があり、親のmargin-(top|bottom)と子のmargin-(top|bottom)の間に何もないことが条件です。
なので、子要素にborderやpaddingなどがあると相殺は起きません。

また、理由はわかりませんが、新しいブロック書式コンテキストの場合も同様に相殺が起きないらしいです。
これはfloatがnone以外の浮動要素やoverflowがvisible以外の場合です。

ブロック書式コンテキストとブロックレベル要素がごちゃごちゃしてわかりにくいですが、以下に書いて有ることを自分なりに解釈してみました。

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

上記を解釈すると、まず、フロートや絶対配置などはブロックボックスではないし、さらにoverflow: visible以外のブロックは新しいブロック書式コンテキストを確立する。

また、ブロック書式コンテキストの中に入っているブロックレベル要素同士はmarginの縦方向の相殺をすると書いてあります。

overflow: visibleやfloatなどが指定されている要素はブロックレベル要素ではなく(厳密には違うけど語るには知識が足りませんすいません。。。)、ブロック書式コンテキストでhtml的に新しい文脈を作成するものなので相殺が起きないみたいな感じですかね?

なんか上手く説明できなくてスイマセン。。。
もし興味があるなら仕様書を読んでみるといいと思います!

投稿2017/09/04 13:03

MasakazuFukami

総合スコア1869

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

olaf

2017/09/05 00:47

ご回答ありがとうございます!仕様書読んでみますね。
guest

0

ベストアンサー

はい、overflowvisible以外の値の場合、その要素自体が1つの「ブロック整形コンテキスト」となる(その中と外は、レイアウト上いわば別世界になる)ため、子要素との相殺は起きません。

新しいブロック整形コンテキスト(たとえば、'visible'以外の'overflow'の浮動体や要素など)を設置する要素のマージンは、そのフロー内の子とともに相殺しない。

マージンの相殺
ブロック整形コンテキスト

※制式採用されなかったCSS 2.2のものですが、この部分は2.1や3とそう変わりません。

投稿2017/09/04 13:00

編集2017/09/04 13:06
maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

olaf

2017/09/05 00:46

ご回答ありがとうございます! 新しいブロック整形コンテキストになるんですね。浮動体と同じ原理になるということで理解しました。
guest

0

※追記しました。見ていただけると幸いです。

同じく初心者ですが、簡単にテスト用のHTMLを書いてみました。

lang

1<!doctype html> 2<html> 3<head> 4<meta charset="utf-8"> 5<title>overflow</title> 6<style type="text/css"> 7#parent { 8 background-color: lightskyblue; 9 margin:50px 50px; 10 overflow: visible; 11 height : 250px; 12 width : 250px; 13 14 border: 5px solid red; 15} 16#child { 17 background-color: turquoise; 18 margin:100px 100px; 19 height : 500px; 20 width : 500px; 21 22 border: 5px solid red; 23} 24</style> 25<script> 26 27window.onload = function(){ 28 var button_elem = document.getElementById('button'); 29 30 button_elem.addEventListener("click",function(){ 31 var parentStyle = document.getElementById('parent').style; 32 if(parentStyle.overflow == 'hidden'){ 33 parentStyle.overflow = 'visible'; 34 button_elem.innerHTML = '現在 : visible'; 35 }else{ 36 parentStyle.overflow = 'hidden'; 37 button_elem.innerHTML = '現在 : hidden'; 38 } 39 },false); 40} 41</script> 42</head> 43<body> 44<div id="parent"> 45 <div id="child"> 46 demo 47 </div> 48 </div> 49</div> 50<br /> 51<button id="button">現在 : visible</button> 52</body> 53</html>

ボタンをクリックしてもらえばわかると思いますが、そもそもoverflowとmarginは関係ないように見えます。

参考になれば。

###追記

ごめんなさい私自信相殺についてわかってなかったみたいです。

maisumakun様やMasakazuFukami様の回答を読ませていただいてから調べました。

ただ私が間違ってしまったのは、(私の場合はですが)最初からoverflowが設定されていた時の挙動の方が自然に見えたからかもしれません。

その挙動というのは、overflowを設定すると、子要素のmarginがbodyに対してではなく、parentに対して行われるようになる、というものです。最初から全てこういう仕様(marginは常に直近の親要素に対して適用されるという仕様)の方がいいように私は感じましたが、
何か理由があるのだと思います。(多分その理由というのが他の回答者様のおっしゃる仕様関連のところにあるのでしょう。)

overflowがないと子要素のmarginはbodyに対するものになっていますね。
ある場合はparentに対するものになっていますから、構造的なもの、となるとこの挙動が解決案にはならないでしょうか?

また質問者様の質問を読んでいると、むしろ「相殺されるのはなぜですか?」みたいになるのかと思いました。

というのはもしoverflow:hidden;によってbodyに対してmarginがついたままで、parentのmarginがchildのmarginより大きく、さらに相殺されないならば、childの方はparentより上に行くことで、childの一部または全部がhiddenをvisibleにしないと見ることができない領域に行くであろうからです。

実際はparentからのmarginとなるので、子要素はあたかも相殺されたかのように下に行き、さらには自身のmarginによってさらに下に行きます。

その様子を見れるように改めてhtmlを書いてみました。言いたいことが伝われば幸いです。

lang

1<!doctype html> 2<html> 3<head> 4<meta charset="utf-8"> 5<title>sousai</title> 6<style> 7.parent { 8 background-color: red; 9 margin-top: 100px; 10} 11 12.child { 13 background-color: yellow; 14 margin-top: 250px; 15 margin-left: 10px; 16} 17</style> 18<script> 19var disp1; 20var parent; 21var parentStyle; 22var disp2; 23var button; 24 25window.onload = function(){ 26 disp1 = document.getElementById("disp1"); 27 parent = document.getElementsByClassName("parent")[0]; 28 disp2 = document.getElementById("disp2"); 29 button = document.getElementById("button"); 30 31 32 button.addEventListener("click",function(){ 33 parentStyle = parent.style; 34 if(parentStyle.overflow=="hidden"){ 35 parentStyle.overflow = ""; 36 disp1.innerHTML = "childのmargin-top: 250px;が適用"; 37 disp2.innerHTML = ""; 38 button.innerHTML = "現在 : none"; 39 }else{ 40 parentStyle.overflow = "hidden"; 41 disp1.innerHTML = "parentのmargin-top: 100px;が適用"; 42 disp2.innerHTML = "childのmargin-top: 250px;が適用"; 43 button.innerHTML = "現在 : hidden"; 44 } 45 },false); 46} 47</script> 48</head> 49<body> 50<span id="disp1">childのmargin-top: 250px;が適用</span> 51<div class="parent"> 52<span id="disp2"></span> 53<div class="child"> 54child 55</div> 56parent 57</div> 58<button id="button">現在 : none</button> 59</body> 60</html>

(長文、乱文、また初心者な回答、失礼しました。m(_ _)m)

投稿2017/09/04 13:37

編集2017/09/04 22:04
namnium1125

総合スコア2045

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

olaf

2017/09/05 00:43

ご回答ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問