Warum werden Rand- / Auffüllprozentsätze in CSS immer gegen die Breite berechnet?

130

Wenn Sie sich die CSS-Box-Modellspezifikation ansehen , werden Sie Folgendes beachten:

Der Prozentsatz [Rand] wird in Bezug auf die Breite des Blocks der generierten Box berechnet . Beachten Sie, dass dies auch für "Rand oben" und "Rand unten" gilt. Wenn die Breite des enthaltenen Blocks von diesem Element abhängt, ist das resultierende Layout in CSS 2.1 nicht definiert. (Hervorhebung von mir)

Das ist in der Tat wahr. Aber warum ? Was um alles in der Welt würde jemanden dazu zwingen, es so zu gestalten? Es ist leicht, sich Szenarien vorzustellen, in denen eine bestimmte Sache immer 25% vom oberen Rand der Seite entfernt sein soll, aber es ist schwierig, einen Grund zu finden, warum die vertikale Polsterung relativ zur horizontalen Größe von sein soll das Elternteil.

Hier ist ein Beispiel für das Phänomen, auf das ich mich beziehe:

<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/

mqp
quelle
3
Mein erster Gedanke ist, dass dies zu Unklarheiten darüber führen würde, was margin: 25%tatsächlich bedeutet. Es wäre kein gleichmäßiger Spielraum, obwohl der Code dies nahelegt. Ich habe keine Beweise, um dies zu belegen, aber es scheint vernünftig.
Ryan Kinal
4
Geige meiner Gedanken . Die Höhe ist viel veränderlicher als die Breite, sodass sich die Ränder bei Änderungen des Inhalts auf schwer vorhersehbare Weise verschieben.
RichardTowers
1
@ Ryan: Das stimmt, es wäre kein gerader Rand, aber wenn Sie sagen, dass height: 10%; width: 10%Sie auch kein quadratisches Element erhalten.
mqp
4
Laut dev.w3.org/csswg/css3-box/#the-margin-properties heißt es 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).also, es geht in beide Richtungen
Adam Sweeney
1
@ Ryan Ich denke wir haben einen Gewinner. Suchen Sie hier nach einer Demo - jsFiddle
RichardTowers

Antworten:

60

Übertragen Sie meinen Kommentar auf eine Antwort, weil es logisch sinnvoll ist. Bitte beachten Sie jedoch, dass dies eine unbegründete Vermutung ist. Die eigentliche Begründung, warum die Spezifikation so geschrieben ist, ist technisch noch unbekannt.

Die Elementhöhe wird durch die Größe der untergeordneten Elemente definiert. Wenn ein Element eine Auffüllspitze hat: 10% (relativ zur übergeordneten Höhe), wirkt sich dies auf die Höhe des übergeordneten Elements aus. Da die Größe des Kindes von der Größe des Elternteils abhängt und die Größe des Elternteils von der Größe des Kindes abhängt, haben wir entweder eine ungenaue Größe oder eine Endlosschleife. Sicher, dies betrifft nur den Fall, in dem Offset Parent === Parent ist, aber immer noch. Es ist ein seltsamer Fall, der schwer zu lösen ist.

Update: Die letzten paar Sätze sind möglicherweise nicht ganz korrekt. Die Höhe des Blattelements (Kind ohne Kinder) wirkt sich auf die Höhe aller darüber liegenden Elemente aus, sodass dies viele verschiedene Situationen betrifft.

