Обложка статьи «18 советов по CSS, которые сделают жизнь разработчика проще»

18 советов по CSS, которые сделают жизнь разработчика проще

Перевод статьи «CSS rules that will make your life easier»

Цвета

Когда вы используете в проекте огромное количество цветов, сложно не запутаться, так как порой отличия бывают незаметными: возьмите #3426D1 и #3426D2. Для решения этой проблемы достаточно использовать элементарные классы цветов в CSS или SCSS.

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

Другая проблема — баги при использовании альфа-канальных цветов. Обычно такие цвета задаются с использованием функций rgba() или hsla(). Цвет, заданный со значением альфа-канала, отличным от 1, является полупрозрачным. Воспринимаемый цвет теперь меняется в зависимости от того, что находится на заднем плане. Если цвет вам нужен таким, каким он выглядит на белом фоне, лучше использовать hex-значение. Некоторые функции, lighten() в SASS например, сгенерируют полупрозрачный цвет, поэтому лучше придерживайтесь точно закодированных значений.

Типографика

Все свойства, которые влияют или находятся под влиянием шрифта, должны быть объявлены в одном месте, сразу после какого-нибудь @font-face. Также можно добавлять классы для шрифтов, которые меняют font-size (через rem) и задают те line-height, letter-spacing и word-spacing, которые подходят для заданного шрифта и его размера. После этого нигде не должны использоваться font-* или text-* (за исключением text-overflow).

Объявление данных свойств вместе с font-face гарантирует, что страницы сайта всегда будут выглядеть правильно. Настройка line-height вместо padding или margin может вызвать ошибки при обвёртывании текста. А установка font-weight отдельно от всех остальных свойств (стилей), касающихся шрифта, приведёт к faux bold font. Изменение font-style для шрифта, который не поддерживается, тоже ведёт к неправильному его отображению.

Устанавливайте размер шрифта в rem единицах. Использование em приведёт к проблемам при вложении элементов, так как em является скалярным кратным текущему размеру шрифта.  px может создать нечитаемый и  неадаптивный  контент. Позвольте пользователю (или браузеру пользователя) установить подходщий им размер шрифта  — не объявляйте размер шрифта в body или элементе html и используйте только rem.

Интервалы

На сайте, где в первую очередь важен контент, интервалы должны гармонично дополнять содержание. Но в некоторых измерениях, как padding: 4px, общий вид будет выглядеть не очень. А любое динамическое измерение, сообщающееся со шрифтом, например padding: .5em, будет хорошо смотреться во всех случаях.

Для интервалов используйте em.

Инструмент CSS Grid Layout

CSS Grid очень хорошо поддерживается (возвращаясь к IE10) и позволяет организовывать контент без добавления контейнерных элементов наподобие Bootstrap-row или Bootstrap-col. Дизайнеры часто работают с 12-колонной сеткой, и CSS-фреймворки следуют этому. Но сетки, как и интервалы, должны организовывать контент, а не ограничивать его. Сетки не должны быть заранее заточены под определённый формат. Не стоит целиком полагаться на сетку.

Выравнивание текста

text-align используют для выравнивания не только текста, но и других элементов. Но для этого лучше подходит flexbox. В некоторых языках, которые пишутся справа налево или вертикально, свойства left и right могут работать некорректно. В случае с justify проблемы могут возникнуть с языками, где есть орграфы. Также он может доставить неудобства людям с дислексией. Каждый из этих вариантов решается flexbox. Поэтому для таких случаев всегда используйте его.

Свойство outline

Границы выделенных элементов — это то, как браузер взаимодействует с элементами, находящимися в фокусе. Хотя дефолтные границы достаточно хороши, всё равно их часто либо изменяют, либо вообще убирают, просто потому что они не сочетаются с дизайном. И если вы всё-таки решили не использовать оригинальный outline, запомните: пока вы не заменили свойство чем-нибудь другим, не удаляйте и не аннулируйте его.

Псевдоклассы :focus и :hover

