このCSSマージントップスタイルが機能しないのはなぜですか?


321

別のdiv内のdivにマージン値を追加しようとします。トップ値以外はすべて正常に機能し、無視されているようです。しかし、なぜ?

私が期待したこと:
私がマージンを期待したもの:50px 50px 50px 50px;

私が得るもの:
マージンで得られるもの:50px 50px 50px 50px;

コード:

#outer {
    	width: 500px; 
    	height: 200px; 
    	background: #FFCCCC;
    	margin: 50px auto 0 auto;
    	display: block;
}
#inner {
    	background: #FFCC33;
    	margin: 50px 50px 50px 50px;
    	padding: 10px;
    	display: block;
}
<div id="outer">
  <div id="inner">
  	Hello world!
  </div>
</div>

W3Schoolは、マージンがこのように動作する理由を説明していません。


4
インナーを浮かせてみましたか?
オンドリ

6
ハム..それでfloat:left;動作します...しかし、なぜこれが必要なのですか?浮かせたくない。そして、なぜ左/右のマージンが機能するのですか?
jamietelin

44
CSSマージン折りたたみアルゴリズムの楽しい世界へようこそ!
GordonM

10
W3Schools対W3CDocs ...勝者はいると思います。:D
enderskill

15
それのjsFiddle、次の男を25秒救うためjsfiddle.net/kLeu9
CodyBugstein

回答:


453

実際には、#inner要素の上余白が要素の上端に折りたたま#outer#outer余白だけがそのまま残ります(画像には表示されていません)。マージンが等しいため、両方のボックスの上端は互いに揃っています。

W3C仕様の関連ポイントは次のとおりです。

8.3.1マージンの縮小

CSSでは、2つ以上のボックスの隣接するマージン(兄弟である場合とそうでない場合がある)を組み合わせて1つのマージンを形成できます。このように組み合わされたマージンは崩壊すると言われ、結果として生じる結合マージンは崩壊マージンと呼ばれます。

隣接する垂直マージンが崩れる[...]

次の場合に限り、2つのマージンが隣接します。

  • どちらも同じブロックフォーマットコンテキストに参加するインフローブロックレベルボックスに属しています
  • ラインボックスなし、クリアランスなし、パディングなし、境界線なし
  • どちらも垂直方向に隣接するボックスエッジに属します。つまり、次のペアのいずれかを形成します。
    • ボックスの上マージンと最初のインフローの子の上マージン

マージンが崩れないようにするには、次のいずれかを実行できます。

上記のオプションがマージンの崩壊を防ぐ理由は次のとおりです。

  • フロートボックスと他のボックスの間のマージンは折りたたまれません(フロートとフロー内の子の間もです)。
  • 新しいブロックのフォーマットコンテキストを確立する要素の余白(フロートや 'visible'以外の 'overflow'を持つ要素など)は、インフローの子では折りたたまれません。
  • インラインブロックボックスの余白は折りたたまれません(インフローの子の場合でも)。

左マージンと右マージンは、次の理由で期待どおりに動作します。

水平マージンは決して崩れません。



2
この答えはすごい!追加するだけの何か。あなたのw3cの引用はそれを言っていますが、私は今だけ気づきました。他の人のために明確にするために、#outerに境界を与えることもできます。
driechel 14

フローティングのリンクが壊れているようです。
EP

@episanty:コメントにリンクすると、こうなります。リンク解除されました。
BoltClock

私は知っています-あなたに知らせたかっただけです。あなたは♦を有効にしているので、コメントを復活させたり、それに応じて投稿を変更したりすることを考えました。ところで、良い答えをありがとう。
EP

92

display: inline-block;内側のdivで使用してみてください。

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
}
#inner {
    background:#FFCC33;
    margin:50px 50px 50px 50px;
    padding:10px;
    display:inline-block;
}

6
いい答えだ。この変更により問題が修正される理由が説明されている場合は、より良いでしょう。
JohnFx

1
わかりました、それは気紛れです!なぜそれが機能するのですか?期待どおりに機能しない理由の論理的な説明は何ですか。マージン左/右なしで動作しdisplay:inline-block;ます。またdisplay:inline-block;、divで100%の幅が失われるというのも、使用時に後退しています。
jamietelin

3
インラインブロックに切り替えると、ブラウザは配置されたdivと他のルールが適用された後、divのサイズを強制的に再評価します。
オンドリ

