[英]Shadow DOM styling from the outside
我正在尋找一種從外部設置 shadow DOM 樣式的方法。 例如,我想將所有“span.special”元素中所有文本的顏色設置為紅色。 包括來自 shadow DOM 的“span.special”元素。 我怎么能做到這一點?
以前有::shadow偽元素和/deep/組合器又名>>>用於此目的。 所以我可以寫一些類似的東西
span.special, *::shadow span.special {
color: red
}
但現在::shadow 、 /deep/和>>>已被棄用。 那么,我們有什么可以替代它們呢?
好吧,如果您正在使用無法更改的庫 Web 組件,@import 不是解決方案......
最后我找到了幾種方法:
1) 級聯。 Shadow DOM 的宿主元素的樣式也會影響 Shadow DOM 元素。 如果您需要為 Shadow DOM 的特定元素設置樣式,則不是一個選項,而不是每個元素。
2) 自定義屬性https://www.polymer-project.org/1.0/docs/devguide/styling如果 Web 組件的作者提供了這樣的屬性。
3) 在 Polymer 中,也有自定義 Mixins https://www.polymer-project.org/1.0/docs/devguide/styling
4) @import,但僅適用於非庫組件
所以,有幾種可能性,但都是有限的。 沒有像 ::shadow 那樣強大的外部造型方法。
我確實嘗試了很多方法,包括這里描述的方法。 由於我使用的是外部 Web 組件庫,因此我無權修改這些組件。 因此,對我querySelector
的唯一解決方案是使用 JS querySelector
,如下所示:
document.querySelector("the-element.with-shadow-dom")
.shadowRoot.querySelector(".some-selector").setAttribute("style", "color: black");
不是最好的解決方案,不適合大型樣式,但確實適用於小裝飾。
@John 這已經用 Chrome 83.0.4103.116 測試過(仍將在 Safari 中測試),我為 Ionic (v5) ion-toast
組件做了測試。 這是我使用的(幾乎)真實代碼:
import { toastController } from '@ionic/core';
let toastOpts = {
message: "Some message goes here.",
cssClass: "toast-with-vertical-buttons",
buttons: [
{
text: "Button 1",
side: 'end'
},
{
text: "Button2",
side: 'end'
},
{
icon: "close",
side: "start"
}
]
}
toastController.create(toastOpts).then(async p => {
let toast = await p.present(); // this renders ion-toast component and returns HTMLIonToastElement
toast.shadowRoot.querySelector('div.toast-button-group-end').setAttribute("style", "flex-direction: column");
});
仍然沒有簡單的方法可以刺穿陰影根部,但是您可以通過以下 3 種方法進行操作。 請記住,您需要在 Web 組件內部進行更改。
使用變量 v1 - 您將需要傳遞該屬性並在 Web 組件內使用該變量。
使用變量 v2 - 您將需要使用 Web 組件內的變量。
使用::part()
- 您需要將 part 屬性添加到要在 Web 組件中設置樣式的元素。 (注意:這個偽元素得到了很好的支持,但仍處於實驗模式,所以在生產中使用它之前請確保你知道這一點)。
運行下面的代碼示例以獲取詳細信息。
const elA = document.querySelector('custom-container-a'); const shadowRootA = elA.attachShadow({mode:'open'}); shadowRootA.innerHTML = '<style>:host([border]) {display:block;border: var(--custom-border);}</style>'+ '<p>Shadow content A</p>' const elB = document.querySelector('custom-container-b'); const shadowRootB = elB.attachShadow({mode:'open'}); shadowRootB.innerHTML = '<style>p {display:block;color: var(--custom-color, blue);}</style>'+ '<p>Shadow content B</p>' const elC = document.querySelector('custom-container-c'); const shadowRootC = elC.attachShadow({mode:'open'}); shadowRootC.innerHTML = '<p part="paragraph">Shadow content C</p>'
/* Normal way of styling */ p { color: orange; } /* Using variables version 1 */ custom-container-a { --custom-border: 3px solid gold; } /* Using variables version 2 */ custom-container-b { --custom-color: green; } /* Using ::part() NOTE: The specs for this hasn't been finalized. So it might not be a good idea to use in production. */ custom-container-c::part(paragraph) { color: magenta; }
<p>Light content</p> <custom-container-a border></custom-container-a> <custom-container-b></custom-container-b> <custom-container-c></custom-container-c>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.