Как упоминалось выше, менять значение :focus не рекомендуется, так как оно выступает в роли индикатора для элемента, который в данный момент находится в фокусе. При добавлении стилей :hover не используйте псевдоселекторы для демонстрации дополнительного контента, если вы не проделали то же самое для :focus. Обычно, но не всегда, полезно использовать :hover и :focus псевдоселекторы одновременно для одних и тех же стилей (но будьте осторожны, добавление focus-селектора на hover-стили, например для кнопки, может вызвать эффект залипания).

Непрозрачность

Устанавливая opacity на ноль, вы фактически не скрываете элемент от инструментов специальных возможностей. Он до сих пор находится в документе, и его может найти любой желающий. Это свойство действительно требуется только в двух случаях: когда элемент появляется в поле зрения (быстрое изменение opacity c 0 до 1) и при стилизации наложения диалогового окна (таким образом содержимое под окном ещё немного заметно). Избегайте наложения полупрозрачных слоёв, так как уровень прозрачности (opacity) накапливающийся. Контент, находящийся под двумя элементами с opacity: 50%,  будет выглядеть так, будто он находится под одним элементом с opacity: 25%.

Селекторы

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

Производительность CSS-селекторов в современных браузерах — вопрос не первой важности, возможно, вы слышали об универсальном селекторе (*). О чём действительно стоит беспокоиться, так это о слишком большом охвате этого селектора. В будущем это может повлечь больше неудобств, чем пользы. Использование селектора вроде .my-class > в конечном счёте потребует от вас выбрать какой-нибудь дочерний класс, так что вам придётся добавлять другие классы и направлять этот селектор на них.
Тот же самый аргумент можно привести в пользу неиспользования type-селекторов (div, main), которые скапливаются в больших количествах и требуют добавления некоторых идентифицирующих свойств div.some-class. Вот такие множественные селекторы более специфичны, и вероятность багов меньше.
То же самое с селекторами .class[attribute] и :focus.

Чрезмерная точность

Селекторы бывают не только слишком общими, но ещё и слишком специфичными — два конкретно запарных случая. Чрезмерно специфичные селекторы порождают ещё более специфичные селекторы. Каждый последующий из них становится препятствием при изменении стилей элемента, что в конце концов приводит к хрупким таблицам стилей, с которыми никто не хочет работать.

В CSS есть встроенная специфичность — порядок (очередь) resultset’ов. Это каскад в каскадных таблицах стилей. Исходя из этого, можно выдавать resultset’ы в порядке возрастания по их значимости, без увеличения уровня специфичности селектора. Например:

.btn {
  color: black;
}
.btn--primary {
  color: green;
}
.btn--primary--light {
  color: white;
}

В этом примере каждый последующий классовый селектор более специфичен, чем предыдущий, таким образом устраняется необходимость объявлять стили для .btn.btn--primary or .btn.btn--primary--light.

Запомните: используйте единичные классовые селекторы везде, где только возможно, записывайте их в порядке возрастания значимости и избегайте образования хрупких таблиц стилей.

Свойство text-transform

Для сайтов, которые поддерживают какие-либо языки, помимо английского, со свойством text-transform могут возникнуть проблемы. Бывает, браузеры подставляют ненужный символ для преобразования нижнего и верхнего регистра. Чтобы это не случилось, не юзайте text-transform.

Свойство z-index

Если в стилях присутствует любой z-index, обязательно будет ещё два свойства, которые объявляют z-index: 9999; и z-index: 99999;. При попытке использования атомарных классов или переменных для ограничения количества допустимых z-index без метода calc() и SCSS-математики не обойтись, поскольку придётся изменять значение переменной.

В большинстве случаев, если не во всех, z-index можно заменить изменением структуры HTML для натуральной укладки элементов (чем глубже элементы в верстке — тем выше они в отображении) или добавлять к элементу или его родителю новый контекст наложения.
В общем, избегайте z-index.

Псевдоэлементы

Иногда с псевдоэлементами ::before и ::after  можно поиграться, многие стилистические фичи основаны именно на этих двух псевдоэлементах, и пока они пустые (без контента), всё выглядит вполне сносно. Проблема с размещением контента в этих элементах заключается в том, что не все устройства способны справляться с нагрузкой. Так что не размещайте в них ничего.

