CSS-префиксер для изоляции стилей: добавляем класс-обёртку ко всем правилам

При разработке крупных проектов или интеграции готовых UI-библиотек часто возникает проблема конфликта имён CSS-классов. Стили одной библиотеки могут неожиданно повлиять на элементы другой, даже если вы старались использовать уникальные имена. Обычно эту проблему решают через CSS Modules или Scoped CSS.

Существует и другой, менее очевидный подход: добавить единый класс-контейнер ко всем селекторам CSS-файла. Например, если все правила начинаются с .my-app, то они будут применяться только к элементам внутри блока с этим классом. Это эффективно изолирует стили, не требуя переписывания всей библиотеки.

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

Постановка задачи

Исходный CSS-файл (materialize.css) содержит селекторы разных типов:

Нужно получить файл, в котором каждый селектор (кроме тех, что внутри @keyframes, так как они не относятся к DOM-элементам) будет начинаться с указанного класса, например .mlds. При этом важно сохранить вложенность и медиа-правила:

Почему не Autoprefixer?

Созвучное название может внести путаницу. Autoprefixer добавляет вендорные префиксы к CSS-свойствам (-webkit-, -moz- и т.д.). Наша задача – изменить селекторы, а не свойства. Это позволяет создать неймспейс для целой библиотеки. Такой приём часто называют «css namespacing» или «scoping через родительский класс».

Обзор решения

Я буду использовать библиотеку sabberworm/php-css-parser, которая разбирает CSS в объектную модель, позволяет изменять узлы и затем рендерить обратно в строку. Скрипт:

  1. Загружает исходный CSS.
  2. Парсит его в дерево.
  3. Рекурсивно обходит все блоки правил (DeclarationBlock).
  4. Для каждого селектора добавляет перед ним префикс-класс и пробел.
  5. Пропускает @keyframes (их селекторы не нужно префиксировать).
  6. Сохраняет результат в новый файл.

Код с пояснениями

Я использую composer для подключения Sabberworm. Потому в начале файла появляется строка с vendor/autoload.php. Если вы подключаете Sabberworm напрямую, то у вас этот момент может отличаться.

input и output файлы определяют какой файл нужно править и куда потом сохранить правки.

Теперь в примере — достаточно обернуть часть страницы в <div class="mlds">, и стили Materialize будут действовать только внутри этого контейнера, не конфликтуя с остальными.

Ограничения и нюансы

  1. Сложные селекторы – скрипт просто добавляет пробел и класс в начало строки. Для селекторов вида div > .class + span это даст .mlds div > .class + span, что корректно.
  2. Селекторы с запятой – парсер библиотеки разбивает их на отдельные объекты, поэтому каждый получит префикс.
  3. :host и теневой DOM – если в CSS есть псевдоклассы для веб-компонентов, добавление класса может сломать логику. В таких случаях префиксация не рекомендуется.
  4. @keyframes не префиксируется – это осознанное решение. Если нужно изолировать имена анимаций, потребуется отдельный подход (переименование).
  5. Вес селекторов – добавление родительского класса увеличивает специфичность всех правил. Это редко приводит к проблемам, но о нюансе стоит помнить.

Мало букафф? Читайте есчо !

100vh не корректно работает для мобильных устройств

Июль 23, 2021 г.

Правильно будет сказать, что свойство не работает так как ожидается. Оказывается, что часть контейнера с установленной высотой 100vh, может быть перекрыта нижней панелью браузера. Разберемся как решается данная проблема. В интернете можно найти ...

Читать

Эффект тряски элемента на сайте при наведении с помощью CCS3

Октябрь 23, 2015 г.

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

Читать

box-sizing: padding-box на Chrome

Сентябрь 19, 2015 г.

Пока Хром не поддерживает данное значение атрибута спецификации CSS, что то надо делать! Можно отказаться, но удобно ведь? Самый простой выход написать вместо злополучного экспериментального padding-box: [crayon-6adba8d2552d5681607064/] Во ...

Читать

Вставка переменной в инлайновое изображение в LESS

Август 29, 2019 г.

Небольшие векторные элементы очень удобно вставлять как часть CSS кода. Хочу показать пример, как сделать их еще и параметрически зависимыми, при компиляции из LESS. К примеру, при ребрендинге или использовании кусочка стилей на другом сайте, вы ...

Читать
 

Комментарии к «CSS-префиксер для изоляции стилей: добавляем класс-обёртку ко всем правилам»

Понравилась статья? Есть вопросы? - пишите в комментариях.



Комментарий: