Играем с Infinity в CSS
infinity. Когда я впервые узнал об этом, мозг озарило множество абсурдных возможностей. Давайте обсудим! Возможно, найдутся и практические варианты использования.Прежде чем мы приступим к работе, необходимо знать одно важное правило: infinity можно использовать только внутри оператора calc(). Итак, приступим.
Никогда больше не проиграете битву за z-index
Вам когда-нибудь требовалось, чтобы элемент отображался поверх всего остального, но постоянно растущая гонка вооружений z-index заставляла прибегать к всё более высоким значениям z-index?
Завершите битву. Используйте infinity, чтобы получить максимально возможный z-index и одержать победу навсегда.
В демо приведённом ниже, не существует возможного значения z-index для синей карты, при котором она окажется выше фиолетовой карты с z-index: calc(infinity). Попробуйте!
Самый большой из возможных элементов
Что произойдёт, если вы создадите <div> с width и height в infinity пикселей?
.big {
width: calc(infinity * 1px);
height: calc(infinity * 1px);
}Обратите внимание, что мы умножаем infinity на 1px, чтобы превратить её в длину пиксели.
Вот демонстрация, показывающая результат, с некоторыми дополнительными пометками, чтобы лучше понять, что происходит в браузере.
Значения в функции getComputedStyle() — то, к чему применяются свойства CSS. Значения в функции getBoundingRect() отражают реальный размер отображаемого <div> в области просмотра. Вот фрагмент кода.
// getComputedStyle()
const computed = window.getComputedStyle(bigEl);
const computedWidth = computed.getPropertyValue('width');
const computedHeight = computed.getPropertyValue('height');
// getBoundingRect()
const rect = bigEl.getBoundingClientRect();
const rectWidth = rect.width + 'px';
const rectHeight = rect.height + 'px';Во-первых, infinity в CSS на самом деле не бесконечна. Это просто очень большое число. Моё разочарование неизмеримо, в отличие от infinity в CSS.
На моей машине (Windows desktop с Chrome) общая площадь <div> в демонстрации составляет 33 554 428px в квадрате, что примерно равно 79 км2. Неплохо! Но и не бесконечно.
Разные бесконечности
Обратите внимание, что в последнем абзаце я сказал на моей машине
. Хотя infinity поддерживается во всех основных браузерах, значение, в которое оно преобразуется, может не совпадать в разных браузерах и операционных системах.
Некоторые примеры из демонстрации выше:
- Chrome на macOS выдаёт
16 777 214pxпо ширине и высоте, что вдвое меньше, чем в Windows. - Firefox сообщает о ширине
1,78957e+7pxпри использовании функцииgetComputedStyle()и8 947 849pxпри использовании функцииgetBoundingRect(). - Firefox даже не пытается использовать
height: calc(infinity * 1px)— просто игнорирует его. Но установка height:17895697px(наибольшая длина CSS, которую разрешает использовать Firefox) работает. Я не знаю, почему Firefox не разрешаетheightс таким значением, как это происходит сwidth.
Кроме того, infinity может принимать различные значения в зависимости от того, с каким CSS-свойством вы его используете. Помните пример с z-index? Значение infinity там было 2 147 483 647 — одинаковое для всех браузеров, которые я тестировал, но отличающееся от различных значений width и height, только что увиденных нами.
Все эти странные значения для infinity, конечно, выбраны не случайно — они обусловлены тем, как хранятся числа. Например, 2 147 483 647 — это 2<sup>31</sup>-1, наибольшее возможное значение для знакового 32-битного целого числа.
Анимация до бесконечности
Что произойдёт, если вы попробуете анимировать элемент до infinity, как в этом случае?
.interstellar {
animation: go 10s;
}
@keyframes go {
to { translate: calc(infinity * 1px); }
}Оказывается, элемент немедленно переходит в конец анимации и остаётся там на протяжении всего времени. Таким образом, в данном случае элемент остаётся справа настолько далеко, насколько может выдержать браузер, в течение всех 10 секунд.
В этом есть смысл. На пути к бесконечности нет приращений. Доля от бесконечности всё равно остаётся бесконечностью. Поэтому для каждого кадра анимации анимированное значение равно бесконечности.
Что произойдёт, если задать бесконечную animation-delay?
.interstellar {
animation-delay: calc(infinity * 1s);
}Вы, наверное, догадываетесь. Анимация никогда не начинается.
Практические случаи использования infinity
Захотите ли вы когда-нибудь использовать infinity в CSS? Возможно! Иногда нужно просто огромное значение (каким бы оно ни было), и infinity может его дать.
Например, вы можете придать форму пилюли, используя border-radius со значением длины (не в процентах). Использование значения, большего, чем нужно, не изменит форму и будет хорошей идеей на случай, если элемент изменит размер.
div {
border-radius: calc(infinity * 1px);
}Ещё одно возможное применение — это распространённый CSS сниппет, используемый, чтобы сделать контент "только для устройств чтения с экрана", расположив его далеко за пределами страницы.
.screen-reader-only {
position: absolute;
left: calc(infinity * -1px);
/* и остальное */
}Но действительно ли infinity лучше, чем большое произвольно значение, например 9999px? Функционально — нет. Конечный результат тот же. Но думаю, это помогает сделать код более самодокументированным, потому что infinity передаёт смысл. Она выражает, что всё дело в величине, а не в конкретном магическом числе.
Деление на ноль и отрицательные значения
Деление на ноль даст infinity. Другими словами, calc(1 / 0) и calc(infinity) — это одно и то же. Это также работает с единицами измерения. Так, можно сделать что-то вроде calc(1px / 0) и получить то же значение, что и calc(infinity * 1px).
Полезно знать, но я бы всё равно использовал infinity напрямую, чтобы сделать CSS более очевидным.
Существует также константа -infinity, дающая наименьшее возможное значение. Ничего удивительного, это то же самое, что умножить infinity на -1.
Конец
Итак, главное, что нужно знать о infinity в CSS, — то, что она, по сути, является сокращением для обозначения наибольшего возможного значения в конкретной ситуации. Это значение может и будет меняться в зависимости от браузера, операционной системы и свойств CSS.
Использовать infinity или нет — решать вам. Поддержка браузерами довольно хороша (на момент перевода статьи 91.87%), и infinity может быть хорошим индикатором намерений, делающим CSS более читабельным, но это, конечно, необязательно.