Ryan Kinal
quelle
1
Beachten Sie, dass es Ausnahmen von dieser Regel gibt - Abschnitt 10.6 von CSS2.1 behandelt fast alle Fälle der Höhenberechnung für verschiedene Arten von Boxen. In der Tat führen Fälle, in denen eine Größenabhängigkeit zwischen Eltern und Kind besteht, zu undefiniertem Verhalten.
BoltClock
1
@sanjaypoyzer Ich würde im einfachsten Fall vermuten, dass Browser Blockbreiten von außen nach innen (Wurzel zu Spitzen) berechnen und dann Inhalte in diese Blöcke fließen lassen, um ihre Höhe zu bestimmen (Spitzen zu Wurzel).
Sam
9
Warum macht W3C das ständig? Anscheinend ist "semantisch" für das W3C das Äquivalent dazu, sich um Menschen kümmern zu müssen, die nicht logisch denken können, was keinen Sinn ergibt. Es ist, als würde man sich darüber beschweren, wie verwirrend und dumm die Menschen auf der Welt sind, und dann mehr Verwirrung und Dummheit verbreiten. Die Argumentation, die Sie angegeben haben, macht keinen Sinn: Das gleiche Argument gilt für Breiten, aber das funktioniert einwandfrei. Alles, was benötigt wird, ist, einen Kontext und eine Richtung festzulegen, in denen die Höhen bestimmt werden. Wenn die Höhe des übergeordneten Elements nicht in Pixel oder etwas Unveränderlichem festgelegt ist, gibt es kein großes Problem.
U353
3
Diese Abhängigkeit ist eine algebraische Formel, die eine Lösung hat und nicht zu einer Endlosschleife führt, es sei denn, Sie lösen sie auf eine Weise, die dies nicht berücksichtigt. Angenommen, die Größe der Eltern ist h_p. Eine Polsterung von 10% ergibt die Größe des Kindes h_c = h_ci + 0.1h_p, wobei h_cies sich um die innere Größe des Kindes handelt und nicht von der Größe des Elternteils abhängt. Für ein Kind finden Sie einfach die Elternhöhe aus der Gleichung h_p = h_ci + 0.1h_p=> h_p = h_ci / 0.9. Sie können dies immer tun, egal wie viele Kinder Sie haben, auch bei unterschiedlicher Polsterung. Es ist nur eine unbekannte ( h_p) und eine Gleichung.
Jeteon
2
Ich denke nicht, dass die unendliche Berechnung der Grund ist. Ein einfacher Grund ist folgender: Die widthhorizontale Verwendung führt zu demselben Problem.
Joy
29

Damit "n%" Rand (und Polsterung) gleich sind für margin-top / margin-rechts / margin-unten / links-Marge, die alle vier haben an derselben Basis relativ zu sein. Wenn oben / unten eine andere Basis als links / rechts verwendet würde, würde der Rand (und die Polsterung) "n%" nicht auf allen vier Seiten dasselbe bedeuten.

(Beachten Sie auch, dass der obere / untere Rand im Verhältnis zur Breite einen seltsamen CSS-Hack ermöglicht, mit dem Sie eine Box mit einem unveränderlichen Seitenverhältnis angeben können ... selbst wenn die Box neu skaliert wird.)

Chuck Kollars
quelle
... eine überraschend einfache Antwort. Obwohl alle oben genannten Vermutungen ihre Berechtigung haben, ist dies ein ziemlich guter Punkt. Es scheint möglicherweise ein Fall zu sein, in dem mehrere Lösungen korrekt wären, sodass sie nur die am wahrscheinlichsten verwendete auswählen ... vielleicht?
Dudewad
1
Ich nehme an, es wäre schön, ein zusätzliches Element in der Syntax zu haben, damit Sie sagen können padding: n [type]. Sie hätten also padding: 5% logical(was das OP vorschlägt) im Gegensatz zu padding: 5% widthdem zweiten Parameter, der aus Gründen der Abwärtskompatibilität standardmäßig "width" ist.
Jeteon
5
"n% Marge (und Polsterung) würden nicht auf allen vier Seiten dasselbe bedeuten" - Aber warum wäre das ein Problem?
Herbertusz
4

Ich stimme für die Antwort von @ChuckKollars, nachdem ich mit dieser JSFiddle (auf Chrome 46.0.2490.86) gespielt und auf diesen Beitrag (auf Chinesisch geschrieben) verwiesen habe .


Ein Hauptgrund gegen die Vermutung der unendlichen Berechnung ist folgender: Verwenden von widthGesichtern dieselbe unendliche Berechnung Problem .

