Хабрахабр

[Из песочницы] Так когда же всё таки можно использовать !important?

Любая фича в «кривых» руках становится плохой. Импортант —  не исключение. Плохо не то, что он умеет, а то, как его используют.

Анимированное изображение на котором Маллой добавляет яд в блюдо

Как работает !important

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

Например:

.content .title { color: red;
} .title { color: blue;
}

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

Так вот, используя этот же пример, но с !important, мы вдруг узнаём, что ему «плевать» на вашу специфичность.

.content .title { color: red;
} .title { color: blue !important;
}

Заголовок будет синим! Это свойство нарушает естественный поток написанных нами правил и менее приоритетным стилям даёт наибольший приоритет.

Допишем ещё один импортант. Ну хотя, как «плевать»… Не совсем уж и плевать.

.content .title { color: red !important;
} .title { color: blue !important;
}

И заголовок снова красный. Потому что у нас конфликтуют два !important и решается этот конфликт сравнением весов селекторов.

Импортант —  это плохо, когда так:

.title { color: red;
}

«Хм, я же написал “красный”, почему мой заголовок не красный? А если так?»

.title { color: red !important;
}

«Отлично! Красный!» А точно ли отлично?

Скорее всего, вес селектора, которым вы воспользовались, оказался просто недостаточным и, написав чуть более точный и «тяжелый» селектор, вы бы решили свою проблему, а так вы жестко переопределили стили, и хорошо, если вы знаете и проверили все места, где использовался этот класс, но если это не так, то вы подчинили элемент в одном месте и, вероятно, сломали в другом. Такой подход плох как минимум потому, что вы переопределяете стили не разобравшись, почему они не применялись без импортанта.

Инструмент для hotfix

Очень часто, когда я задаю кому-то вопрос про импортанты, я слышу ответ в стиле: «Я использую important тогда, когда мне нужно быстро пофиксить проблему и некогда разбираться в коде, который писал не я и который написан очень плохо».

Вы и сами не заметили, как сделали «плохой чужой код» ещё хуже. Да, но только задачи всегда «срочные», такие задачи, как правило, никто и никогда не доделает, так это и оставив.

Разве узнать необходимый вес селектора для переопределения так сложно и долго? Что значит «быстро»? Мы очень активно используем DevTools при разработке, и для решения этой задачи ответ у нас есть там же.

Его текущий цвет — черный. Инспектируем элемент, который хотим изменить. Смотрим, по какому же селектору был назначен этот цвет?

Скриншот веб-инспектора с примером инспектирования цвета у элемента

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

Скриншот веб-инспектора с примером инспектирования цвета у элемента

Мне кажется, по времени это мало отличается от того, чтобы дописать !important, однако намного правильнее и безопаснее. Разве это долго?

Сторонние решения и чужой код

Второй по популярности ответ на вопрос про необходимость использования импортантов: «Я использую !important, когда переопределяю стили сторонних библиотек и плагинов или CMS-ок».

Именно в такой форме он неправильный, потому как стили сторонних файлов можно перезаписывать точно так же, как и свои, просто дописывая их после подключения чужих стилей и повышая вес селектора. Этот ответ чуть ближе к правде, но только если его чуть более точно сформулировать.

Например, если вы подключили слайдер к своей странице, который реализован так, что при переключении слайда JavaScript-ом перезаписываются значения некоторых свойств в CSS. Однако в некоторых случаях этот ответ «попадает» в вопрос.

Скриншот веб-инспетора с динамическим изменением стилей у элемента

А вам почему-то надо переопределить эти свойства, проигнорировав изменения самого плагина.

То есть фактически любые свойства, изменённые у элемента с помощью JavaScript, будут просто записаны в атрибут style. JS может переназначать значения свойств только с помощью inline-стилей. С точки зрения механизма специфичности, эти стили более приоритетные, и как бы вы ни повышали вес селектора, вы не сможете перезаписать их.

Это именно тот первый случай, в котором нам просто не обойтись без important.
Если нам нужно переопределить инлайновые стили, то нам поможет только important.
Приоритетность стилей с импортантом выше, чем приоритетность инлайн-стилей, и если у вас почему-то появилась необходимость перезаписывать инлайновые стили, то у вас нет вариантов, кроме как использовать !important.

Important во благо

Рассмотрим ещё один случай, который иногда применяют в коде различных библиотек и плагинов.

Возможно, им тоже просто нужно было быстро пофиксить, и они так поступили (сарказм), но вообще этому есть более подходящее объяснение. Если вы откроете исходный CSS-код библиотеки Bootstrap, то увидите, что там разработчики библиотеки очень часто прибегают к использованию импортантов. Таким образом разработчики Bootstrap «защищают» свой код. В этом случае important-ы используются «во благо».

Таким образом, разработчики перестраховались, и сломать поведение их кода будет сложнее, если вы не знаете, как работает специфичность. Дело в том, что вы, подключая к своему сайту эту библиотеку, можете переопределять её исходные стили. Но если вы понимаете, как работает механизм специфичности в CSS, то можете переопределить их импортант, записав свои стили тоже с импортантом, но с более «тяжелым» селектором.

Тем самым мы приходим к второму случаю, когда без импортанта нельзя.
Если вам нужно переопределить important (ваш или из сторонней библиотеки), то вам поможет только !important.

И совсем не важно откуда эти стили: из ваших файлов или из сторонних. Именно поэтому некорректно говорить: «Я использую импортанты, когда мне нужно переопределить стили сторонних библиотек», правильнее будет сказать: «Я использую импортанты, когда мне нужно переопределить inline-стили или другие !important».

Хелперы

В предыдущем абзаце, по сути, описаны все случаи, когда использование импортантов будет нормальным и правильным. Это те случаи, в которых применение импортантов будет неизбежным. Но существуют ещё случаи, в которых использование импортантов будет допустимым, хоть, возможно, уже и не совсем уместным.

Иногда нам необходимы вспомогательные универсальные классы, которые мы используем в своём коде с целью повторного использования кода и некоторого упрощения.
Например, мы создаём какой-то класс .warning, который будем применять к различным элементам на странице, тем самым обозначая их важность.

.warning { color: red;
}

И мы хотим, чтобы, применяя этот класс к любому элементу, мы точно делали текст в этом элементе красным. Но ведь у элемента могут быть более приоритетные стили, записанные по более точному селектору, и тогда наш цвет из класса .warning перетрется. В таком случае, добавив important в наш классхелпер, мы делаем его более универсальным, потому что цвет, применяемый в этом классе, будет более приоритетным. Однако сказать, что это хорошо, я не могу. Ведь это делает стили класса более приоритетными, но все равно не гарантирует вам стопроцентной работы, поскольку этот хелпер может столкнуться с другим important, и все равно всё пойдёт не по плану. А потом, когда окажется, что все же в определенном случае этот класс должен делать текст «не таким уж и красным», то вы сразу же «родите» новый селектор с повторением импортанта.

Когда всё таки можно

Правильно и нормально использовать !important, когда вам нужно переопределить inline-стили или другие !important.

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

Современные методологии вроде БЭМ тоже диктуют свои правила, в которых использование инлайновых стилей или импортантов будет неуместным.

Импортант вам не нужен не потому, что он какой-то загадочный и ужасный, а просто потому, что в большинстве случаев можно обойтись без него.

Например, у вас может появиться необходимость использовать это, когда вы разрабатываете собственную библиотеку, плагин или браузерное расширение и вам нужно какое-то более приоритетное поведение конкретных стилей. Все исключения, которые я определил для себя, как правило, сводятся к не очень типичным случаям. Однако это далеко не про типичное регулярное использование.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть