Магические числа в CSS
Несмотря на довольно весёлое название, магические числа — это плохо. Термин берёт свое начало в программировании и означает «безымянную числовую константу». Другими словами, это помещенное в код число, которое сильно влияет на то, будет ли код работать корректно, но его конкретное предназначение непонятно тем, кто не слишком тщательно разобрался в коде. В CSS очень часто встречаются безымянные числовые константы, но они обычно окружены контекстом в виде селекторов и свойств, потому не являются слишком загадочными. И все же, в CSS присутствуют магические числа, и ничего хорошего в этом нет.
В CSS магическими можно назвать числа, которые «работают» в определённых обстоятельствах, но очень хрупки и склонны к сбоям, когда эти обстоятельства изменяются. В большинстве случаев они имеют какое-то отношение к шрифтам. Их обычно используют люди, которые ограничиваются тестированием в одном браузере с идеальными настройками. Давайте рассмотрим несколько примеров, чтобы разобраться, что такое магические числа, и избегать их в будущем.
Взгляните на этот простой набор вкладок:
Для каждой из вкладок установлена ширина width: 100px;
. В этом примере 100px
и есть то самое «магическое число». При его использовании многое может пойти
не так, как нужно. В этом можно убедиться, добавив вкладку с текстом подлиннее:
Выглядит немного странно и вряд ли так, как хотелось бы. Переноса строки можно
избежать, применив white-space: nowrap;
, но так, наверное, еще хуже:
Вероятность некрасивого отображения вкладок можно уменьшить, используя
min-width
:
Или же можно вообще не указывать ширину:
Если же вы во что бы то ни стало хотите, чтобы все вкладки были одной ширины,
можете попробовать использовать overflow: hidden;
и text-overflow: ellipsis;
:
В таком случае, наверное, стоит добавить атрибут title
, чтобы можно было
каким-то образом отобразить полное название вкладки. Вам может прийти в голову,
что это можно решить путем ограничения длины названий вкладок в системе
управления контентом. Но как насчет пользователей, которые самостоятельно
увеличивают размер шрифта для своего удобства? Такое решение с ограничением
длины названия вкладок может причинить им неудобства.
В недавней публикации «Заголовки с линиями по бокам» я использовал для
свойства line-height
значение, которое можно считать магическим числом. Скажем,
вы использовали этот прием в сочетании с причудливым шрифтом, подключенным через
@font-face
. Теперь представьте, что подключенный шрифт не загрузился, или же
пользователь поменял его на какой-то другой, или страницу просматривают в
браузере, который не поддерживает @font-face
. Загружается запасной шрифт,
размеры которого могут кардинально отличаться от размеров вашего подключенного
шрифта. Линии вокруг текста с запасным шрифтом размещаются странным образом и не
центрируются, как было задумано. Магическое число не работает.
Этот конкретный пример немного надуман, но, могу поспорить, вы встречали подключенные шрифты с немыслимой высотой строчного знака или другими особенностями, коренным образом отличающими их от стандартных решений.
Скажем, у вас есть группа блоков с различным количеством содержимого. Вам нужно
расположить их в виде сетки, и вы используете для этого float:left;
.
Получается довольно безобразно:
Постойте, ведь если задать для них одинаковую высоту, проблема будет решена!
Это если пользователь будет просматривать сайт с точно такими же настройками размеров шрифта, что и у вас. Но пользователи могут их менять.
В этом месте мне хочется заплакать:
Используя min-height
, можно избежать странностей с перекрытием, но тогда
размеры блоков будут разными, и снова возникает проблема с float
. Я не буду
слишком углубляться в решение этой проблемы, потому что она и без того стала
слишком абстрактной, но наверняка можно использовать прокрутку внутри блоков,
подкорректировать размеры блоков с помощью JavaScript или же использовать
какой-то другой макет.
Гарри Робертс (Harry Roberts) привел классический пример магического числа в своей статье «Код CSS „с душком“».
.site-nav > li:hover .dropdown{
position: absolute;
top: 37px;
left: 0;
}
Это CSS выпадающего меню. Меню спрятано за пределами экрана до тех
пор, пока пользователь не наведет курсор на элемент в родительском списке, тогда
выпадающее меню появляется в зоне видимости. Оно должно располагаться под
родительским элементом. В браузере автора этого кода высота родительского
элемента составляла 37px
. Уверен, вы уже успели предположить что это не во всех
случаях будет так. 37px
является магическим числом. Гарри советует заменить его
на top: 100%
, сбои при котором намного менее вероятны.
В статье «Боремся с пробелами между элементами со свойством Inline-Block»,
автор утверждает, что задав значение -4px
для границ, можно избавиться от лишнего
пространства между блоками. Это без сомнения магическое число. По стечению
обстоятельств, 4px
— это всего лишь ширина пробела для довольно большого
количества гарнитур при кегле 16px
, который обычно указан по умолчанию.
Измените font-family
на что-то вроде Monaco. Сбой. Увеличьте или уменьшите
кегль. Сбой.
В этой статье указаны и другие возможные решения.
Путаница в определении
Так как я пытаюсь аргументировать отказ от использования магических чисел, нужно четко определить, что же они из себя представляют, когда речь идет о CSS. Я стал свидетелем множества обсуждений, в которых мнения на этот счёт расходятся. (1) (2) (3).
Вот несколько примеров:
CSS
-webkit-transform: translateZ(0);
Магическое число? Нет. Просто маленький хак, который мы когда-то использовали чтобы улучшить производительность.
CSS
.parent {
padding: 22px;
}
.child {
bottom: 22px;
left: 22px;
}
Магическое число? Нет. Это число странное, но не магическое. Дочерний элемент
позиционируется по нижнему левому краю родительского элемента без отступов.
Поскольку числа одинаковы, происходящее вполне логично. Если бы все они были
разными, это бы значило что здесь не обошлось без хитромудрой привязки к
font-size
, и тогда речь бы шла о магических числах.
CSS
top: 37px;
Допустим, что это магическое число, так же, как и в примере с выпадающим меню выше. Можно ли с этим разобраться с помощью Sass?
SCSS
$topDistance: 37px;
.dropdown {
top: $topDistance;
}
Это больше не «безымянная» числовая константа, так как мы дали ей название, верно? Тем не менее, это все еще магическое число в CSS. Оно осталось столь же хрупким, как и было.
CSS
letter-spacing: -.05em;
Магическое число? Нет. Оно наверное было бы таким если бы использовались пиксели, так как значение в пикселях остается неизменным, и эффект от его использования зависит от текущего значения font-size. При большом font-size изменения практически незаметны, при маленьком font-size, изменения существенны. Использование относительных единиц уменьшает вероятность сбоев.
В качестве заключения
Знали бы вы, как я не люблю эту часть публикаций, однако полезно выделить своего рода свалку для мелочей, которым не нашлось места где-нибудь еще.
-
Согласно CSS-стандартам, предложенным командой WordPress, магические числа использовать не стоит. Что говорят другие?
-
Используя символьные шрифты, не забывайте, что для них, как и для обычных шрифтов, можно менять размер. Вы не можете «забронировать» для них пространство в пикселях, так как размер шрифта может измениться, а пиксельное значение нет.
-
Я хотел бы обновлять эту публикацию хорошими примерами сбоев при использовании магических чисел, так что, если вы можете предложить такой пример, оставьте комментарий.
-
Если вы пытаетесь отцентрировать изображение и текст, vertical-align работает довольно неплохо. Однако я часто замечаю смещение на 1px и прописываю
postion: relative; top: 1px;
в таких случаях. Это магическое число? Не уверен.