Изоляция стилей в Shadow DOM
Тред из третьего дня моей недели в @jsunderhood.
Сегодняшняя тема — Shadow DOM, его возможности и ограничения. Начнем с треда о главной проблеме, которую Shadow DOM призван решить: глобальный неймспейс и отсутствие в CSS изоляции.
— jsunderhood (@jsunderhood) November 11, 2020
Этим летом я выступал на DevParty Russia с докладом “Shadow DOM: вдали от проторенных троп”. Тред отчасти написан по его мотивам.https://t.co/4GRbINugJT
— jsunderhood (@jsunderhood) November 11, 2020
“Проторенной тропой” я называю способы инкапсуляции стилей, ставшие традиционными: БЭМ и другие методологии, CSS modules, CSS-in-JS. Все это — варианты именования или генерации классов.
— jsunderhood (@jsunderhood) November 11, 2020
Сразу определимся с терминами: инкапсуляция = стили компонента не протекают наружу. Изоляция = то же самое плюс отсутствие для внешних, глобальных стилей возможности проникнуть внутрь.
— jsunderhood (@jsunderhood) November 11, 2020
В теории изоляция кажется полезной. Но как показала практика, в качестве универсального решения этот подход не работает (в том числе потому, что его реализация требует JS, но не только).
— jsunderhood (@jsunderhood) November 11, 2020
В статье на Web Fundamentals есть фраза “Shadow DOM fixes CSS and DOM”. Я бы сказал, все обстоит наоборот: он ломает некоторые привычные представления, требуя иначе структурировать код.https://t.co/HDj7lUpNww
— jsunderhood (@jsunderhood) November 11, 2020
Пример: если на странице есть reset, normalize или глобальные стили для box-sizing, внутри shadow root они не применятся. Это, впрочем, не столь важно при использовании компонентного подхода.
— jsunderhood (@jsunderhood) November 11, 2020
Еще один момент: обычно, вне зависимости от выбранного способа инкапсуляции стилей, его принято строго придерживаться. Вряд ли имеет смысл смешивать в одном проекте несколько подходов.
— jsunderhood (@jsunderhood) November 11, 2020
Но повсеместное использование Shadow DOM чревато рядом последствий. Mattia Astorino приводит хорошую аналогию: завернуть приложение в shadow root — все равно что поместить его в <input>.https://t.co/BMYZ7vKo1c
— jsunderhood (@jsunderhood) November 11, 2020
Это ключевой момент: изоляция Shadow DOM подобна той, которой обладают встроенные HTML-элементы. О том, как это выглядит на практике, можно почитать в статье Ire Aderinokun.https://t.co/Q4Q1v8V5l5
— jsunderhood (@jsunderhood) November 11, 2020
Кстати, заглянуть внутрь <input type=“range”> или <video> можно не только в браузерах на основе Chromium (галочка “show user agent shadow DOM” в настройках DevTools), но и в Safari.
— jsunderhood (@jsunderhood) November 11, 2020
Изоляция исключает конфликты из-за имен классов, селекторов по ID и тегам. Это полезно, но в реальных проектах регулярно возникает необходимость в сторонней библиотеке на CSS-классах.
— jsunderhood (@jsunderhood) November 11, 2020
Раньше в слаке Polymer регулярно звучал вопрос “как использовать Bootstrap внутри Shadow DOM” (стоп, а нужна ли тогда изоляция?). Сегодня тенденция поменялась: стали спрашивать про Tailwind.
— jsunderhood (@jsunderhood) November 11, 2020
Что примечательно, такие вопросы задают не только новички. То есть, причина не в отсутствии понимания принципов изоляции, а в желании сохранить удобные, устоявшиеся практики.
— jsunderhood (@jsunderhood) November 11, 2020
С одной стороны, Shadow DOM позволяет забыть об именовании классов. Но, устраняя одну из причин появления CSS-методологий, изоляция не отменяет необходимости писать поддерживаемый код.
— jsunderhood (@jsunderhood) November 11, 2020
В результате у Material Web Components мы можем внутри shadow DOM увидеть классы, именуемые по БЭМ (правда, это связано и с тем, что базовые стили подключаются из отдельного npm-пакета).https://t.co/25PNNarRsj
— jsunderhood (@jsunderhood) November 11, 2020
Подытожим: изоляция Shadow DOM предлагает решение одной из важных проблем CSS, но при этом приносит новые. Иногда его использование оправдано, но в целом этот подход не взлетел.
— jsunderhood (@jsunderhood) November 11, 2020
Добавлю, что Nicole Sullivan из Google уже зондирует почву на предмет альтернативной инкапсуляции на CSS media queries. В поддержку высказался Rich Harris, известный критик Shadow DOM.https://t.co/TKFagrEcTu
— jsunderhood (@jsunderhood) November 11, 2020