Introduction
Some modern web applications use Nested Shadow DOM, where one Shadow DOM contains another Shadow Host with its own Shadow Root. This creates multiple levels of encapsulation, making element access more complex than a single Shadow DOM.
To interact with elements inside a Nested Shadow DOM, Selenium (or JavaScript) must traverse each Shadow Root one level at a time until it reaches the desired element.
In this tutorial, you’ll learn what Nested Shadow DOM is, how Selenium handles it, and how to automate nested Shadow DOM elements using Selenium with Python.
What is Nested Shadow DOM?
A Nested Shadow DOM exists when one Shadow Root contains another Shadow Host.
Example:
HTML Document
│
└── Outer Shadow Host
│
└── Outer Shadow Root
│
└── Inner Shadow Host
│
└── Inner Shadow Root
│
└── Target Element
To reach the target element, Selenium must pass through both Shadow Roots.
Why Use Nested Shadow DOM?
Developers use Nested Shadow DOM to:
Build complex reusable components.
Encapsulate multiple UI layers.
Prevent style conflicts.
Improve modularity.
Organize large component-based applications.
Why is Nested Shadow DOM Challenging?
Unlike normal HTML elements, Selenium cannot directly locate elements inside multiple Shadow Roots.
The automation script must:
Locate the outer Shadow Host.
Access its Shadow Root.
Locate the inner Shadow Host.
Access its Shadow Root.
Locate the target element.
Example
from selenium import webdriver
# Topic: 31. Modern Web Elements - Nested Shadow DOM
# Practice site: https://www.testmuai.com/selenium-playground/
# Run: pytest -s 31_examples/test_04_nested_shadow_dom.py
#
# Nested shadow DOM means a shadow root contains another shadow host. This
# example creates a small nested shadow DOM demo on the practice page.
def test_nested_shadow_dom_text():
driver = webdriver.Chrome()
try:
driver.get("https://www.testmuai.com/selenium-playground/")
driver.execute_script(
"""
const outerHost = document.createElement('div');
outerHost.id = 'outer-host';
document.body.appendChild(outerHost);
const outerRoot = outerHost.attachShadow({ mode: 'open' });
const innerHost = document.createElement('section');
innerHost.id = 'inner-host';
outerRoot.appendChild(innerHost);
const innerRoot = innerHost.attachShadow({ mode: 'open' });
const message = document.createElement('p');
message.id = 'message';
message.textContent = 'Nested shadow DOM is ready';
innerRoot.appendChild(message);
"""
)
nested_text = driver.execute_script(
"""
return document
.querySelector('#outer-host').shadowRoot
.querySelector('#inner-host').shadowRoot
.querySelector('#message').textContent;
"""
)
assert nested_text == "Nested shadow DOM is ready"
finally:
driver.quit()
Understanding the Code
Import Required Library
from selenium import webdriver
Imports the Selenium WebDriver module required to launch the browser.
Create a Chrome Browser Instance
driver = webdriver.Chrome()
Starts a new Chrome browser session.
Open the Practice Website
driver.get("https://www.testmuai.com/selenium-playground/")
Navigates to the Selenium Playground website.
Create a Nested Shadow DOM Structure
driver.execute_script(
"""
...
"""
)
This JavaScript creates a demonstration of a Nested Shadow DOM by:
Creating an outer Shadow Host.
Attaching an outer Shadow Root.
Creating an inner Shadow Host inside the outer Shadow Root.
Attaching an inner Shadow Root.
Creating a paragraph element containing the text “Nested shadow DOM is ready”.
This provides a sample nested Shadow DOM structure for testing.
Read the Nested Shadow DOM Text
nested_text = driver.execute_script(
"""
return document
.querySelector('#outer-host').shadowRoot
.querySelector('#inner-host').shadowRoot
.querySelector('#message').textContent;
"""
)
This JavaScript accesses each level one at a time:
Finds the outer Shadow Host.
Opens the outer Shadow Root.
Finds the inner Shadow Host.
Opens the inner Shadow Root.
Locates the paragraph element.
Retrieves its text content.
This demonstrates how Nested Shadow DOM must be traversed level by level.
Verify the Retrieved Text
assert nested_text == "Nested shadow DOM is ready"
Verifies that the retrieved text exactly matches the expected value.
If the text is different, the test fails.
Close the Browser
driver.quit()
Closes the browser and ends the WebDriver session.
Practical Example
Suppose an enterprise dashboard uses multiple nested Web Components for displaying analytics.
The automation script:
Opens the dashboard.
Traverses each Shadow Root.
Retrieves the displayed statistics.
Verifies the reported values.
Automation Testing Example
Consider a banking application built using reusable Web Components.
The account information is displayed inside multiple nested Shadow DOM components.
The automation script:
Opens the dashboard.
Traverses each Shadow Root.
Reads the account balance.
Verifies the displayed information.
Real-World Example
Nested Shadow DOM is commonly used in:
Material Design applications
Enterprise dashboards
Banking applications
Salesforce applications
Google applications
Modern JavaScript frameworks
Component libraries
Examples include reusable cards, navigation menus, profile panels, dashboards, and custom UI controls.
Advantages of Automating Nested Shadow DOM
Supports complex Web Components.
Tests deeply nested user interfaces.
Verifies encapsulated components.
Improves automation coverage.
Supports modern enterprise applications.
Common Mistakes Beginners Make
Trying to Access the Final Element Directly
Elements inside Nested Shadow DOM cannot be accessed directly.
You must traverse each Shadow Root individually.
Forgetting One Shadow Root
Skipping a Shadow Root usually prevents Selenium from locating the desired element.
Always follow the hierarchy.
Assuming Shadow DOM Works Like Normal HTML
Shadow DOM creates isolated DOM trees.
Each level must be accessed separately.
Ignoring the Component Structure
Inspect the page carefully to identify the complete Shadow DOM hierarchy before writing automation.
Best Practices
Inspect the Shadow DOM hierarchy using browser Developer Tools.
Traverse one Shadow Root at a time.
Verify each level before moving deeper.
Use Selenium 4 Shadow DOM support or JavaScript where appropriate.
Keep Shadow DOM traversal code readable and well organized.
Conclusion
Nested Shadow DOM extends the concept of Shadow DOM by allowing multiple Shadow Roots to exist within one another. Selenium must navigate through each Shadow Host and Shadow Root individually before interacting with the target element. Understanding Nested Shadow DOM is essential for automating modern component-based applications that use deeply nested Web Components.
Frequently Asked Questions (FAQs)
What is Nested Shadow DOM?
Nested Shadow DOM occurs when one Shadow Root contains another Shadow Host with its own Shadow Root.
Why is Nested Shadow DOM more difficult to automate?
Because Selenium must traverse multiple Shadow Roots before reaching the target element.
Can Selenium access Nested Shadow DOM?
Yes.
Selenium 4 and JavaScript can access Nested Shadow DOM by navigating through each Shadow Root individually.
Why does this example create the Shadow DOM using JavaScript?
The practice page does not already contain a nested Shadow DOM example, so the script creates one dynamically to demonstrate how Selenium can work with nested Shadow Roots.
Where is Nested Shadow DOM commonly used?
Nested Shadow DOM is commonly used in enterprise dashboards, Material Design applications, Web Component libraries, banking systems, Salesforce applications, and modern JavaScript frameworks.
Key Takeaways
Nested Shadow DOM contains multiple Shadow Roots.
Selenium must traverse each Shadow Root one level at a time.
Standard locators cannot directly reach deeply nested Shadow DOM elements.
JavaScript or Selenium 4 Shadow DOM support can be used to access nested components.
Understanding the Shadow DOM hierarchy is essential for reliable automation.
Nested Shadow DOM is widely used in modern component-based web applications.
