web-dev-qa-db-ja.com

マージントップがクリアで機能しない:両方

<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both; margin-top: 200px;">Main Data</div>

なぜmargin:top上記のコードで「メインデータ」が機能しない場合

67
Vishal

2つのフロートdivをanotherに入れることができます。

<div style='overflow:hidden'>
  <div style="float: left;">Left</div>
  <div style="float: right;">Right</div>
</div>
<div style="clear: both; margin-top: 200px;">Main Data</div>

edit—この5歳の答えに少し付け加えると、混乱を招く動作の原因は、 マージンの崩壊 。 OPの元のHTMLを使用する良い方法は、次のようなCSSルールを追加することです。

div { border: 1px solid transparent; }

失礼!今(私の追加<div>)それは正常に動作します!まあ、境界線からの余分なピクセルを除いて。特に、Ithinkそれはclear: bothが機能し、OPのコードから予期しないレイアウトが発生するマージン折りたたみルール。

もう一度編集—完全な(そして、私は、完全に正確だと思う)ストーリーについては、 Mark Ameryの優れた答えを参照してください 。詳細には複雑さがあり、この回答ではさらに詳しく説明します。

68
Pointy

Pointyはdivでフロートをラップする方法を示していますが、代わりにフロートとメインデータセクションの間に空のdivを挿入することもできます。例えば:

<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both;"></div>
<div style="margin-top: 200px;">Main Data</div>

これは、HTMLの周囲にdivラッパーを追加することが望ましくない場合に役立つことがあります。

20
Randall Cook

この仕様の背後にあるロジックは、気が遠くなるようなもので、 clearance および collapsing margins のルールの複雑な相互作用を伴います。

おそらく、従来のCSS ボックスモデル に精通しているでしょう。この場合、コンテンツボックスパディングボックスボーダーボックス内に含まれるマージンボックス内に含まれる

Diagram of box model

clearnone以外に設定されている要素の場合、追加のコンポーネントがこのモデルに導入されます:clearance

'none'以外の値は潜在的にclearanceを導入します。クリアランスは、マージンの崩壊を抑制し、要素のマージン上部の上のスペースとして機能します。

言い換えれば、これらの場合のボックスモデルは実際には次のようになります。

Box model with 'clearance' added above the top of the margin box

しかし、クリアランスはいつ導入されますか?それらの質問の最初から始めましょう。仕様 says

「クリア」が設定されている要素のクリアランスの計算は、最初に要素の上部境界Edgeの仮想位置を決定することによって行われます。この位置は、要素の「clear」プロパティが「none」であった場合に実際の上部境界線Edgeがあった場所です。

要素の上部境界線Edgeのこの仮想位置が関連するフロートを超えていない場合、クリアランスが導入され、8.3.1のルールに従ってマージンが崩壊します。

この質問を質問者のコードに適用してみましょう。次のコードの3番目のdivの位置を説明しようとしていることを思い出してください(視覚化を支援するために背景が追加されています)。

<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: both; margin-top: 200px; background: blue;">Main Data</div>

仕様で求められているように、clearnoneではなく、3番目のdivのbothに設定されていると想像してみましょう。次に、上記のスニペットはどのようになりますか?

<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: none; margin-top: 200px; background: blue;">Main Data</div>

ここでは、3番目のdivはoverlapping2つの浮動divです。ちょっと待って;なぜそうなのですか?確かに、フロートされた要素がブロックレベルの要素と重複することは許容されます( フロート仕様に従って)そして、フロートボックスがフロートが存在しないかのように垂直に流れた後。 ")が、3番目のdivにはmargin-topの負荷があり、2つのフロートdivの後に来る。フローティングされた2つのdivはボディの上部に表示され、3番目のdivは200ピクセル下に表示されるべきではありませんか?

これが発生しない理由は、3番目のdivのマージンがdivの親(この場合はボディ-ただし、親divで3つのdivをすべてラップした場合も同じ動作)のマージンに折りたたまれるためです。 Collapsing margins spec (以下にいくつかの無関係な詳細を省略して引用)は、次のことを示しています。

隣接する垂直マージンが崩壊します...

次の場合にのみ、2つのマージンはadjoiningです。

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

この例の3番目のdivは確かにボディの最初の子ではありませんが、最初のin-flow子です。 https://www.w3.org/TR/CSS22/visuren.html#positioning-scheme に注意してください:

要素は、フロート、絶対配置、またはルート要素の場合、out of flowと呼ばれます。要素は、フロー外ではない場合、in-flowと呼ばれます。

この例の最初と2番目のdivはフロートされているため、3番目のdivのみがインフローです。したがって、その上余白は親の上余白に隣接し、余白は崩壊します-ボディ全体を押し下げる、2つの浮動要素を含む。したがって、3番目のdivは、大きなmargin-topを持っているにもかかわらず、その兄弟と重複しています。その結果、3番目の要素のclearnoneに設定されているこの仮説の場合、次の条件を満たす:

要素の上部の境界線が関連するフロートを超えていない

したがって:

クリアランスが導入され、8.3.1のルールに従ってマージンが崩壊します

クリアランスはいくらですか?仕様では、ブラウザに2つのオプションがあり、いくつかの明確な注意事項があります。

次に、クリアランスの量が次のうち大きい方に設定されます。

  • クリアされる最下部のフロートの外側の下部エッジでも、ブロックの境界エッジを配置するのに必要な量。
  • ブロックの上端の境界線を仮想的な位置に配置するのに必要な量。

