2015-06-14 17 views
16

Kiedy nieokreślona wartość pikseli jest używana do obramowania elementu, przeglądarka po prostu obcina wartość, aby stać się liczbą całkowitą. Dlaczego tak jest?Przeglądarki obcinają wartości graniczne do liczb całkowitych

Jestem świadomy, że ta granica nie będzie w rzeczywistości obejmować części piksela, ale te typy wartości są czasami używane w połączeniu z innymi, tworząc pełne piksele. Na przykład, lewa i prawa krawędź o szerokości 1,6 piksela powinna spowodować zwiększenie całkowitej szerokości elementu o 3 piksele. Działa to ponieważ the full value is stored in memory and used for calculations.

Jednak wydaje się, że nie jest tak w przypadku renderowania obramowania, mimo że szerokość, dopełnienie i margines zachowują się poprawnie.

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>

Podczas badania, kod produkowane takie same wyniki (pomijając precyzją) konsekwentnie. Większość głównych przeglądarek (Chrome, Firefox, Opera) zachowywało się tak samo. Wyjątkami były Safari 5.1 (które zapewniało dopełnienie i margines podobny do granicy, ale jest to prawdopodobnie tylko ze względu na wersję) i Internet Explorera (który poprawnie obliczył szerokość-szerokości-szerokości).

Szerokość, dopełnienie i margines zostały zapamiętane jako wartości dziesiętne, a dopełnienie odpowiednio wpłynęło na wysokość, ale granica nie była. Zostało skrócone do liczby całkowitej. Dlaczego jest to tylko granica szerokości sprawy? Czy istnieje sposób na zapamiętanie wartości obramowania w pełniejszej formie, aby można było uzyskać wysokość elementu za pomocą JavaScript?

+1

Dlaczego po prostu nie wykonać obliczeń? – PHPglue

+0

@PHPglue Wartość graniczna znajduje się w dołączonym pliku css, który jest czasami nadpisywany. Aby wykonać obliczenie, musiałbym wiedzieć, jaka jest wartość graniczna. Problem polega na tym, że zwraca 1px, kiedy powinien powrócić około 1,6px (w odniesieniu do przykładu). – Anonymous

+0

Nie należy używać liczb dziesiętnych dla pikseli. – PHPglue

Odpowiedz

9

Prostym wyjaśnieniem jest to, że przeglądarka używa liczb całkowitych o szerokości granicznych wewnętrznie (lub przynajmniej naraża je publicznie jako takie).

Przykładem tego jest kod źródłowy Chrome (chrom), które w ComputedStyle.h plików definiuje wszystkie granicznych szerokościach jako liczby całkowite (line 508):

source code snapshot

Niewiele możemy zrobić z tym i jako dlaczego: jest bardzo mało informacji o szerokościach granicznych w W3C specification for CSS Backgrounds and Borders. Stwierdza tylko line-width bez jednostek, typu lub definicji dotyczących sposobu leczenia tej jednostki oprócz tego, że jest bezwzględny (nieujemna):

Wartość: < linia szerokości >
[...]
Wartość obliczona: długość bezwzględna; „0”, jeśli styl obramowania jest „brak” lub „ukryte”

I:

Długości odpowiadające „cienka”, „średnich” i „grube” nie są określony, ale wartości są stałe w całym dokumencie i są cienkie ≤ średnie ≤ grube. UA może np. Sprawić, że grubość zależy od średniego rozmiaru czcionki: jeden wybór może wynosić 1, 3 & 5px, gdy średniowy rozmiar czcionki " " wynosi 17 pikseli lub mniej. Wartości ujemne są niedozwolone.

Ta sama informacja została znaleziona in the box model document bez nowych szczegółów.

Jak wszystkie wartości ostatecznie skończyć jako wartości pikseli (jak nasze ekrany są pixel-devices) liczbę pochodzących przez em, VW, % itd wydaje się skończyć jako liczba całkowita kiedy go dochodzi do szerokości obramowania bez uwzględnienia sub-pixelingu.

Wygląda na to, że nawet przekształcenia (skala) nie wpływają na to w przeglądarkach, które używają liczb całkowitych do szerokości obramowania.

Ostatecznie wydaje się, że od dostawcy przeglądarki zależy, jak potraktować te wartości: (może to być po prostu powód estetyczny, wydajność, .. możemy się tylko domyślać ...).

+0

Wątpię, żeby to była wydajność, ponieważ już używa zachowuje wartości zmiennoprzecinkowe dla innych właściwości. Jeśli chodzi o estetykę, wartość pikseli niekoniecznie spowoduje zmianę wyglądu *, czyli jak zostanie zapamiętana. Nie widzę żadnego dobrego powodu niezgodności między obsługą nieruchomości, ale ta odpowiedź jest całkiem dobra, jeśli nie. Zostawię otwartą nagrodę tylko po to, by zobaczyć, czy pojawią się inne odpowiedzi, ale to wygląda na niefortunną prawdę. – Anonymous

+0

To prawdopodobnie nie wydajność, ale więcej nawyków programistów. Deweloperzy preferują najbardziej wydajny typ danych (z uzasadnionych powodów). A ponieważ programiści nie widzieli powodu, aby uwzględnić wartości niecałkowite dla granic, wybierali liczby całkowite. – light

+2

może to być artefakt atrybutów 'border = 3' html3/4, który pobierał tylko liczbę całkowitą. – dandavis

1

O ile mogę powiedzieć, od kilku prostych testów, szerokości podpikselowych krawędzi działają dokładnie tak, jak powinny. Myślę, że literówka w tobie ("border-top-width" vs. "border-left-width") może być przyczyną rozbieżności. Przykład ten działa zgodnie z oczekiwaniami dla mnie:

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

W Twoim przykładzie szerokość w Chrome pozostała niezmieniona: ' szerokość: 300px' i 'szerokość: 300px;'. – Anonymous

+0

To zależy od przeglądarki, ponieważ IE10 mówi "width: 298px" i "width: 297.54px". – m69

+0

Tak, tak myślę. Internet Explorer wydaje się być jedynym, który robi to poprawnie (co jest wprawdzie trochę skręcające). – Anonymous

Powiązane problemy