Изучая принципы базового CSS, человека учат писать модульные, многократно используемые и описательные стили, чтобы обеспечить удобство сопровождения. Но когда разработчики начинают заниматься реальными приложениями, часто кажется невозможным добавлять функции пользовательского интерфейса без утечки стилей в непредусмотренные области. Эта проблема часто превращается в самореализующуюся петлю; стили, которые теоретически привязаны к одному элементу или классу, начинают появляться там, где им не место. Это вынуждает разработчика создавать еще более конкретные селекторы для переопределения просочившихся стилей, которые затем случайно переопределяют глобальные стили и так далее. Жесткие соглашения об именах классов, такие как БЭМ, являются одним из теоретических решений этой проблемы. Методология BEM (Блок, Элемент, Модификатор) — это систематический способ именования классов CSS для обеспечения возможности повторного использования и структуры файлов CSS. Подобные соглашения об именах могут снизить когнитивную нагрузку за счет использования языка предметной области для описания элементов и их состояния, а при правильной реализации могут упростить поддержку стилей для больших приложений. Однако в реальном мире не всегда так получается. Приоритеты могут меняться, и с этими изменениями реализация становится непоследовательной. Небольшие изменения в структуре HTML могут потребовать внесения множества изменений в имена классов CSS. В высокоинтерактивных интерфейсных приложениях имена классов, соответствующие шаблону БЭМ, могут стать длинными и громоздкими (например, app-user-overview__status--is-authenticating), а неполное соблюдение правил именования нарушает структуру системы, тем самым сводя на нет ее преимущества. Учитывая эти проблемы, неудивительно, что разработчики обратились к фреймворкам, причем Tailwind является самым популярным фреймворком CSS. Вместо того, чтобы бороться с кажущейся безвыигрышной войной между стилями, проще отказаться от каскада CSS и использовать инструменты, гарантирующие полную изоляцию. Разработчики больше полагаются на утилиты Откуда мы знаем, что некоторые разработчики стараются избегать каскадных стилей? Это появление «современных» интерфейсных инструментов, таких как фреймворки CSS-in-JS, разработанных специально для этой цели. Работа с изолированными стилями, тесно привязанными к конкретным компонентам, может показаться глотком свежего воздуха. Это избавляет от необходимости давать названия вещам — по-прежнему одной из самых ненавистных и трудоемких задач интерфейса — и позволяет разработчикам работать продуктивно, не понимая полностью и не используя преимущества наследования CSS. Но отказ от CSS Cascade имеет свои проблемы. Например, составление стилей в JavaScript требует сложных конфигураций сборки и часто приводит к неуклюжему смешиванию стилей с разметкой компонентов или HTML. Вместо тщательно продуманных соглашений об именах мы позволяем инструментам сборки автоматически генерировать для нас селекторы и идентификаторы (например, .jsx-3130221066), требуя от разработчиков поддерживать еще один псевдоязык сам по себе. (Как будто когнитивной нагрузки по пониманию того, что делают все useEffects вашего компонента, уже недостаточно!) Дальнейшее абстрагирование работы по присвоению имен классам инструментария означает, что базовая отладка часто ограничивается конкретными версиями приложений, скомпилированными для разработки, вместо использования встроенных функций браузера, поддерживающих живую отладку, таких как инструменты разработчика. Это похоже на то, что нам нужно разработать инструменты для отладки инструментов, которые мы используем для абстрагирования того, что уже предоставляет Интернет — и все это ради того, чтобы избежать «боли» написания стандартного CSS. К счастью, современные функции CSS не только делают написание стандартного CSS более гибким, но и дают таким разработчикам, как мы, гораздо больше возможностей для управления каскадом и заставить его работать на нас. Каскадные слои CSS — отличный пример, но есть еще одна функция, которой на удивление не уделяется внимания — хотя ситуация меняется теперь, когда она недавно стала совместимой с Baseline. CSS @scope At-правило Я считаю, что at-правило CSS @scope является потенциальным лекарством от беспокойства, вызванного утечкой стилей, которое мы рассмотрели, и которое не заставляет нас жертвовать собственными веб-преимуществами ради абстракций и дополнительных инструментов сборки. «CSS-правило @scope позволяет вам выбирать элементы в определенных поддеревьях DOM, точно ориентируясь на элементы, не создавая слишком специфические селекторы, которые трудно переопределить, и не привязывая ваши селекторы слишком тесно к структуре DOM». — MDN
Другими словами, мы можем работать с изолированными стилями в конкретных случаях, не жертвуя наследованием, каскадированием или даже базовым разделением задач.это давний руководящий принцип фронтенд-разработки. Кроме того, он имеет отличное покрытие браузера. Фактически, в декабре Firefox 146 добавил поддержку @scope, что впервые сделало его совместимым с Baseline. Вот простое сравнение кнопки, использующей шаблон BEM, и кнопки @scope:
<стиль> .button .button__text { /* стили текста кнопки */ } .button .button__icon { /* стили значков кнопок */ } .button--primary { стили основных кнопок */ } стиль>
<стиль> @scope (.primary-button) { span:first-child { /* стили текста кнопки */ } span:last-child { /* стили значков кнопок */ } } стиль>
Правило @scope обеспечивает точность с меньшими сложностями. Разработчику больше не нужно создавать границы, используя имена классов, что, в свою очередь, позволяет им писать селекторы на основе собственных элементов HTML, тем самым устраняя необходимость в предписывающих шаблонах имен классов CSS. Просто устраняя необходимость в управлении именами классов, @scope может облегчить страх, связанный с CSS в больших проектах. Основное использование Для начала добавьте правило @scope в свой CSS и вставьте корневой селектор, к которому будут применяться стили: @scope (<селектор>) { /* Стили ограничены <селектором> */ }
Так, например, если бы мы ограничили стили элементом
@scope (навигация) { a { /* Стили ссылок в области навигации */ }
a:active { /* Стили активных ссылок */ }
a:active::before { /* Активная ссылка с псевдоэлементом для дополнительного оформления */ }
@media (максимальная ширина: 768 пикселей) { a { /* Адаптивные настройки */ } } }
Это само по себе не является новаторской особенностью. Однако к области можно добавить второй аргумент, чтобы создать нижнюю границу, эффективно определяя начальную и конечную точки области.
/* К любому элементу a внутри ul не будут применены стили */ @scope (nav) to (ul) { а { размер шрифта: 14 пикселей; } }
Эта практика называется кольцевой областью действия, и существует несколько подходов, которые можно использовать, включая серию похожих, очень специфических селекторов, тесно связанных со структурой DOM, псевдоселектор :not или присвоение определенных имен классов элементам внутри
Заключение CSS-фреймворки, ориентированные на утилиты, такие как Tailwind, хорошо подходят для прототипирования и небольших проектов. Однако их преимущества быстро уменьшаются при использовании в более крупных проектах, в которых участвует более двух разработчиков. За последние несколько лет фронтенд-разработка становится все более сложной, и CSS не является исключением. Хотя правило @scope не является панацеей, оно может снизить потребность в сложных инструментах. При использовании вместо стратегического именования классов или вместе с ним @scope может упростить и сделать более интересным написание поддерживаемого CSS. Дальнейшее чтение
CSS @scope (MDN) «CSS @scope», Хуан Диего Родригес (CSS-Tricks) Примечания к выпуску Firefox 146 (Firefox) Поддержка браузера (CanIUse) Популярные CSS-фреймворки (состояние CSS 2024) «Буква «C» в CSS: Cascade», Томас Йип (CSS-Tricks) Введение в БЭМ (получите БЭМ)