または、クリアランスは、ブロックの境界エッジを配置するのに必要な量に正確に設定されます。これは、クリアされる最低のフロートの下部外側エッジでもです。

注:両方の動作は、既存のWebコンテンツとの互換性の評価が保留されています。将来のCSS仕様では、どちらか一方が必要になります。

注:クリアランスは、負またはゼロにすることができます。

これらのルールの適用を開始する前に、すぐに問題が発生します。 clearnoneである仮説の場合に考慮しなければならなかった折り畳みマージンを覚えていますか?さて、この非仮説的に存在するは存在しませんクリアランスのそれはそれを禁止します。 8.3.1からの折りたたみマージンルール を思い出してください。前に引用したように、マージンはadjoining次の場合:

  • 行ボックスなし、クリアランスなし、パディングなし、境界線なし

(強調を追加)。そのため、3番目のdivの上マージンとその親の上マージンは隣接しなくなります。サンプルスニペットでこの事前クリアランスシナリオをシミュレートするには、clear: noneを保持しますが、padding-top: 1pxを本文に追加します。これにより、上記のルールに従ってマージンの折りたたみも無効になります。

body {
  padding-top: 1px;
}
<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: none; margin-top: 200px; background: blue;">Main Data</div>

これで、マージンが折りたたまれたときとは異なり、3番目のdivはその2つの浮いた兄弟の下に快適になります。しかし、マージンdidが崩壊するという仮想シナリオに基づいて、クリアランスを追加する必要があることをすでに決定しています。残っているのは、amountのクリアランスを選択することです:

クリアされる最低のフロートの下部外側エッジでもブロックの境界エッジを配置します

そのため、3番目のdivにnegativeクリアランスを適用して、その上部border Edgeを上にドラッグする以外に選択肢はありません上の浮いた要素の下部外側のエッジマージンエッジとも呼ばれます)にタッチします。そのため、フローティング要素の高さがそれぞれ10pxで、3番目のdivに200pxの上部マージンがある場合、-190pxのクリアランスが適用されます。最後に、質問者から見た最終結果に到達します。

<div style="float: left; background: red;">Left</div>
<div style="float: right; background: green;">Right</div>
<div style="clear: both; margin-top: 200px; background: blue;">Main Data</div>

(ブラウザの開発ツールを使用して上記のスニペットの3番目のdivを調べると、divの上に200pxの上部マージンが表示され、残りのすべてのコンテンツよりもずっと上に表示されることに注意してください。マージンボックス全体が、大きな負のクリアランスによって上方に引き上げられています。)

シンプル!

13
Mark Amery

PointyとRandall Cookは優れた答えを持っています。もう1つの解決策を示すと思いました。

<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="float: left; clear: both; margin-top: 200px;">Main Data</div>

3番目の要素を「float:left;」にするとAND "clear:both;"、3番目の要素に200ピクセルのマージンを与えるという望ましい効果があるはずです。ここに link の例があります。

これは、他のフォローアップ要素がフロートである必要があるかどうかに関しても影響する可能性があります。ただし、望ましい効果がある場合もあります。

7
rvbyron

代替ソリューション:

margin-bottomを持つ要素を下にプッシュダウンするために、実際に浮動要素にclear: bothを配置できます。

http://jsfiddle.net/9EY4R/

enter image description here

注:この提案を行った後、一般的には良いアイデアではないのですぐに撤回する必要がありますが、一部の限られた状況では適切な場合があります。


<div class='order'>

    <div class='address'>
        <strong>Your order will be shipped to:</strong><br>
        Simon</br>
        123 Main St<br>
        Anytown, CA, US
    </div>

    <div class='order-details'>
        Item 1<br>
        Item 2<br>
        Item 3<br>
        Item 4<br>
        Item 5<br>
        Item 6<br>
        Item 7<br>
        Item 8<br>
        Item 9<br>
        Item 10<br>
    </div>

    <div class='options'>
        <button>Edit</button>
        <button>Save</button>
    </div>
</div>

アイテムのあるパネルは、このCSSでorder-detailsと呼ばれます

.order-details
{
    padding: .5em;
    background: lightsteelblue;

    float: left;
    margin-left: 1em;

    /* this margin does take effect */
    margin-bottom: 1em;
}

上記のフィドルでは-黄色のパネルにはmargin-topがありますが、最も高い浮動アイテムより大きくなければ、何もしません(もちろん、これがこの質問の要点です)。

黄色のパネルのmargin-topを20emに設定すると、マージンは外側の青いボックスの上部から計算されるため、表示されます。

4
Simon_Weaver

代わりにメインデータdivで「padding-top」を使用してください。または、メインデータdivを「padding-top」で1つにラップします。

2
freeworlder

フローティング要素の1つに下マージンを設定してみてください。または、フロートを親要素でラップし、cssハックを使用して 追加のマークアップなしでクリア にすることもできます。

0
Jack Cheng

相対位置とマージンの組み合わせにより、この種の問題を解決できる場合があります。

WordPressのalignrightクラスとalignleftクラスにこの手法を使用します。

たとえば、使用できる要素をクリアすることで尊重される「下マージン」が必要な場合。

.alignright{
   float: right;
   margin-left: 20px;
   margin-top: 20px;
   position: relative;
   top: -20px;
}

あなたの例では、次のようなことができます

<div style="float: left;">Left</div>
<div style="float: right;">Right</div>
<div style="clear: both; margin-bottom: 200px; position: relative; top: 200px;">Main Data</div>
0
christian