🔥

Тред (Сергей Куликов)


Сегодняшняя тема — Shadow DOM, его возможности и ограничения. Начнем с треда о главной проблеме, которую Shadow DOM призван решить: глобальный неймспейс и отсутствие в CSS изоляции.

Этим летом я выступал на DevParty Russia с докладом “Shadow DOM: вдали от проторенных троп”. Тред отчасти написан по его мотивам. youtu.be/97_zqVXwAj4?t=…

“Проторенной тропой” я называю способы инкапсуляции стилей, ставшие традиционными: БЭМ и другие методологии, CSS modules, CSS-in-JS. Все это — варианты именования или генерации классов.

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

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

В статье на Web Fundamentals есть фраза “Shadow DOM fixes CSS and DOM”. Я бы сказал, все обстоит наоборот: он ломает некоторые привычные представления, требуя иначе структурировать код. developers.google.com/web/fundamenta…

Пример: если на странице есть reset, normalize или глобальные стили для box-sizing, внутри shadow root они не применятся. Это, впрочем, не столь важно при использовании компонентного подхода.

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

Но повсеместное использование Shadow DOM чревато рядом последствий. Mattia Astorino приводит хорошую аналогию: завернуть приложение в shadow root — все равно что поместить его в <input>. equinusocio.dev/blog/web-compo…

Это ключевой момент: изоляция Shadow DOM подобна той, которой обладают встроенные HTML-элементы. О том, как это выглядит на практике, можно почитать в статье Ire Aderinokun. bitsofco.de/what-is-the-sh…

Кстати, заглянуть внутрь <input type=“range”> или <video> можно не только в браузерах на основе Chromium (галочка “show user agent shadow DOM” в настройках DevTools), но и в Safari.

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

Раньше в слаке Polymer регулярно звучал вопрос “как использовать Bootstrap внутри Shadow DOM” (стоп, а нужна ли тогда изоляция?). Сегодня тенденция поменялась: стали спрашивать про Tailwind.

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

С одной стороны, Shadow DOM позволяет забыть об именовании классов. Но, устраняя одну из причин появления CSS-методологий, изоляция не отменяет необходимости писать поддерживаемый код.

В результате у Material Web Components мы можем внутри shadow DOM увидеть классы, именуемые по БЭМ (правда, это связано и с тем, что базовые стили подключаются из отдельного npm-пакета). github.com/material-compo…

Подытожим: изоляция Shadow DOM предлагает решение одной из важных проблем CSS, но при этом приносит новые. Иногда его использование оправдано, но в целом этот подход не взлетел.

Hey CSS friends, does this make sense to you? @ scope (.airplane) end (.passenger_cabin, .cockpit, .luggage_compartment) If you had to guess, what does this do?
Добавлю, что Nicole Sullivan из Google уже зондирует почву на предмет альтернативной инкапсуляции на CSS media queries. В поддержку высказался Rich Harris, известный критик Shadow DOM. twitter.com/stubbornella/s…