CSSのマージン/パディング率が常に幅に対して計算されるのはなぜですか?


130

あなたが見ればCSSボックスモデルの仕様は、次のことを守っます:

[マージン]パーセンテージは、生成されたボックスの包含ブロックのを基準に計算されます。これは「margin-top」と「margin-bottom」にも当てはまることに注意してください。包含ブロックの幅がこの要素に依存する場合、結果のレイアウトはCSS 2.1で定義されていません。 (強調鉱山)

これは確かに本当です。しかし、なぜですか?このように設計することを誰に強制するのでしょうか?必要なシナリオを考えるのは簡単です。たとえば、特定のものが常にページの上部から25%下になるようにすることですが、垂直方向のパディングを水平方向のサイズに対して相対的にする必要がある理由を思い付くのは困難です。親。

これが私が言及している現象の例です:

<div style="border: 1px solid red; margin: 0; padding: 0; width: 200px; height: 800px;">
  This div is 200x800.
  <div style="border: 1px solid blue; margin: 10% 0 0 10%;">
    This div has top-margin of 10% and left-margin of 10% with respect to its parent.
  </div>
</div>

http://jsfiddle.net/8JDYD/


3
私の最初の考えは、それがmargin: 25%実際に何を意味するのかについて曖昧さを引き起こすだろうということです。コードがそれを示唆しているとしても、それは均一なマージンではありません。これを裏付ける証拠はありませんが、それは妥当なようです。
Ryan Kinal

4
私の考えのjsFiddle。高さは幅よりもはるかに変化しやすいため、コンテンツが変更されるたびにマージンを予測するのが困難な方法でシフトします。
RichardTowers 2012年

1
@ライアン:それは本当です、それは均一なマージンにheight: 10%; width: 10%はなりませんが、四角い要素も得られないと言った場合も同じです。
mqp

4
dev.w3.org/csswg/css3-box/#the-margin-properties によると、両方向Note that in a horizontal flow, percentages on ‘margin-top’ and ‘margin-bottom’ are relative to the width of the containing block, not the height (and in vertical flow, ‘margin-left’ and ‘margin-right’ are relative to the height, not the width).進む
Adam Sweeney

1
@ライアン勝者はいると思う。デモはここにあります-jsFiddle
RichardTowers

回答:


60

私のコメントを回答に転送します。論理的に意味があるからです。ただし、これは根拠のない推測であることに注意してください。仕様がこのように書かれている理由の実際の推論はまだ、技術的には不明です。

要素の高さは、子の高さによって定義されます。要素にpadding-top:10%(親の高さに対して)がある場合、それは親の高さに影響します。子の高さは親の高さに依存し、親の高さは子の高さに依存するため、不正確な高さになるか、無限ループになります。確かに、これはオフセットの親===親の場合にのみ影響しますが、それでも影響します。解決が難しい奇妙なケースです。

更新:最後の数文は完全に正確ではない場合があります。リーフ要素(子を持たない子)の高さは、その上のすべての要素の高さに影響を与えるため、さまざまな状況に影響します。


1
このルールには例外があることに注意してください。CSS2.1のセクション10.6は、さまざまなタイプのボックスの高さを計算するほとんどすべてのインスタンスをカバーしています。実際、親子の高さに依存関係があるケースでは、未定義の動作が発生する傾向があります。
BoltClock

1
@sanjaypoyzer最も単純なケースでは、ブラウザがブロックの幅を外側から(ルートからヒントに)計算し、コンテンツをそれらのブロックに流して高さを決定します(ヒントからルート)。
2013年

9
なぜW3Cは常にこれを行うのですか?どうやらW3Cの「セマンティック」は、論理的に考えることができない人々に対応しなければならないことと同等であり、意味がありません。それは、世界の人々がいかに混乱して馬鹿であるかについて不平を言って、さらに混乱と愚かさを広めるようなものです。あなたが提供した推論は意味がありません:同じ議論が幅にも当てはまりますが、それでもうまくいきます。必要なのは、高さを決定するコンテキストと方向を設定することだけです。親の高さがピクセルまたは不変に設定されていない限り、それほど問題はありません。
u353 2014年

3
その依存性は解決策を持っているとします代数式ではないあなたはこれを尊重していない方法でそれを解決するために選択しない限り、無限ループになります。親の身長はと言いh_pます。10%のパディングトップは、子の高さを作成しますh_c = h_ci + 0.1h_p。ここh_ciで、は子の内側の高さであり、親の高さに依存しません。1つの子の場合は、方程式h_p = h_ci + 0.1h_p=> から親の高さを見つけるだけh_p = h_ci / 0.9です。たとえパディングが異なっていても、子供がいくついても、いつでもこれを行うことができます。その1つの未知数(h_p)と1つの方程式。
jeteon 2015年