Schauen Sie sich diese JSFiddle an , die parentAnzeige ist inline-block, die berechtigt ist, Rand / Abstand darauf zu definieren. Der childhat Margin-Wert 20%. Wenn wir der unendlichen Berechnungsvermutung folgen :

  1. Die Breite der childhängt von derparent
  2. Die Breite der parenthängt von derchild

Infolgedessen stoppt Chrome die Berechnung jedoch irgendwo, was Folgendes zur Folge hat:

Geben Sie hier die Bildbeschreibung ein

Wenn Sie versuchen, das Bedienfeld "Ergebnis" auf der JSFiddle horizontal zu erweitern, werden Sie feststellen, dass sich die Breite nicht ändert. Bitte beachten Sie, dass der Inhalt childin zwei Zeilen (nicht beispielsweise eine Zeile) eingeschlossen ist. Warum? Ich denke, Chrome hat es einfach irgendwo hart codiert. Wenn Sie den childInhalt bearbeiten , um ihn zu verbessern ( JSFiddle ), werden Sie feststellen, dass Chrome den Inhalt zwei Zeilen lang behält, solange horizontal zusätzlicher Speicherplatz vorhanden ist.

Wir können also sehen: Es gibt eine Möglichkeit, die unendliche Berechnung zu verhindern .


Ich stimme der Vermutung zu, dass: bei diesem Entwurf nur die vier Rand- / Füllwerte auf der Grundlage des gleichen Maßes beibehalten werden sollen.

Dieser Beitrag (auf Chinesisch geschrieben) schlägt auch einen anderen Grund vor: Er liegt an der Ausrichtung des Lesens / Satzes. Wir lesen von oben nach unten, wobei die Breite fest und die Höhe unendlich (virtuell) ist.

Freude
quelle
Dies liegt daran, dass Webseiten vertikal in eine im Allgemeinen unendliche Richtung scrollen. So kann die Breite aus der Breite des Browserfensters berechnet werden. Elemente sind nur dann breiter als der Bildschirm, wenn Sie ihre Breite als größer angeben. Typische Blockelemente haben eine Breite von 100% und dehnen sich automatisch in vertikaler Richtung aus (unbekannt). Deshalb hat die Breite nicht das gleiche Problem.
Lucent Fox
3

Mir ist klar, dass das OP fragt, warum die CSS-Spezifikation Prozentsätze für den oberen / unteren Rand als% der Breite (und nicht, wie angenommen wird, der Höhe) definiert, aber ich dachte, es könnte auch nützlich sein, eine mögliche Lösung zu veröffentlichen.

Die meisten modernen Browser unterstützen jetzt vw und vh, mit denen Sie Randnummern für die Breite des Ansichtsfensters und die Höhe des Ansichtsfensters angeben können.

100vw / 100vh entsprechen 100% Breite / 100% Höhe, wenn keine Bildlaufleiste vorhanden ist. Wenn eine Bildlaufleiste vorhanden ist, berücksichtigen die Ansichtsfensternummern dies nicht (während die% -Nummern dies tun). Zum Glück verwenden fast alle Browser Bildlaufleistengrößen von 17 Pixel ( siehe hier ), sodass Sie die CSS-Berechnungsfunktion verwenden können, um dies zu berücksichtigen. Wenn Sie nicht wissen, ob eine Bildlaufleiste angezeigt wird oder nicht, funktioniert diese Lösung nicht.

Beispiel: Angenommen, keine horizontale Bildlaufleiste, ein oberer Rand von 50% der Höhe, könnte als "Rand oben: 50 vh;" definiert werden. Mit einer horizontalen Bildlaufleiste könnte dies definiert werden als "Rand oben: calc (0,5 * (100vh - 17px))"; (Denken Sie daran, dass die Minus- und Plusoperatoren in calc Leerzeichen auf beiden Seiten benötigen!).

VKK
quelle
1
In vielen Fällen ist dies eine nützliche Problemumgehung, aber es gibt viele Beispiele, bei denen dies nicht funktioniert (z. B. wenn Sie versuchen, den Inhalt proportional zur Größe eines Flexbox-Containers anzupassen, der wächst, um den verfügbaren Speicherplatz zu füllen, während eine andere Box vorhanden ist variabler Inhalt).
Jules