Написание CSS на профессиональном уровне сделает код более поддерживаемым, расширяемым, понятным и чистым. Давайте рассмотрим 5 простых и очень эффективных принципов, которые выведут ваш CSS на новый уровень
- Принцип именования
Правильное именование и структурирование ваших CSS-селекторов является первым шагом к тому, чтобы сделать ваш CSS более удобочитаемым, структурированным и чистым. Определение правил и ограничений в соглашении об именовании делает ваш код стандартизированным, надежным и простым для понимания.
- Принцип низкой специфичности
Переопределение CSS-свойств является очень полезным, но в более сложных проектах всё может достаточно быстро выйти из-под контроля. Цепочки переопределения могут стать очень длинными и сложными, что вынудит вас использовать !important для решения проблем специфичности, в которых можно легко потеряться при отладке кода или добавлении новых функций.
/* Селектор с низкой специфичностью */ .card {} /* Селекторы с высокой специфичностью */ .card .title {} .blog-list .card img {} .blog-list .card.featured .title {} #js-blog-list .blog-list .card img {}
- Браузер и специфичность
Одно из преимуществ следования принципу низкой специфичности - это производительность. Браузеры парсят CSS справа налево.
Давайте взглянем на следующий пример:
.blog-list .card img {}
Браузеры «прочитают» селектор следующим образом:
Вы можете видеть, как селекторы с высокой специфичностью влияют на производительность, особенно когда нам нужно глобально выбрать общий элемент типа div, img, li, и т.п.
- Использование одинакового уровня специфичности
Используя селекторы CSS-классов с низкой специфичностью в сочетании с методологией BEM или одним из других принципов именования, мы можем создать производительный, гибкий и легкий для понимания код.
Зачем использовать CSS-классы? Мы хотим придерживаться одинакового уровня специфичности, оставаясь гибкими и способными выбирать несколько элементов. Селекторы элементов и селекторы по id не обеспечивают нужной нам гибкости.
Давайте перепишем предыдущий пример используя BEM и придерживаясь низкой специфичности:
/* Селектор с низкой специфичностью */ .card {} /* Замена селекторам с высокой специфичностью */ .card__title {} .blogList__image {} .blogList__title--featured {} .blogList__img--special {}
Вы можете видеть, насколько эти селекторы проще, понятнее и могут быть легко переопределены и расширены, если потребуется. И сохраняя их специфичность на низком уровне (единственный класс), мы гарантируем оптимальную производительность и гибкость.
- Принцип DRY
Принцип DRY (Don't Repeat Yourself - не повторяйся) также может быть применён к CSS. Дублирование в CSS может привести к раздутию кода, ненужным переопределениям, ухудшению поддерживаемости и т.п. Эта проблема может быть исправлена с помощью надлежащего структурирования кода и наличия качественной документации.
/* Без использования принципа DRY */ .warningStatus { padding: 0.5rem; font-weight: bold; color: #eba834; } .errorStatus { padding: 0.5rem; font-weight: bold; color: #eb3d34; } .form-errorStatus { padding: 0.5rem 0 0 0; font-weight: bold; color: #eb3d34; }
Давайте проведём рефакторинг кода, следуя принципу DRY:
/* С использованием принципа DRY */ .status { padding: 0.5rem; font-weight: bold; } .status--warning { color: #eba834; } .status--error { color: #eb3d34; } .form__status { padding: 0.5rem 0 0 0; }
- Принцип единственной ответственности
Используя принцип единственной ответственности в CSS, можно быть уверенным, что CSS-классы являются легко расширяемыми и переопределяемыми. Давайте рассмотрим следующий пример:
.button { padding: 1rem 2rem; font-size: 2rem; border-radius: 0.2rem; background-color: #eb4934; color: #fff; font-weight: bold; } .button--secondary { border-radius: 0; font-size: 1rem; background-color: #888; }
Видно, что если потребуется расширить класс .button с помощью модификатора .button--secondary, придётся выполнить много переопределений, хотя мы хотим всего лишь поменять цвет фона, сохранив стили по умолчанию.
Проблема в том, что наш класс .button имеет несколько ролей:
Это усложняет расширение CSS-класса и его объединение с другими классами. Учитывая это, давайте улучшим наш CSS с помощью BEM и OOCSS:
/* Общие стили */ .button { padding: 1rem 2rem; font-weight: bold; color: #fff; } /* Расширения стиля */ .button--radialBorder { border-radius: 0.2rem; } .button--large { font-size: 2rem; } .button--primary { background-color: #eb4934; } .button--secondary { background-color: #888; }
Мы разбили стили нашего button на несколько классов, которые могут использоваться для расширения базового класса. При необходимости мы можем применить модификаторы и добавить новые по мере изменения дизайна или добавления новых элементов.
- Принцип открытости/закрытости
Программные сущности (классы, модули, функции и т. п.) должны быть открыты для расширения, но закрыты для изменения.
Мы уже использовали принцип открытости/закрытости в предыдущих примерах. Все новые функции и опции должны добавляться путём расширения. Давайте рассмотрим этот пример:
.card { padding: 1rem; } .blog-list .card { padding: 0.5em 1rem; }
Селектор .blog-list .card имеет несколько потенциальных проблем:
Давайте перепишем предыдущий пример:
.card { padding: 1rem; } .blogList__card { padding: 0.5em 1rem; }
Мы исправляем проблему, если используем одиночный селектор класса. С этим селектором мы можем избежать непредвиденных эффектов и не используем условно вложенные стили.