Сегодняшняя тема — 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…