JavaScript Element shadowRoot Property

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Baseline
Instance property

What You’ll Learn

Element.shadowRoot is a read-only instance property that returns the open ShadowRoot hosted by an element, or null when no accessible shadow tree exists. Learn open vs closed mode, how it pairs with attachShadow(), and how to query inside a shadow tree—with five examples and try-it labs.

01

Kind

Instance property

02

Access

Read-only

03

Type

ShadowRoot or null

04

Open mode

Accessible via property

05

Closed mode

Returns null

06

Status

Baseline widely

Introduction

Shadow DOM lets an element host a private DOM tree. That tree is rooted at a ShadowRoot. After you attach an open shadow root with attachShadow(), you can reach it later with element.shadowRoot.

If the shadow root was attached as closed, shadowRoot stays null. That is the main beginner rule for this property.

JavaScript
const host = document.createElement("div");
host.attachShadow({ mode: "open" });
console.log(host.shadowRoot); // ShadowRoot
💡
Beginner tip

Prefer mode: "open" unless you have a strong reason for closed encapsulation. Open mode is easier to debug and style from outside.

Understanding the Property

MDN: the read-only shadowRoot property represents the shadow root hosted by the element. Use Element.attachShadow() to add a shadow root to an existing element.

  • Read-only — create shadow trees with attachShadow(), not assignment.
  • ShadowRoot or null — null means no accessible shadow root.
  • Open mode only — closed roots do not appear on this property.
  • Built-ins may be closed — some browser controls keep shadowRoot null.

📝 Syntax

JavaScript
element.shadowRoot

Value

A ShadowRoot object instance, or null if there is no open shadow root.

ItemDetail
TypeShadowRoot or null
AccessRead-only property
Created byattachShadow({ mode })
OpenshadowRoot returns the tree
ClosedshadowRoot is null
⚠️
Null safety

Always check for null before calling methods like querySelector() on element.shadowRoot.

📋 Open vs Closed Pattern

MDN’s core idea: open roots are readable through shadowRoot; closed roots are not.

JavaScript
const openHost = document.createElement("div");
openHost.attachShadow({ mode: "open" });
console.log(openHost.shadowRoot); // ShadowRoot

const closedHost = document.createElement("div");
closedHost.attachShadow({ mode: "closed" });
console.log(closedHost.shadowRoot); // null

Related learning: attachShadow(), ShadowRoot.mode, and part for styling shadow internals.

⚡ Quick Reference

GoalCode / note
Attach open shadowel.attachShadow({ mode: "open" })
Read shadow rootel.shadowRoot
Query insideel.shadowRoot.querySelector(".x")
Closed rootel.shadowRoot === null
Keep closed referenceStore return value of attachShadow()
MDN statusBaseline Widely available

🔍 At a Glance

Four facts about Element.shadowRoot.

Kind
get only

Instance

Type
ShadowRoot|null

Or null

Open
accessible

Via property

Baseline
widely

Shadow DOM

Examples Gallery

Examples follow MDN Element: shadowRoot and show how open and closed modes affect the property.

📚 Getting Started

Start with a normal element that has no shadow root.

Example 1 — No Shadow Root Yet

A plain element returns null until you attach a shadow tree.

JavaScript
const host = document.createElement("div");
console.log(host.shadowRoot); // null
Try It Yourself

How It Works

shadowRoot only appears after an open shadow tree is attached.

📈 Open, Closed & Query

Compare modes and reach into an open shadow tree.

Example 2 — Open Mode Returns ShadowRoot

Attach with mode: "open" and read the property.

JavaScript
const host = document.createElement("div");
host.attachShadow({ mode: "open" });
console.log(host.shadowRoot.mode); // "open"
Try It Yourself

How It Works

Open encapsulation keeps the shadow root reachable from outside JavaScript.

Example 3 — Closed Mode Returns null

Closed mode hides the tree from element.shadowRoot.

JavaScript
const host = document.createElement("div");
const root = host.attachShadow({ mode: "closed" });
console.log(host.shadowRoot); // null
console.log(root.mode);       // "closed"
Try It Yourself

How It Works

Keep the return value of attachShadow() if you still need access inside your component.

Example 4 — Query Inside an Open Shadow Root

Use shadowRoot like a document fragment to find nodes.

