2015-06-14 11 views
16

Immer wenn ein nicht ganzzahliger Pixelwert für den Rand eines Elements verwendet wird, schneidet der Browser den Wert einfach ab, um eine Ganzzahl zu werden. Warum ist das der Fall?Browser kürzen Randwerte auf Ganzzahlen

Ich bin mir bewusst, dass die Grenze nicht tatsächlich Teil eines Pixels aufnehmen wird, aber diese Arten von Werten werden manchmal in Kombination mit anderen verwendet, um volle Pixel zu bilden. Zum Beispiel sollte der linke und der rechte Rand mit einer Breite von 1,6 px die Gesamtbreite des Elements um 3 px erhöhen. Dies funktioniert, weil the full value is stored in memory and used for calculations.

Dies scheint jedoch nicht der Fall zu sein, wenn der Rahmen gerendert wird, obwohl sich Breite, Auffüllung und Rand alle korrekt verhalten.

var div = document.getElementsByTagName('div'), 
 
    len = div.length, 
 
    style; 
 
for (var i = 0; i < len; i++) { 
 
    style = getComputedStyle(div[i]); 
 
    div[i].innerHTML = div[i].className + ': ' + style.getPropertyValue(div[i].className) + '<br>height: ' + style.getPropertyValue('height'); 
 
}
div { 
 
    width: 300px; 
 
    border: 1px solid black; 
 
    padding: 50px 0; 
 
    text-align: center; 
 
    -webkit-box-sizing: border-box; 
 
    -moz-box-sizing: border-box; 
 
    box-sizing: border-box; 
 
} 
 
div.width { 
 
    width: 300.6px; 
 
} 
 
div.padding-top { 
 
    padding-top: 50.6px; 
 
} 
 
div.margin-top { 
 
    margin-top: 0.6px; 
 
} 
 
div.border-top-width { 
 
    border-top-width: 1.6px; 
 
}
<div class="width"></div> 
 
<div class="padding-top"></div> 
 
<div class="margin-top"></div> 
 
<div class="border-top-width"></div>

Beim Test erzeugte Code die gleichen Ergebnisse (genaue Präzision ungeachtet) konsistent. Die meisten gängigen Browser (Chrome, Firefox, Opera) verhielten sich ähnlich. Die Ausnahmen waren Safari 5.1 (das Padding und Rand ähnlich wie Rand gerendert hat, aber dies liegt wahrscheinlich nur an der Version) und Internet Explorer (der die Grenze oben rechts richtig berechnet hat).

Breite, Auffüllung und Rand wurden alle als Dezimalwerte gespeichert und erlaubten, dass das Auffüllen die Höhe entsprechend beeinflusste, die Grenze jedoch nicht. Es wurde zu einer Ganzzahl abgeschnitten. Warum ist das konkret nur die Fallbreite? Wäre es möglich, den Grenzwert in einem vollständigeren Formular zu speichern, damit die Höhe des Elements mithilfe von JavaScript abgerufen werden kann?

+1

Warum nicht einfach eine Berechnung durchführen? – PHPglue

+0

@PHPglue Der Rahmenwert befindet sich in einer eingeschlossenen CSS-Datei, die gelegentlich überschrieben wird. Um eine Berechnung durchzuführen, müsste ich wissen, was der Grenzwert ist. Das Problem ist, dass es 1px zurückgibt, wenn es ungefähr 1.6px (in Bezug auf das Beispiel) zurückgeben sollte. – Anonymous

+0

Verwenden Sie keine Dezimalstellen für Pixel. – PHPglue

Antwort

9

Die einfache Erklärung ist, dass der Browser ganze Zahlen für Rahmenbreiten intern verwendet (oder zumindest macht sie öffentlich als solche).

Ein Beispiel hierfür ist der Quellcode von Chrome (Chrom), die in der Datei ComputedStyle.h alle Grenzbreiten als ganze Zahlen definiert (line 508):

source code snapshot

Es gibt wenig, das wir tun können, damit und wie zu warum: es gibt sehr wenig Informationen über Randbreiten in der W3C specification for CSS Backgrounds and Borders. Darin heißt es nur line-width ohne Einheiten ein, oder Definition darüber, wie diese Einheit zu behandeln, außer es ist absolut (nicht-negativ):

