Deep Shadow DOM
This page renders a real Web Component tree, two shadow-root levels deep, mounted once via customElements.define. Level 1 uses an open shadow root; nested inside it, level 2 uses a closed shadow root. Each level keeps its own click counter that is only visible within that level's own shadow tree.
Shadow tree
Try in devtools: document.querySelector('tf-open-level').shadowRoot returns a real ShadowRoot. Its nested tf-closed-level element's .shadowRoot property returns null because it was attached with { mode: "closed" }.
Why this matters for automation
- Open shadow roots expose
element.shadowRoot, so tools like Playwright (which pierces shadow DOM by default in its locators) and Selenium 4'sgetShadowRoot()can query into them. - Closed shadow roots return
nullforelement.shadowRoot. There is no standards-based way to reach inside from outside the component's own JavaScript. Some tools work around this via CDP (Chrome DevTools Protocol) internals, but plain DOM APIs cannot.