стили :: элементы с прорезями в shadowDOM
TL; DR
содержимое с ячейками остается в lightDOM, это отражение на <slot>
::slotted(*)
можно только нацеливать на lightDOM SKIN с простыми селекторами
фон
Да, ::slotted()
отсутствие стилизации вложенных элементов является ожидаемым поведением.
Термин slotted
противоречит интуиции, это означает, что элемент lightDOM перемещен в shadowDOM
слот lightDOM НЕ перемещен , он остается .. скрытым .. в lightDOM содержимое (если разделено на IF): отражено в <slot></slot>
Или из Документация разработчика Google
????????????, ??????????? ????? ??? ???? ? ??? ???????. ????? ???'? ?????????? ???? ???; ???? ?????? ?? ?? ??????? ???????? ?????? ??? ?????? ???.
Я использую термин отраженный вместо render , потому что render подразумевает вас может получить к нему доступ в shadowDOM. Вы не можете, потому что содержимое слотов не в shadowDOM ... только отражено от lightDOM.
Почему: слот имеет ограниченную функциональность
Был опробован более продвинутый стиль shadowDOM.
Веб-компоненты версии 0 (v0) имели <content>
и ::content
; но его удалили из spe c: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/content
Основной вывод из обсуждения стандартов W3 C (@hayatoito (команда Google) здесь и здесь ):
So in V1 we have :slotted
: https://developer.mozilla.org/en-US/docs/Web/CSS/ :: прорези
Дополнение №1: Производительность if :: slotted разрешена для сложных селекторов
От разработчика Mozilla Эмилио:
источник: https://github.com/w3c/webcomponents/issues/889
Проблема с производительностью заключается в том, что он увеличивает количество поддеревьев, в которых каждый узел должен go искать правила, которые на них влияют.
Прямо сейчас logi c выглядит так: если вы проходите через свои слоты и собирайте правила в их теневых деревьях по мере необходимости. Это код Это хорошо, потому что сложность стилизации элемента напрямую зависит от сложности теневых деревьев, которые вы строите, и затрагивает только узлы с прорезями.
Если вы Если вы хотите разрешить комбинаторам проходить через слоты, тогда каждому узлу нужно будет посмотреть на своих предков и предыдущих братьев и сестер и посмотреть, какие из них имеют слоты, а затем проделать этот процесс для всех своих слотов. Затем, в верхней части, вам также необходимо изменить общий код сопоставления селекторов, чтобы селекторы, не содержащие селекторов со слотами, не совпадали, если вы не находитесь в правом теневом дереве.
Это стоимость, которая вы платите за все элементы, независимо от того, используете ли вы Shadow DOM или :: slotted, и, вероятно, просто не полетит.
Так что из-за проблем с производительностью
:slotted( S )
ограничена CSS функциональность селектора:
► для S требуются только простые селекторы -> В основном все, что содержит пробел, не будет работать
► нацелен только на lightDOM 'skin' . -> Другими словами, работает только первый уровень
<my-element>
<h1>Hello World</h1>
<p class=foo>
<span>....</span>
</p>
<p class=bar>
<span>....</span>
</p>
</my-element>
Примечание: ::slotted([Simple Selector])
соответствует правилам специфичности, но (будучи простым) не добавляет веса селекторам lightDOM skin , поэтому никогда не получает более высокую специфичность. Вам может понадобится !important
в некоторых (редких) случаях использования.
<style>
::slotted(H1) {
color: blue !important;
}
<style>
Стилизация содержимого с слотами
См. Также: Применение дополнительных выбор глубины для: host CSS псевдокласс
# 1 - стиль lightDOM
<span>
скрыт в lightDOM, любые сделанные там изменения будут продолжать отражать его слот представление.
Это означает, что вы можете применить любой стиль вы хотите с CSS в основном DOM (или родительский контейнер shadowDOM, если вы обернули <my-element>
в один)
<style>
my-element span {
.. any CSS you want
}
<style>
# 2 - (обходной путь) переместите lightDOM в shadowDOM
Если вы переместите lightDOM с appendChild
или append
(или insertBefore или cloneNode, et c.) из lightDOM в shadowDOM, вы можете делать все, что захотите.
Без использования <slot></slot>
и :slotted()
# 3 - :: part (Shadow Parts)
Это другой / мощный способ стилизации содержимого shadowDOM:
Apple наконец реализовала это в Safari 13.1, март 2020
см .:
Примечание! ::part
стили shadowDOM , <slot></slot>
содержимое остается в lightDOM !
ссылки
имейте в виду: может содержать документацию v0!
Пример: использование слотов в качестве маршрутизатора
Изменить имя слота при нажатии кнопки и извлечение нового контента из lightDOM:
<template id=MY-ELEMENT>
<style>
::slotted([slot="Awesome"]){
background:lightgreen
}
</style>
<slot><!-- all unslotted content goes here --></slot>
<slot id=answer name=unanswered></slot>
</template>
<style>/* style all IMGs in lightDOM */
img { max-height: 165px;border:3px dashed green }
img:hover{ border-color:red }
</style>
<my-element><!-- content below is: lightDOM! -->
SLOTs are: <button>Cool</button> <button>Awesome</button> <button>Great</button>
<span slot=unanswered>?</span>
<div slot=Cool> <img src="https://i.imgur.com/VUOujQT.jpg"></div>
<span slot=Awesome><b>SUPER!</b></span>
<div slot=Awesome><img src="https://i.imgur.com/y95Jq5x.jpg"></div>
<div slot=Great> <img src="https://i.imgur.com/gUFZNQH.jpg"></div>
</my-element>
<script>
customElements.define('my-element', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode:'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
this.onclick = (evt) => {
const label = evt.composedPath()[0].innerText; // Cool,Awesome,Great
this.shadowRoot.getElementById("answer").name = label;
}
}
});
</script>
Больше ответов, связанных с SLOT, можно найти с помощью поиска StackOverflow: Пользовательские элементы SLOT