How can I tell if an element is in a shadow DOM?
If you call a ShadowRoot's toString()
method, it will return "[object ShadowRoot]"
. According to this fact, here's my approach:
function isInShadow(node) { var parent = (node && node.parentNode); while(parent) { if(parent.toString() === "[object ShadowRoot]") { return true; } parent = parent.parentNode; } return false;}
EDIT
Jeremy Banks suggests an approach in another style of looping. This approach is a little different from mine: it also checks the passed node itself, which I didn't do.
function isInShadow(node) { for (; node; node = node.parentNode) { if (node.toString() === "[object ShadowRoot]") { return true; } } return false;}
You can check if an element has a shadow parent like this:
function hasShadowParent(element) { while(element.parentNode && (element = element.parentNode)){ if(element instanceof ShadowRoot){ return true; } } return false;}
This uses instanceof
over .toString()
.
⚠️ Warning: Deprecation Risk
The
::shadow
pseudo-element is deprecated in and being removed from from the dynamic selector profile. The approach below only requires that it remain in the static selector profile, but it may also be deprecated and removed there in the future. Discussions are ongoing.
We can use Element
's .matches()
method to determine if an element is attached to a shadow DOM.
If and only if the element is in a shadow DOM, we will be able to match it by using the selector :host
to identify elements that have a Shadow DOM, ::shadow
to look in those shadow DOMs, and *
and to match any descendant.
function isInShadow(element) { return element.matches(':host::shadow *');}