Werden die Dezimalstellen in einer CSS-Breite eingehalten?

225

Etwas, das ich mich schon eine Weile beim CSS-Design gefragt habe.

Werden Dezimalstellen in CSS-Breiten eingehalten? Oder sind sie gerundet?

.percentage {
  width: 49.5%;
}

oder

.pixel {
  width: 122.5px;
}
Alastair Pitts
quelle

Antworten:

186

Wenn es sich um eine prozentuale Breite handelt, wird sie respektiert . Wie Martin betonte, brechen die Dinge zusammen, wenn Sie zu Bruchpixeln kommen, aber wenn Ihre Prozentwerte einen ganzzahligen Pixelwert ergeben (z. B. 50,5% von 200 Pixel im Beispiel), erhalten Sie ein vernünftiges, erwartetes Verhalten.

Bearbeiten: Ich habe das Beispiel aktualisiert, um zu zeigen, was mit gebrochenen Pixeln passiert (in Chrome werden die Werte abgeschnitten, sodass 50, 50,5 und 50,6 alle dieselbe Breite aufweisen).

Skilldrick
quelle
7
Sie haben Recht damit, dass Prozentwerte nicht selbst gerundet werden, sondern Pixelbreiten mit Dezimalstellen und das Endergebnis der Prozentberechnung immer auf ganze Pixel gerundet werden :)
MartinodF
2
@ MartinodF Danke für die Klarstellung. Ja, die Pixel sind gerundet, aber es ist nicht definiert, ob sie tatsächlich auf den nächsten Boden oder die nächste Decke gerundet sind (was ich mit "Dinge brechen zusammen" gemeint habe).
Skilldrick
1
@Skilldrick Aus Neugier habe ich die Bruchpixel in Ihrer Demo in einigen Browsern ausprobiert: Sowohl IE9p7 als auch FF4b7 runden auf das nächste Pixel ab, während Opera 11b, Chrome 9.0.587.0 und Safari 5.0.3 den Wert abschneiden. @andras Nur zur Verdeutlichung: Ich sage nicht, dass die internen Werte gerundet sind, sondern nur die endgültigen Renderwerte. Wenn Sie zoomen oder einige Elemente Eigenschaften usw. erben, zählen diese Dezimalstellen.
MartinodF
10
Modernes Update: Meine Chrome-Version 24 rundet die Bruchpixel tatsächlich auf . Beim Betrachten der jsFiddle runden 50,5 und 50,6 beide auf 51 Pixel auf und sind 1 Pixel breiter als die 50 Pixel Div.
Michael Butler
5
Am wichtigsten ist möglicherweise, wie Elemente mit gebrochenen Pixelabmessungen nebeneinander gestapelt werden. Während sie sich selbst visuell aufrunden
Sandy Gifford
53

Selbst wenn die Zahl beim Malen der Seite gerundet wird, bleibt der vollständige Wert im Speicher erhalten und wird für die nachfolgende untergeordnete Berechnung verwendet. Wenn Ihre Box mit 100.4999px beispielsweise auf 100px malt, wird das Kind mit einer Breite von 50% als .5 * 100.4999 anstelle von .5 * 100 berechnet. Und so weiter zu tieferen Ebenen.

Ich habe tief verschachtelte Rasterlayout-Systeme erstellt, bei denen die Breite der Eltern ems und die Kinder die Prozentzahl sind. Die Einbeziehung von bis zu vier Dezimalstellen stromaufwärts hatte spürbare Auswirkungen.

Rand Fall, sicher, aber etwas zu beachten.

Natekoechley
quelle
2
Die akzeptierte Antwort ist vollständiger als diese, aber die Anekdote in dieser gibt mir ein besseres Gefühl dafür, wie sich die technischen Implikationen auswirken werden. Danke, dass du es gepostet hast.
Tom
23

Obwohl Bruchpixel auf einzelnen Elementen aufgerundet zu sein scheinen (wie @SkillDrick sehr gut demonstriert), ist es wichtig zu wissen, dass die Bruchpixel im tatsächlichen Box-Modell tatsächlich berücksichtigt werden .

Dies ist am besten zu erkennen, wenn Elemente nebeneinander (oder übereinander) gestapelt sind. Mit anderen Worten, wenn ich 400 0,5-Pixel-Divs nebeneinander platzieren würde, hätten sie die gleiche Breite wie ein einzelnes 200-Pixel-Div. Wenn sie alle tatsächlich auf 1 Pixel aufgerundet würden (wie das Betrachten einzelner Elemente implizieren würde), würden wir erwarten, dass das 200-Pixel-Div halb so lang ist.