Wert: <Linienbreite>
[...]
Berechneter Wert: absolute Länge; ‚0‘, wenn die Grenze Stil ist ‚kein‘ oder ‚versteckt‘

Und:

Die Längen entsprechend ‚dünn‘, ‚mittel‘ und ‚dick‘ sind nicht angegeben, aber die Werte sind in einem Dokument konstant und dünn ≤ mittel ≤ dick. Ein UA könnte z. B. die Dicke von der mittleren Schriftgröße abhängig machen: Eine Option könnte 1, 3 & 5px sein, wenn die Schriftgröße "mittel" 17px oder weniger beträgt. Negative Werte sind nicht erlaubt.

Die gleichen Informationen werden in the box model document ohne neue Details gefunden.

Als alle Werte schließlich als Pixelwert am Ende die Zahl kommt durch em (wie unsere Bildschirme Pixel-Geräte), vw, % usw. scheint als eine ganze Zahl, um am Ende, wenn es kommt zu Randbreiten, ohne Subpixeling zu berücksichtigen.

Nicht einmal Transformationen (Skalierung) scheinen dies in den Browsern zu beeinflussen, die Ganzzahlen für Randbreiten verwenden.

Am Ende scheint es der Browser-Anbieter zu sein, wie man diese Werte behandelt (es könnte einfach ästhetische Gründe dafür sein, Leistung, .. können wir nur raten ..).

+0

Ich bezweifle, dass es Leistung ist, da es bereits beibehalten Float-Werte für andere Eigenschaften verwendet. Hinsichtlich der Ästhetik würde der Pixelwert nicht unbedingt eine Änderung in der Art und Weise bewirken, wie er * aussieht, wie er gerade erinnert wird. Ich kann keinen guten Grund für die Inkonsistenz zwischen Property Handling sehen, aber diese Antwort ist ansonsten ziemlich gut. Ich werde das Kopfgeld offen lassen, nur um zu sehen, ob noch andere Antworten kommen, aber das scheint die unglückliche Wahrheit zu sein. – Anonymous

+0

Es ist wahrscheinlich nicht Leistung, sondern mehr Entwicklergewohnheiten. Entwickler bevorzugen tendenziell den effizientesten Datentyp (mit guten Gründen). Und da die Entwickler keinen Grund sahen, nicht ganzzahlige Werte für Rahmen einzubeziehen, wählten sie Ganzzahlen. – light

+2

könnte es ein Artefakt von html3/4 'border = 3'-Attributen sein, die nur eine ganze Zahl benötigten. – dandavis

1

Soweit ich anhand ein paar einfacher Tests feststellen kann, funktionieren Subpixel-Rahmenbreiten genau so, wie sie sollten. Ich denke ein Tippfehler in deinem Beispiel ("border-top-width" vs. "border-left-width") könnte die Ursache für die Diskrepanz sein. Dieses Beispiel funktioniert wie für mich erwartet:

var div = document.getElementsByTagName("div"); 
 
for (var i = 0; i < div.length; i++) 
 
{ 
 
    div[i].innerHTML += getComputedStyle(div[i]).getPropertyValue("width"); 
 
}
DIV 
 
{ 
 
    width: 300px; 
 
    border: 1px solid black; 
 
    -webkit-box-sizing: border-box; 
 
    -moz-box-sizing: border-box; 
 
    box-sizing: border-box; 
 
} 
 
DIV.subpixel 
 
{ 
 
    border-width: 1.23px; 
 
}
<DIV>border-width: 1px<BR>width: </DIV> 
 
<DIV CLASS="subpixel">border-width: 1.23px<BR>width: </DIV>

+1

In Ihrem Beispiel zeigt die Breite für mich unverändert in Chrome: ' Breite: 300px' und 'Breite: 300px;'. – Anonymous

+0

Dann ist es Browser-abhängig, weil IE10 sagt "width: 298px" und "width: 297.54px". – m69

+0

Ja, ich denke schon. Internet Explorer scheint der einzige zu sein, der es richtig macht (was zugegebenermaßen ein bisschen eine Wendung ist). – Anonymous