Статьи

Повесть о CSS и Sass Precision

Различные браузеры как тотемы смотрят на загадочный знак процента

Работа от SitePoint / Наталья Бальская

В Edenspiekermann мы в значительной степени полагаемся на обзоры кода, чтобы убедиться, что работа, которую мы выполняем, достаточно хороша ™. Я регулярно сталкиваюсь с нечеткостью чисел, особенно тех, которые имеют десятичную точку. Следовательно, вот небольшая статья, чтобы пролить свет на этот вопрос.

Начальная настройка

Чтобы сделать все объяснение более понятным, прежде чем даже начать, мы собираемся поработать над небольшим фрагментом кода, который, как оказалось, очень актуален для нашего случая.

.list-item {
  float: left;
  width: 33%;
}

В чем проблема?

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

Хотя 33% + 33% + 33% равны 99%, а не 100%. Хотя это может не иметь никакого значения в большинстве случаев, при работе с прямыми выравниваниями 1% может иметь большое значение. 1% от 1400px14px Это довольно большое расстояние.

Почему бы нам просто не переместить десятичную точку (или, скорее, добавить ее), чтобы сделать ее более точной? Возможно, мы могли бы сократить разрыв до 1.4px0.14px Давайте начнем с этого тогда.

 .list-item {
  float: left;
  width: 33.33%;
}

Это работает лучше, но все еще не идеально. Эта проблема широко обсуждалась в этой совершенно замечательной статье Джона Альбина Уилкинса, озаглавленной «Грязный маленький секрет гибкого дизайна». Если вы не читали это, прочитайте это.

Браузер не может справиться с этим?

В этот момент вам может быть интересно, почему браузер не может просто заставить его работать ™. Дело в том, что спецификации CSS ничего не указывают (иронично) поставщикам браузеров о том, что делать в случае плавающей точности с процентными числами. А когда в спецификациях CSS нет подробностей, вы можете быть уверены, что каждый браузер сделает это по-своему.

Возьмите этот пример из вышеупомянутой статьи:

[…] С сеткой из 6 столбцов, каждый столбец имеет ширину 100% ÷ 6 = 16,666667% в ширину. В окне просмотра шириной 1000 пикселей (которое я удобно выбрал, чтобы упростить нашу математику), которое составляет 166,66667 пикселей на столбец. Поскольку в спецификации не содержится указаний, поставщики браузеров могут сами устанавливать свои правила. Если бы браузер округлился до ближайшего пикселя, в нашем примере мы получили бы 167 пикселей. Но поскольку 167 x 6 = 1002 пикселей, у нас больше не будет места для всех 6 столбцов в нашем окне просмотра. В качестве альтернативы, если браузер округляется до 166 пикселей на столбец, нам не хватит 4 пикселя для идеального размещения всех столбцов в нашем окне просмотра.
Джон Альбин Уилкинс

Именно так и происходит. Старые версии Internet Explorer (в основном 6 и 7) округляются до ближайшего целого числа, что приводит к поломке макета. Браузеры WebKit округляются, что предотвращает любой катастрофический результат компоновки, но оставляет нам дополнительное пространство. Opera (по крайней мере, в своем старом движке рендеринга) делала странные вещи, которые я даже не потрудился объяснить. Но опять же, в спецификации нет правил об этом поведении, так кто же виноват? Не браузеры, использующие субпиксельный рендеринг , это точно, потому что в конце концов это то, что дает лучшие результаты.

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

Как насчет Sass?

Sass поддерживает математические операции. Это не ново и фактически является одной из первых вещей, для которых Sass был использован (для построения математических сеточных систем). Что мы можем сделать, так это сказать Sass, что мы хотим разделить ширину нашего контейнера на 3 равные части.

 .list-item {
  float: left;
  width: (100% / 3);
}

Мы могли бы также использовать функцию percentage(..) для того же результата:

 .list-item {
  float: left;
  width: percentage(1 / 3);
}

Sass, как в Ruby, так и в LibSass, имеет точность точности 5. Это на самом деле проблема, потому что она довольно низкая; 10 будет лучше, но это не по умолчанию (хотя настраивается, но не простым способом).

Этот код даст следующий CSS:

 .list-item {
  float: left;
  width: 33.33333%;
}

Это не решает проблему нашего браузера, но облегчает разработку таблиц стилей. Мы не только не должны сами обрабатывать вычисления и точность, но мы также делаем код более удобным для чтения и обновления, фактически отображая вычисления.

Я бы сказал, что это хорошо.

Лучшее из обоих миров

До сих пор мы узнали, что хорошо, если Sass будет выполнять вычисления для нас, а не жестко кодировать значение. Теперь лучшим подходом было бы позволить браузеру справиться с этим наилучшим образом. Для этого есть CSS-функция calc(..)

 .list-item {
  float: left;
  width: calc(100% / 3);
}

Этот фрагмент кода не компилируется ни во что. Поражает браузер как созданный. Тогда это до браузера, чтобы сделать лучшее из этого. Я буду полностью честен с вами и скажу, что не уверен, что браузеры обрабатывают значения calc(..) Я полагаю, они выполняют вычисления, а затем округляют их. Некоторые браузеры, кажется, вносят субпиксельный рендеринг в уравнение. Если у вас есть понимание этого, пожалуйста, поделитесь в комментариях.

Для браузеров, которые не поддерживают выражение calc(..) , в основном Internet Explorer 8 и Opera Mini, мы можем поместить статическое значение, выраженное как операция Sass, прямо перед ним. Таким образом, мы получаем лучшее из обоих миров.

 .list-item {
  float: left;
  width: (100% / 3);
  width: calc(100% / 3);
}

Вывод

Давайте немного подведем итоги. Начнем с того, что процентные макеты трудно обрабатывать из-за несоответствий браузера и отсутствия спецификации в отношении точности с плавающей точкой.

Кроме того, жесткое кодирование значений, полученных в результате довольно сложного вычисления, обычно не очень хорошая идея. Мы можем позволить Sass вычислить приближение (до 5 цифр после плавающей запятой).

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

Это довольно много, где это сейчас. Ничего нового, но я думал, что быстрое резюме поможет!