Dies ist in diesem ausführbaren Code-Snippet zu sehen:

body {
  color:            white;
  font-family:      sans-serif;
  font-weight:      bold;
  background-color: #334;
}

.div_house div {
  height:           10px;
  background-color: orange;
  display:          inline-block;
}

div#small_divs div {
  width:            0.5px;
}

div#large_div div {
  width:            200px;
}
<div class="div_house" id="small_divs">
  <p>0.5px div x 400</p>
  <div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</div>
<br>
<div class="div_house" id="large_div">
  <p>200px div x 1</p>
  <div></div>
</div>

Sandy Gifford
quelle
11
In Bezug auf das Rendern: In Ihrem Beispiel konkurrieren zwei Divs um jedes Pixel. In diesen Fällen wählt Ihr Browser eine davon aus, um das gesamte Pixel zu rendern - um Unschärfe und andere seltsame Artefakte zu vermeiden. Wenn Sie die Hälfte der Pixel mit :nth-child(even)oder auf blau einstellen :nth-child(odd), stellen Sie fest, dass entweder das Ganze orange oder das Ganze blau ist - keine Mischung aus Blau und Orange (was einen vagen violetten Farbton hätte).
Daan Wilmer
16

Die Breite wird auf eine ganzzahlige Anzahl von Pixeln gerundet .

Ich weiß nicht, ob jeder Browser es auf die gleiche Weise rundet. Sie scheinen alle eine andere Strategie zu haben, wenn sie Subpixel-Prozentsätze runden. Wenn Sie an den Details der Subpixel-Rundung in verschiedenen Browsern interessiert sind, gibt es einen ausgezeichneten Artikel über ElastiCSS .

edit : Ich habe @ Skilldricks Demo in einigen Browsern aus Neugier getestet. Wenn Sie gebrochene Pixelwerte verwenden (keine Prozentsätze, sie funktionieren wie in dem von mir verlinkten Artikel vorgeschlagen), scheinen IE9p7 und FF4b7 auf das nächste Pixel zu runden, während Opera 11b, Chrome 9.0.587.0 und Safari 5.0.3 die Dezimalstellen abschneiden. Nicht, dass ich gehofft hätte, dass sie doch etwas gemeinsam hätten ...

MartinodF
quelle
7

Sie scheinen die Werte auf die nächste ganze Zahl aufzurunden; Aber ich sehe Inkonsistenzen in Chrom, Safari und Firefox.

Zum Beispiel, wenn 33,3% in 420,945px konvertiert werden

Chrome und Firexfox zeigen es als 421px. während Safari zeigt als 420px.

Dies scheint, als ob Chrom und Firefox der Boden- und Deckenlogik folgen, während Safari dies nicht tut. Diese Seite scheint das gleiche Problem zu diskutieren

http://ejohn.org/blog/sub-pixel-problems-in-css/

Agaase
quelle
6

Elemente müssen auf eine ganzzahlige Anzahl von Pixeln gemalt werden, und wie die anderen Antworten zeigen, werden Prozentsätze tatsächlich eingehalten.

Ein wichtiger Hinweis ist, dass Pixel in diesem Fall CSS-Pixel und keine Bildschirmpixel bedeuten. Daher wird ein 200-Pixel-Container mit einem untergeordneten Element von 50,7499% auf 101- Pixel- CSS- Pixel gerundet , die dann auf einem Retina-Bildschirm auf 202 Pixel gerendert werden, und nicht 400 * . 507499 ~ = 203px.

Die Bildschirmdichte wird bei dieser Berechnung ignoriert, und es gibt keine Möglichkeit, ein Element auf bestimmte Retina-Subpixelgrößen zu malen. Sie können die Hintergründe oder Rahmen von Elementen nicht mit weniger als 1 CSS-Pixel rendern lassen , obwohl die tatsächliche Größe des Elements weniger als 1 CSS-Pixel betragen kann, wie Sandy Gifford gezeigt hat.

[*] Sie können einige Techniken wie 0,5-versetzte Box-Schatten usw. verwenden, aber die tatsächlichen Eigenschaften des Box-Modells werden auf ein volles CSS-Pixel übertragen.

Olex Ponomarenko
quelle
Ausgezeichnete Beobachtung
August