2
無限計算が理由だとは思いません。単純な理由は次のとおりです。使用widthすると、同じ問題が水平方向に発生します。
Joy、

30

「N%」マージン(パディング)があるために同じマージントップ/マージン/右マージン底/余白左のため、すべての4つは、同じベースに対してでなければなりません。上/下が左/右とは異なるベースを使用した場合、「n%」のマージン(およびパディング)は、4辺すべてで同じことを意味することにはなりません。

(また、に対して上下のマージンがあることに注意してくださいがあると、奇妙なCSSハックが有効になり、アスペクト比が変化しないボックスを指定できるようになります(ボックスが再スケーリングされた場合でも)。


...驚くほど簡単な答え。上記の予想にはすべてメリットがありますが、これはかなり良い点です。おそらく、複数のソリューションが正しいため、使用される可能性が最も高いソリューションを選択しただけの可能性があります。
dudewad 2015

1
構文に要素を追加して、言うことができるようにすると便利だと思いますpadding: n [type]。したがって、下位互換性のために2番目のパラメーターがデフォルトで「幅」に設定さpadding: 5% logicalれるのpadding: 5% widthとは対照的に、(OPが示唆するとおり)になります。
jeteon 2015年

5
「n%マージン(およびパディング)は、4辺すべてで同じことを意味しない」-しかし、なぜそれが問題になるのでしょうか。
Herbertusz

4

このJSFiddle(Chrome 46.0.2490.86)で遊んで、この投稿(中国語で書かれている)を参照した後、@ ChuckKollarsからの回答に投票します。


無限計算の予想に対する主な理由は、次のとおりです。使用widthすると、同じ無限計算問題に直面します。

これを見ていJSFiddleをparentディスプレイがありinline-block、それにマージン/パディングを定義する資格があります。childマージン値を持っています20%無限の計算に従うと予想にと:

  1. の幅はchildparent
  2. の幅はparentchild

しかしその結果、Chromeはどこかで計算を停止し、次のような結果になります。

ここに画像の説明を入力してください

JSFiddleで「結果」パネルを水平方向に展開しようとすると、幅が変化しないことがわかります。のコンテンツが2行に(たとえば、1行ではなく)child折り返されていることに注意してください。なぜですか?Chromeはどこかでハードコーディングしただけだと思います。コンテンツを編集してさらに大きくすると(JSFiddle)、水平方向に余分なスペースがある限り、Chromeはコンテンツを2行に保持します。child

だから我々は見ることができます:無限の計算を防ぐいくつかの方法があります


私は、この設計は同じ指標に基づいて4つのマージン/パディング値を維持するだけであるという推測に同意します。

この投稿(中国語で書かれています)も別の理由を提案しています。それは、読み取り/タイプセットの向きが原因です。幅を固定し、高さを(事実上)無限にして、上から下に向かって読みます。


これは、Webページが一般に無限の方向に垂直にスクロールするためです。そのため、幅はブラウザウィンドウの幅から計算できます。要素を画面より広くする唯一の方法は、要素の幅を大きくするように指定した場合です。一般的なブロック要素は幅100%で、垂直方向に自動的に拡張されます(不明)。これが、幅に同じ問題がない理由です。
Lucent Fox

3

私はOPがCSS仕様で上下マージンのパーセンテージを幅の%として定義している理由を尋ねていることを理解していることを理解しています(ただし、想定されているように高さではありません)。

最近のほとんどのブラウザーは、vwとvhをサポートしているため、ビューポートの幅と高さに対してマージンの数値を指定できます。

スクロールバーがない場合、100vw / 100vhは(それぞれ)100%幅/ 100%高さに相当します。スクロールバーがある場合、ビューポート番号はこれを考慮しません(%番号はそうです)。ありがたいことに、ほぼすべてのブラウザーが17pxのスクロールバーサイズを使用しています(こちらを参照))、css calc関数を使用してこれを考慮することができます。スクロールバーが表示されるかどうかわからない場合、このソリューションは機能しません。

例:水平スクロールバーがないと仮定すると、高さの50%の上マージンは、「margin-top:50vh;」として定義できます。水平スクロールバーの場合、これは「margin-top:calc(0.5 *(100vh-17px));」として定義できます。(calcのマイナスとプラスの演算子は、両側にスペースが必要です!)


1
これは多くの場合に役立つ回避策ですが、機能しない例がたくさんあります(たとえば、コンテンツを他のボックスがある間に利用可能なスペースを埋めるように拡大するフレックスボックスコンテナーのサイズに比例して適合させようとしている場合)可変コンテンツ)。
Jules
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.