[英]::slotted CSS selector for nested children in shadowDOM slot
CSS ::slotted
選擇器選擇<slot>
元素的子元素。
但是,當嘗試 select 孫子時,例如::slotted(*)
、 ::slotted(*) *
或::slotted(* *)
,選擇器似乎沒有生效。
class MyElement extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({mode: 'open'}) shadowRoot.innerHTML = ` <style>::slotted(*) { display: block; border: solid blue 1px; padding: 3px; }::slotted(*) span { display: block; border: solid red 1px; padding: 3px; }::slotted(* span) { display: block; border: solid green 1px; padding: 3px; } </style> <slot></slot> `; } } customElements.define('my-element', MyElement);
<my-element> <p> <span>Test</span> </p> </my-element>
請注意跨度如何沒有邊框。
這是預期的行為嗎? 我無法為此找到具體的文檔。
如果是,有沒有辦法解決這個問題?
TL;博士
開槽的內容保留在light DOM中,反映到shadow DOM中的<slot>
::slotted(x)
針對 lightDOM 外部元素(又名“皮膚”),而不是shadowDOM 中的 SLOT
::slotted(x)
采用基本選擇器
可繼承的 styles 流入 shadowDOM
https://lamplightdev.com/blog/2019/03/26/why-is-my-web-component-inheriting-styles/
有關 SLOT 和相關主題的最新 WHATWG 討論,請參閱https://github.com/whatwg/html/issues/6051#issuecomment-816971072
參與者: rniwa (蘋果)、 annvk (Mozilla)、 dominic (谷歌)
是的, ::slotted()
不設置嵌套元素的樣式是預期的行為。
slotted
這個詞是違反直覺的,
它意味着元素 lightDOM 被移動到 shadowDOM
開槽的 lightDOM沒有移動,它仍然是..隱藏的..在 lightDOM 中
內容(IF slotted)反映到<slot></slot>
或者來自谷歌開發者文檔
,.
';.
我使用術語反射而不是渲染,因為渲染意味着您可以在shadowDOM 中訪問它。
您不能,因為開槽的內容不在shadowDOM 中……僅從 lightDOM 中反射。
嘗試了更高級的 shadowDOM 樣式。
WebComponents 版本 0 (v0) 有<content>
和::content
; 但它已從規范中刪除:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/content
W3C 標准討論的主要內容
(@hayatoito(谷歌團隊)在這里和這里)是:
所以在 V1 中我們有:slotted
: https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted
來自 Mozilla 開發人員 Emilio:
來源: https://github.com/w3c/webcomponents/issues/889
性能問題是它增加了每個節點需要 go 查找影響它們的規則的子樹的數量。
現在的邏輯是這樣的:如果你有槽,遍歷你的槽並根據需要在它們的影子樹中收集規則。 這是代碼這很好,因為元素樣式的復雜性直接取決於您正在構建的陰影樹的復雜性,並且它只影響開槽節點。
如果您想允許組合子通過時隙,那么每個節點都需要查看其祖先和上一個兄弟鏈並查看其中哪些是時隙的,然后對它們的所有插槽執行該過程。 然后,最重要的是,您還需要更改通用選擇器匹配代碼,以便如果您不在正確的影子樹中,則不包含帶槽選擇器的選擇器不會匹配。
這是您為所有元素支付的成本,無論您使用的是 Shadow DOM 還是::slotted,而且可能只是行不通。
:slotted( S )
得到了有限的 CSS 選擇器功能:► 它只需要簡單的 S 選擇器。 --> 基本上任何有空格的東西都行不通
► 它只針對 lightDOM的“皮膚” 。 --> 也就是說,只有第一級
<my-element>
<h1>Hello World</h1>
<p class=foo>
<span>....</span>
</p>
<p class=bar>
<span>....</span>
</p>
</my-element>
::slotted(h1)
和::slotted(p)
有效
::slotted(.foo)
有效
::slotted(span)
(或任何更深的東西)將不起作用(不是“皮膚”元素)
注意: ::slotted([Simple Selector])
確認符合特異性規則,
但是(很簡單)不會增加lightDOM皮膚選擇器的權重,因此永遠不會獲得更高的特異性。
在某些(罕見的)用例中,您可能需要!important
。
<style>
::slotted(H1) {
color: blue !important;
}
<style>
另請參閱: 將更多深度選擇應用於:主機 CSS 偽 class
<span>
隱藏在 lightDOM 中,在那里所做的任何更改都將繼續反映到它的開槽表示。
這意味着您可以在主 DOM 中使用 CSS應用您想要的任何樣式
(如果您將<my-element>
包裝在一個中,則為父 shadowDOM 容器)
<style>
my-element span {
.. any CSS you want
}
<style>
如果您使用以下命令將 lightDOM移動到shadowDOM: this.shadowRoot.append(...this.childNodes)
你可以在 shadowDOM <style>
標簽中做所有你想要的樣式。
注意:您現在不能再使用<slot></slot>
和:slotted()
了。
<slot>s
僅適用於從 lightDOM反射的內容。
例如,一個元素將自己包裹在一個額外的 shadowDOM 層中,
所以沒有CSS 流出,並且<slot>s
可以使用,請參閱:
這是樣式化 shadowDOM 內容的一種不同/強大的方式:
Apple 終於在 Safari 13.1 中實現了 shadowParts,2020 年 3 月
看:
筆記! ::part
styles shadowDOM ,
<slot></slot>
內容仍保留在lightDOM中!
請注意:可能包含 v0 文檔!
https://css-tricks.com/encapsulating-style-and-structure-with-shadow-dom/
https://developers.google.com/web/fundamentals/web-components/shadowdom?hl=en#composition_slot
https://polymer-library.polymer-project.org/2.0/docs/devguide/style-shadow-dom#style-your-elements
https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/slotchange_event
::part() - https://developer.mozilla.org/en-US/docs/Web/CSS/::part
更改 buttonclick 上的 slot-name 並反映來自 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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.