私の問題のためにそれを試して、階段効果を作りました。
Jonny

1
display:inline-block私のために働いた。どうもありがとうございます。
starkeen

24

@BoltClockが述べたことはかなりしっかりしています。ここで、この問題の解決策をいくつか追加したいと思います。このw3c_collapsingマージンを確認してください。緑の部分は、この問題をどのように解決できるかについて考えられている可能性があります。

解決策1

フロートボックスと他のボックスの間のマージンは折りたたまれません(フロートとフロー内の子の間もです)。

つまりfloat:left#outerまたは#inner demo1に追加できます。

また、マージンfloatが無効になることに注意してくださいauto

解決策2

新しいブロックのフォーマットコンテキストを確立する要素の余白(フロートや 'visible'以外の 'overflow'を持つ要素など)は、インフローの子では折りたたまれません。

以外にvisible、レットのput overflow: hidden#outer。そして、この方法はかなりシンプルでまともです。私はそれが好きです。

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    overflow: hidden;
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

解決策3

絶対的に配置されたボックスのマージンは折りたたまれません(インフローの子があったとしても)。

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: absolute; 
}
#inner{
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

または

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: relative; 
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
    position: absolute;
}

これら2つの方法は、通常のフローを中断します div

解決策4

インラインブロックボックスの余白は折りたたまれません(インフローの子の場合でも)。

@enderskillと同じ

ソリューション5

流入ブロックレベル要素の下部マージンは、兄弟にクリアランスがない限り、常に次の流入ブロックレベル兄弟の上部マージンと共に縮小します。

これは兄弟間の折りたたみマージンであるため、この質問とはあまり関係がありません。これは一般に、トップボックスにmargin-bottom: 30pxあり、兄弟ボックスにがあるかどうかを意味しますmargin-top: 10px。それらの間の総マージンがある30pxの代わりに40px

解決策6

要素に上部ボーダー、上部パディング、および子のクリアランスがない場合、インフローブロック要素の上マージンは、最初のインフローブロックレベルの子の上マージンで折りたたまれます。

これは非常に興味深いもので、上枠線を1つだけ追加できます。

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    border-top: 1px solid red;

}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;

}

また<div>、デフォルトではブロックレベルであるため、意図的に宣言する必要はありません。私の初心者の評判のため、2つ以上のリンクと画像を投稿できないのは申し訳ありません。少なくとも、次に似たような問題が発生したときに問題がどこから発生しているかがわかります。


14

あなたが持っているものがうまくいかない理由はわかりませんが、追加することができます

overflow: auto;

外側のdivに。


この問題に対するさまざまなソリューションの負荷。ありがとう!この回答と@BoltClockの回答を組み合わせると、このソリューションが機能する理由についての良い情報が得られます。
jamietelin

12

にパディングを追加する#outerと機能します。

デモ

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
    padding-top:1px;
}

11

正確な理由はわかりませんが、内部CSSを

display:inline-block;

うまくいくようです。


3

「なぜ」(折りたたみマージンのあるものである必要があります)には答えませんが、あなたがしようとしていることを行う最も簡単で最も論理的な方法は、外側のdivに追加padding-topすることです:

http://jsfiddle.net/hpU5d/1/

細かい注意- display:block;コード内にブロックしないように指示しているものがない限り、divをに設定する必要はありません。



2

私は設定推測位置のプロパティ#innerのにdiv要素を相対することにも効果を達成するのを助けることがあります。しかし、とにかく、IE9の質問に貼り付けられた元のコードと最新のGoogle Chromeを試したところ、変更を加えなくても望ましい効果が得られました。


2

padding-top:50px外側のdivに使用します。このようなもの:

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}

注:パディングするとdivのサイズが大きくなります。この場合、divのサイズが重要であれば、特定の高さでなければならないかどうかを意味します。高さを50px減らします。

#outer {
    width:500px; 
    height:150px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}

1

何よりも重要なことを試したことがありますか?

margin:50px 50px 50px 50px !important;

-1

簡単な解決策として、子要素を次のdivような要素にラップしてみてください-

<div id="outer">
   <div class="divadjust" style="padding-top: 1px">
      <div id="inner">
         Hello world!
      </div>
   </div>
</div>

中間とdivのinnerパディングのため、divのマージンが崩れません。したがって、論理的には、divの既存のマージンに加えて、追加のスペースがあります。1pxouterinner1pxinner

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.