Псевдоэлементы ::first-letter и ::first-line не работают так, как вы могли предполагать. Они действуют лишь на первый символ/строку в блоке. С ::first-line, бывает, возникает ошибка с двухбайтовыми символами, такими как Japanese Kana, и орграфами.
С управлением стилями выделенного текста или placeholder’а, осуществляемого с помощью ::selection или ::placeholder, зачастую возникают проблемы. С ::placeholder всё просто: не используйте его. Это особенно важно для полей ввода паролей и т.п.

При выделении текста и измении стиля (обычно color и background-color) возникают коварные баги. Пока дефолтные цвета выделения, не совместимые с браузерами и устройствами, недостаточно контрастны и не так сочетаются с цветом и стилем текста на вашем сайте, пользователи частенько переписывают их для лучшей читабельности. Изменение цветов в этом случае либо не будет работать, либо будет мешать их стилям (если вы пользовались !important). Использование этого псевдоэлемента для красивой картинки может обернуться недовольством посетителей вашего сайта.

Переходы и анимация

transitionsи animations в CSS  отличаются от opacity и transform тем, что после их выполнения браузер заново перерисовывает всю страницу. На мощном компьютере это никак не заметно, но на простеньких телефонах и ноутбуках всё выглядит криво. Плохая анимация смотрится хуже, чем её отсутствие.

Медиа-запрос prefers-reduced-motion

Создание красивых ненавязчивых анимаций — нелёгкое дело. С появлением медиа-запроса prefers-reduced-motion управлять анимацией на странице стало намного проще, к тому же он помогает сделать страницы безопаснее для людей, страдающих расстройствами вестибулярного аппарата. Данный скрипт останавливает выполнение всех анимаций, если автор не включает класс safe-animation  в элемент.

/* https://github.com/mozdevs/cssremedy/issues/11#issuecomment-462867630 */
@media (prefers-reduced-motion: reduce) {
  *:not(.safe-animation),
  *:not(.safe-animation)::before,
  *:not(.safe-animation)::after {
    animation-duration: 0.01s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0s !important;
    scroll-behavior: auto !important;
  }
}

Сброс стилей

Хорошо использовать немного улучшенную версию Meyers reset. Несколько аспектов удалены из reset’а, например списки иконок ol и ul элементов, которые могут привести к тому, что начнут объединяться вещи одинаковые по представлению, но разные по происхождению. Также в этой версии отсутствует установка line-height в body на 1, ведь всё зависит от шрифта и впоследствии могут возникнуть непредвиденные ошибки. В этом reset’е есть вещи, упомянутые выше. В CSS не добавляется атомарный класс .hidden, потому что есть лучшее решение, которое будет работать, даже если CSS не подгрузится, — hidden-атрибут. Обычно на скрытые элементы браузер выставляет display: none, но это тоже можно изменить.

body {
  /* more intuitive sizing */
  box-sizing: border-box;
}
*, ::before, ::after {
  box-sizing: inherit;
}
i, cite, em, var, dfn, address {
  /* prevent faux italic */
  font-style: normal;
}
b, h1, h2, h3, h4, h5, h6, strong, th {
  /* prevent faux bold */
  font-weight: normal;
}
[hidden] {
  /* enforce accessible semantics */
  display: none !important;
}

Исходники reset’a — https://github.com/NickGard/css-utils/blob/master/reset.css.
Ещё одна полезная штука — это класс visually-hidden. Вместе с aria-label для невидимого читаемого с экрана текста нужно использовать следующий блок кода:

/* https://a11yproject.com/posts/how-to-hide-content/ */
.visually-hidden {
  position: absolute !important;
  height: 1px;
  width: 1px;
  overflow: hidden;
  clip: rect(1px, 1px, 1px, 1px);
}

Наименования в соответствии с методологией BEM

BEM, пожалуй, лучший способ именования элементов, и читается он легко <button class="btn_primary" /> — сразу понятно, к какому типу кнопки относится данный элемент. Маленькое отступление от стиля BEM <button class="btn btn--primary" />, но это довольно-таки удобно, сразу видно, что второй класс базируется на первом. При этом CSS выглядит так :

.btn, .btn--primary {
  /* base button styles */
}
.btn--primary {
  /* primary button overrides */
  /* has naturally higher specificity */
}

В SCSS вы можете достигнуть подобного эффекта, используя @extend.

Не смешно? А здесь смешно: @ithumor