JavaScript
const host = document.createElement("div");
host.attachShadow({ mode: "open" });
host.shadowRoot.innerHTML = "Hello";
console.log(host.shadowRoot.querySelector(".label").textContent);
Try It Yourself

How It Works

Once you have the open ShadowRoot, you can query, update, and style nodes inside it.

Example 5 — Support Snapshot

Feature-detect and remember the open/closed rule.

JavaScript
console.log({
  supported: "shadowRoot" in Element.prototype,
  returns: "ShadowRoot or null",
  tip: "Closed mode makes shadowRoot null",
  status: "Baseline Widely available (MDN)"
});
Try It Yourself

How It Works

Safe to use widely. It is the main read path into open shadow trees from outside.

🚀 Common Use Cases

  • Reading markup inside a custom element’s open shadow tree.
  • Updating shadow content after attachShadow({ mode: "open" }).
  • Checking whether a host currently exposes an accessible shadow root.
  • Debugging web components from outside the component class.
  • Pairing with part and ::part() for external styling of shadow pieces.

🔧 How It Works

1

You attach a shadow tree

attachShadow() creates a ShadowRoot on the host.

Create
2

Mode decides access

Open roots are public; closed roots stay hidden.

Mode
3

shadowRoot reads the open tree

Returns ShadowRoot or null.

Read
4

You can query and update internals

Open mode enables outside access for components and tooling.

📝 Notes

  • Not Deprecated, Experimental, or Non-standard on MDN (Baseline Widely available).
  • Returns null for closed shadow roots and for some built-in closed UA shadow trees.
  • Do not assign to element.shadowRoot; use attachShadow().
  • Related: attachShadow(), slot, part, JavaScript hub.

Browser Support

Element.shadowRoot is Baseline Widely available (MDN). Logos use the shared browser-image-sprite.png sprite from this project.

Baseline Widely available

Element.shadowRoot

Read-only — returns an open ShadowRoot or null for closed / missing trees.

Baseline Widely available
Google Chrome Supported
Yes
Microsoft Edge Supported
Yes
Mozilla Firefox Supported
Yes
Apple Safari Supported
Yes
Opera Supported
Yes
Internet Explorer Not supported
No
shadowRoot Baseline

Bottom line: Use shadowRoot to access open shadow trees. Prefer mode: "open" unless you intentionally want closed encapsulation.

Conclusion

shadowRoot is the read path into an element’s open Shadow DOM. It returns a ShadowRoot for open trees and null for closed or missing ones.

Continue with slot, part, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Prefer mode: "open" for most components
  • Null-check shadowRoot before querying
  • Use attachShadow() to create the tree
  • Store the return value if you use closed mode
  • Keep shadow internals intentional and documented

❌ Don’t

  • Assign el.shadowRoot = ... (read-only)
  • Assume closed roots are still readable via the property
  • Skip null checks in outside tooling code
  • Expect built-in controls like some form widgets to expose their UA shadow trees
  • Overuse closed mode without a clear encapsulation need

Key Takeaways

Knowledge Unlocked

Five things to remember about shadowRoot

Read-only access to open Shadow DOM trees, or null when closed/missing.

5
Core concepts
📝02

ShadowRoot|null

open access

Type
🔍03

Closed = null

key rule

Mode
04

Baseline

widely available

Status
🎯05

Prefer open

for most apps

Tip

❓ Frequently Asked Questions

It returns the ShadowRoot hosted by the element when the shadow tree was attached in open mode, or null when there is no accessible shadow root.
No. MDN marks Element.shadowRoot as Baseline Widely available. It is not Deprecated, Experimental, or Non-standard.
It returns null when the element has no shadow root, when the shadow root was attached with mode: "closed", or for some built-in elements that use closed user-agent shadow roots.
Call element.attachShadow({ mode: "open" }) or { mode: "closed" }. For open mode, element.shadowRoot then gives you the ShadowRoot.
No. It is read-only. You attach a shadow root with attachShadow(); you do not assign to shadowRoot.
Not through element.shadowRoot — that stays null. Keep the ShadowRoot returned by attachShadow() if you need internal access.
Did you know?

Some built-in elements, such as <input> and <textarea>, use closed user-agent shadow roots, so their shadowRoot property stays null even though a shadow tree exists internally.

Previous: scrollWidth

Learn how Element.scrollWidth measures full content width including overflow.

← scrollWidth

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful