Браузеры обрезают граничные значения целым числам

Всякий раз, когда для границы элемента используется нецелое значение пикселя, браузер просто обрезает значение, чтобы стать целым числом. Почему это так?

Я знаю, что граница фактически не займет часть пикселя, но эти типы значений иногда используются в сочетании с другими, чтобы сформировать полные пиксели. Например, левая и правая границы с шириной 1.6px должны приводить к увеличению общей ширины элемента на 3px. Это работает, потому что полное значение сохраняется в памяти и используется для расчетов.

Однако, похоже, это не так, когда рендеринг границы, даже если ширина, заполнение и маржа все ведут себя правильно.

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>

Ответы

Ответ 1

Простое объяснение заключается в том, что браузер использует целые числа для ширины границ внутри (или, по крайней мере, предоставляет их публично как таковые).

Примером этого является исходный код Chrome (Chromium), который в файле ComputedStyle.h определяет все граничные ширины как целые числа (строка 508):

source code snapshot

Мы мало что можем с этим поделать и почему: информация о ширине границ в очень мало информации о спецификациях W3C для фонов и границ CSS. Он содержит только line-width без единиц, типа или определения о том, как относиться к этому устройству, кроме абсолютного (неотрицательного):

Значение: < line-width >
[...]
Вычисленное значение: абсолютная длина; '0, если стиль рамки "нет" или "скрыт"

и

Длины, соответствующие "тонким", "средним" и "толстым", не соответствуют но значения постоянны во всем документе и тонкие ≤ средняя ≤ толщина. УА может, например, заставлять толщину зависеть от Средний размер шрифта: один выбор может быть 1, 3 и 5px, когда "средний размер шрифта - 17 пикселей или меньше. Отрицательные значения не допускаются.

Эта же информация найдена в документе модели коробки без новых деталей.

Поскольку все значения в конечном итоге оказываются как значения пикселей (поскольку наши экраны являются пиксельными устройствами), число, проходящее через em, vw,% и т.д., похоже, заканчивается как целое число, когда дело доходит до ширины границы без учета субпикселей.

Не кажется, что даже преобразования (масштаб) влияют на это в браузерах, которые используют целые числа для ширины границ.

В конце концов, разработчикам браузеров, как обращаться с этими значениями , может быть просто эстетические причины для этого, производительность, мы можем только догадываться..).

Ответ 2

Насколько я могу судить по нескольким простым тестам, ширина подпиксельной границы работает точно так, как должна. Я думаю, что опечатка в вашем примере ( "border-top-width" vs. "border-left-width" ) может быть причиной расхождения. Этот пример работает так, как ожидалось для меня:

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>