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

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

ただいまの
回答率

90.61%

  • CSS

    5576questions

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

  • HTML5

    3875questions

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

overflow:hiddenとmarginの関係性

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 478

olaf

score 7

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

<div class="parent">
  <div class="child">demo</div>
</div>

<style type="text/css">
  .parent {
    margin:30px 0;
    overflow:hidden;
  }
  .child {
    margin:10px 0;
  }
</style>


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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

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

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/05 09:46

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

    キャンセル

+3

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/05 09:47

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

    キャンセル

0

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

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

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>overflow</title>
<style type="text/css">
#parent {
  background-color: lightskyblue;
  margin:50px 50px;
  overflow: visible;
  height : 250px;
  width : 250px;

  border: 5px solid red;
}
#child {
  background-color: turquoise;
  margin:100px 100px;
  height : 500px;
  width : 500px;

  border: 5px solid red;
}
</style>
<script>

window.onload = function(){
    var button_elem = document.getElementById('button');

    button_elem.addEventListener("click",function(){
      var parentStyle = document.getElementById('parent').style;
      if(parentStyle.overflow == 'hidden'){
         parentStyle.overflow = 'visible';
         button_elem.innerHTML = '現在 : visible';
      }else{
        parentStyle.overflow = 'hidden';
        button_elem.innerHTML = '現在 : hidden';
      }
    },false);
}
</script>
</head>
<body>
<div id="parent">
  <div id="child">
    demo
    </div>
  </div>
</div>
<br />
<button id="button">現在 : visible</button>
</body>
</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を書いてみました。言いたいことが伝われば幸いです。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>sousai</title>
<style>
.parent {
    background-color: red;
    margin-top: 100px;
}

.child {
    background-color: yellow;
    margin-top: 250px;
    margin-left: 10px;
}
</style>
<script>
var disp1;
var parent;
var parentStyle;
var disp2;
var button;

window.onload = function(){
    disp1 = document.getElementById("disp1");
    parent = document.getElementsByClassName("parent")[0];
    disp2 = document.getElementById("disp2");
    button = document.getElementById("button");


    button.addEventListener("click",function(){
        parentStyle = parent.style;
        if(parentStyle.overflow=="hidden"){
            parentStyle.overflow = "";
            disp1.innerHTML = "childのmargin-top: 250px;が適用";
            disp2.innerHTML = "";
            button.innerHTML = "現在 : none";
        }else{
            parentStyle.overflow = "hidden";
            disp1.innerHTML = "parentのmargin-top: 100px;が適用";
            disp2.innerHTML = "childのmargin-top: 250px;が適用";
            button.innerHTML = "現在 : hidden";
        }
    },false);
}
</script>
</head>
<body>
<span id="disp1">childのmargin-top: 250px;が適用</span>
<div class="parent">
<span id="disp2"></span>
<div class="child">
child
</div>
parent
</div>
<button id="button">現在 : none</button>
</body>
</html>

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/05 09:43

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

    キャンセル

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

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • CSS

    5576questions

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

  • HTML5

    3875questions

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