Краткая запись CSS как антипаттерн
Оригинал статьи: CSS Shorthand Syntax Considered an Anti-Pattern
Существует небольшая, но на удивление важная (и, что более удивительно, распространенная) проблема, которую я часто замечал в коде других людей, как непосредственно работая с ним, так и в ходе рефакторинга или аудита кода — это использование краткой записи свойств CSS.
Обычно мы рассматриваем краткий синтаксис как преимущество: меньше нажатий на клавиатуру, меньше строчек кода и меньше данных, передаваемых по сети. Отлично же! Однако, здесь есть неприятный побочный эффект: таким образом мы зачастую сбрасываем значения свойств, которые изначально не собирались модифицировать.
Когда мы пишем что-то вроде этого:
.btn {
background: red;
}
Мы всего лишь хотим, чтобы у нашей кнопки был красный фоновый цвет. Но на самом деле мы задаем целый набор правил:
.btn {
background-image: initial;
background-position-x: initial;
background-position-y: initial;
background-size: initial;
background-repeat-x: initial;
background-repeat-y: initial;
background-attachment: initial;
background-origin: initial;
background-clip: initial;
background-color: red;
}
За счет простого использования краткой записи, мы безоговорочно решили, что не хотим использовать фоновое изображение, заодно указав для него стартовую позицию с левого верхнего края, повторение по осям x
и y
и прокрутку вместе с элементом и т.д.
Почти все проблемы, баги и регрессии в CSS происходят из-за того, что мы делаем слишком многое слишком рано, а через некоторое время сталкиваемся с последствиями этого. Из этого факта следует один простой вывод: в CSS вам нужно делать лишь то, что нужно и ничего более.
Неправильное использование краткой записи это прямой путь к тому, чтобы делать слишком многое слишком рано и поэтому его необходимо избегать. Отменять CSS намного сложнее, чем добавлять.
В нашем примере мы хотели сделать следующее:
.btn {
background-color: red;
}
И в этом коде мы делаем именно то, что нужно и ничего более.
В этом году я столкнулся с одним подобным примером на клиентском проекте:
.base-class {
background-position: 0 0;
background-repeat: no-repeat;
}
.base-class--modifier {
background: radial-gradient(...)
}
Разработчик использовал (и это понятно) синтаксис генератора градиентов для создания сложного радиального градиента, но при этом получилось так, что рендеринг всего вышел совершенно неправильный. Синтаксис градиентов правильный, автопрефиксер работал отлично, но по какой-то причине страница выглядела поломанной.
Команда не смогла разобраться с проблемой, в качестве выхода было предложено “пригласить Гарри, чтобы он разобрался с градиентом” (Гарри Робертс это автор статьи — прим. пер.). Годы опыта в качестве разработчика инстинктивно показали мне, где искать и я нашел: причиной была спрятанная в генераторе градиентов Sass краткая запись свойства background
.
Эта проблема является традиционной для генераторов градиентов, поэтому:
- Обновите свой генератор градиентов прямо сейчас.
- Отправьте пулл-реквест во все проекты, где используется краткая запись.
- Проверьте весь код, который вы скопировали из онлайн-генераторов градиентов.
Пример с background
это лишь один из множества случаев, когда нам не стоит использовать краткую запись. Не менее распространено вертикальное центрирование с помощью margin: 0 auto;
:
.wrapper {
margin: 0 auto;
}
Проблема здесь в том, что при использовании краткой записи мы указываем auto
один раз и это значение используется дважды (справа и слева), а, значит, нам также надо определиться и насчет отступов сверху и снизу. Краткая запись принудила нас к необязательному в обычных условиях решению — явно удалить отступы снизу и сверху, которые вы могли ранее задать в каком-либо другом месте.
Если вам нужно всего лишь центрировать блок, то не стоит при этом трогать верхний и нижний отступы — обычная запись здесь выигрывает:
.wrapper {
margin-right: auto;
margin-left: auto;
}
Поищите в стилях вашего проекта 0 auto
прямо сейчас и посмотрите, что вы найдете.
Исключения
До сих пор мы рассматривали проблему случайного сброса других свойств, но есть случаи, когда этот сценарий работает нормально. Например:
.box {
padding: 10px;
}
Здесь мы ничего случайно не сбрасываем, так как сознательно делаем внутренний отступ в 10 пикселей со всех сторон. И в этом случае краткая запись полностью осмысленна. То же относится и к этой записи:
.btn {
padding: 12px 24px;
}
И к этой:
.foo {
margin: 12px 17px 16px 10px;
}
В этом случае мы по-прежнему явно задаем все четыре расстояния (хотя стоит спросить о смысле магических чисел), но сама краткая запись в полном порядке.
И это главное, что нужно помнить: краткая запись плоха, когда влияет на свойства, которые на самом деле вам не нужно модифицировать.
Этот вид действий — ненамеренный сброс других свойств — особенно проблематичен в модульных и компонуемых системах, когда множество различных классов могут быть использованы в сочетании друг с другом для формирования более сложных композитов. Элементы кода, которые нельзя соединить без коллизий являются неортогональными, а ортогональность это важный принцип архитектуры программного обеспечения.
- Всегда предпочитайте полную запись. Это потребует большего количества нажатий на клавиатуру, большего количества повторений, но это более аккуратно.
- Пишите ровно столько правил, сколько надо и не больше. Большинство проблем в CSS являются следствием слишком широкого применения правил — избегайте этого.