51

私は 2 つの div を作成しようとしています。内側の div は外側の div よりも大きく、外側の div には がoverflow:scrollあり、内側の div には がありmargin:25pxます。だから私はこれを行います:

#outer {
    width: 200px;
    height: 100px;
    overflow: scroll;
}
#inner {
    width: 400px;
    height: 200px;
    margin: 25px;
}

...

<div id="outer">
    <div id="inner">

    </div>
</div>

内側の div が予想どおり 25 ピクセルのマージンを持つ代わりに、3 つの側面に 25 ピクセルのマージンがありますが、右側にはありません。これは私の意見では非常に直感に反しています。

内側の div + 50px を含めるのに十分な幅の中央の div を追加すると、正しく見えるようにすることができますが、それはハッキーな回避策のようです。

JSFiddle での私の例を参照してください: http://jsfiddle.net/d3Nhu/16/

これは、すべての主要なブラウザーで同じように発生します。この動作に正当な理由はありますか? CSS 仕様によると、これは正しい動作ですか?

overflow:auto注: この例で予想されるように、代わりにを使用しても違いはありませんoverflow:scroll

編集:この動作の回避策を探しているわけではないことに注意してください。(私はすでにそれを見つけました。) この動作の理由についての洞察を探しています。特に、 CSS 仕様のどこかに文書化されている場合はなおさらです。

4

3 に答える 3

70

TL;DR:

マージンは、ラッパーを外側に拡張するのではなく、ラッパーから要素を移動するためのものです。

長い説明:

widthこの動作は、ドキュメント内の任意の場所で水平に加えてを指定することと一致してmarginいます。分解するには、次のスニペットを検討してください。ここでは、overflowプロパティのないラッパーを特定marginし、ラッパー要素を展開しません。

body {
    padding: 20px;
}
.outer {
    width: 400px;
    border: 1px solid black;
}
.inner {
    width: 400px;
    height: 40px;
    margin: 0 20px;
    background: grey;
}
<div class="outer">
    <div class="inner">
        
    </div>
</div>

ご覧のとおりmargin、ラッパーのサイズが拡大することはなく、要素がオーバーフローし続けています。この動作は、CSS 2.1 仕様に記載されている の視覚的な書式設定モデルの詳細に記載されています。

「ビジュアル フォーマット モデルの詳細」の「ブロック レベルの、通常のフローで置換されていない要素」セクションからの抜粋:

次の制約は、他のプロパティの使用される値の間で保持する必要があります。

'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = 包含ブロックの幅

[...]

上記のすべてに「auto」以外の計算値がある場合、その値は「過度に制約されている」と見なされ、使用される値の 1 つがその計算値と異なる必要があります。包含ブロックの「方向」プロパティの値が「ltr」の場合、指定された「margin-right」の値は無視され、等式が真になるように値が計算されます。「方向」の値が「rtl」の場合、これは代わりに「マージン左」に発生します。

その抜粋は非常に密集しているので、単純に、 と の幅を無視しborderて、 、、およびpadding0残します。widthmargin-leftmargin-right

との固定width値と 値があるためmargin-leftmargin-right値は「過度に制約されています」。この例では、方向がltrデフォルトであるため、margin-right強制的に補正されます。

dir="rtl"方向の効果を確認するために、ラッパー要素に属性を追加してみましょう。

body {
    padding: 20px;
}
.outer {
    width: 400px;
    border: 1px solid black;
}
.inner {
    width: 400px;
    height: 40px;
    margin: 0 20px;
    background: grey;
}
<div class="outer" dir="rtl">
    <div class="inner">
        
    </div>
</div>

現在、要素は左にオーバーフローしています。dir="rtl"この属性があなたのoverflow: scroll例に同じ効果があるかどうか見てみましょう。

#outer {
    border: 1px solid #00F;
    width: 200px;
    height: 100px;
    overflow: scroll;
}
#inner {
    border: 1px solid #F0F;
    margin: 25px;
    width: 400px;
    height: 200px;
}
<div id="outer" dir="rtl">
    <div id="inner">
    
    </div>
</div>

ええ、そうです。右側ではなく左側の余白がなくなりました。

しかし、なぜoverflow: scroll余白を含めないのでしょうか?

主な理由は、仕様がそうすべきだと言っていないからです。overflowプロパティの CSS 2 仕様を見てみましょう。

「視覚効果」の「オーバーフローとクリッピング」セクションからの抜粋:

オーバーフローが発生するたびに、'overflow' プロパティは、ボックスがパディング エッジまでクリップされるかどうかを指定し、そうである場合は、クリップ アウトされたコンテンツにアクセスするためのスクロール メカニズムが提供されるかどうかを指定します。

「クリップアウトされたコンテンツ」と具体的にどのように表示されているかを確認してください。「コンテンツ」の説明については、CSS 2 仕様の次の図を参照してください。

「ボックス モデル」の「ボックス寸法」セクションの図:

ボックスモデル

ご覧のとおり、 はmarginとは別のものcontentです。ただし、この時点で、パディングとボーダーがスクロール領域に含まれていることに注意する価値があるため、仕様に「コンテンツ」と記載されている場合は、ボーダーボックスを参照している可能性が高いか、少なくともそのように解釈されたようです.

なぜ機能display: inline-blockするのですか?

基本的に、余白inline-blockはブロック レベルではなくコンテンツ レベルであり、「過剰な制約」という概念がないため、要素に対するマージンの動作は異なります。

于 2015-02-23T20:16:43.067 に答える
21

divdisplay:inline-block;に追加 #inner

このフィドルを参照してください

于 2012-07-27T20:47:09.903 に答える