JavaScript Node getRootNode() Method

Beginner
6 min read
Updated: Oct 2026
5 examples
Live preview
Baseline

What Is getRootNode()?

Node.getRootNode() returns the root of the tree that contains the node — usually the Document, or a ShadowRoot when the node lives in shadow DOM (MDN). An optional composed flag can cross the shadow boundary.

Baseline · Widely available: not Deprecated, Experimental, or Non-standard (since about January 2020).

Remember
node.getRootNode()
node.getRootNode({ composed: true })

in a normal page     → #document (HTMLDocument)
inside shadow DOM    → ShadowRoot  (default)
composed: true       → root beyond the shadow (often #document)
detached tree        → top node of that tree (may be itself)
UsePrefer
Page / light DOM rootnode.getRootNode()
Stay inside shadowdefault (composed: false)
Cross shadow boundarygetRootNode({ composed: true })

How to Use getRootNode()

Call it on any node; pass { composed: true } only when you need to escape a shadow tree.

  1. Call node.getRootNode() with no options for the default root.
  2. Inspect root.nodeName or compare with document / a ShadowRoot.
  3. For shadow children, default root is the ShadowRoot.
  4. Use { composed: true } to climb past the shadow root (often to the document).
PieceRequired?Role
Receiver nodeYesAny Node in a tree
options.composedNo (default false)Cross shadow boundary when true
Return value—A Node (Document, ShadowRoot, …)

Pseudocode

Pseudocode
function getRootNode(node, composed = false):
  walk toward parents / hosts
  if hit ShadowRoot and composed is false:
    return that ShadowRoot
  if composed is true:
    keep walking past the shadow host
  return the outermost root
    (#document, ShadowRoot, or detached top node)

Cheat Sheet

Keep these facts handy when resolving document vs shadow roots.

TopicDetail
Syntaxnode.getRootNode() · node.getRootNode(options)
Defaultcomposed: false
Page elementUsually #document
Shadow childDefault → ShadowRoot
composed: trueRoot beyond shadow (often document)
Detached topElement with no parent is its own root
vs ownerDocumentCreator document ≠ always current tree root
Status (MDN)Baseline Widely available

Live Preview

Compare document roots, detached trees, and shadow composed true/false (MDN-style demo).

Browser demo of Node.getRootNode() — Document, ShadowRoot, and composed.

Result
Loading…

JavaScript Examples

Short, copy-ready snippets. Open DevTools Console, or use Try It Yourself for a live editor.

Example 1 — Document Root

An element in the page usually roots at the document (MDN).

JavaScript
const child = document.querySelector(".child");
const root = child.getRootNode();
console.log(root.nodeName);      // #document
console.log(root === document);  // true
Try It Yourself

How It Works

  1. Call with no options. Default composed is false.
  2. Read nodeName. Documents report #document.
  3. Compare to document. Confirms the page root.
  4. Same for parent/child. Both light-DOM nodes share that document root.

Example 2 — Detached Tree Root

Unmounted trees root at their top node (MDN Example 3).

JavaScript
const element = document.createElement("p");
const child = document.createElement("span");
element.append(child);

const rootNode = child.getRootNode();
console.log(element === rootNode);           // true
console.log(element === element.getRootNode()); // true
Try It Yourself

How It Works

  1. Build a tiny tree. p parents span, not in the page yet.
  2. Child’s root is p. No document above it.
  3. Top node roots itself. No parent ⇒ that node is the root.
  4. Still has ownerDocument. Creator document ≠ this tree root.

Example 3 — Default Shadow Root

Inside shadow DOM, default getRootNode() returns the ShadowRoot.

JavaScript
const host = document.querySelector(".shadowHost");
const shadowRoot = host.attachShadow({ mode: "open" });
shadowRoot.innerHTML = '
shadowChild
'; const shadowChild = shadowRoot.querySelector(".shadowChild"); console.log(shadowChild.getRootNode() === shadowRoot); // true
Try It Yourself

How It Works

  1. Attach an open shadow. Creates a separate tree under the host.
  2. Query inside the shadow. shadowChild lives there.
  3. Default stops at ShadowRoot. composed is false.
  4. Identity check. Same object as attachShadow returned.

Example 4 — composed: true

Cross the shadow boundary to reach the document (MDN).

JavaScript
const host = document.querySelector(".shadowHost");
const shadowRoot = host.attachShadow({ mode: "open" });
shadowRoot.innerHTML = '
shadowChild
'; const shadowChild = shadowRoot.querySelector(".shadowChild"); console.log( shadowChild.getRootNode({ composed: true }).nodeName ); // #document
Try It Yourself

How It Works

  1. Pass { composed: true }. Opt into crossing the boundary.
  2. Climb past the host. Continues into the light DOM.
  3. Often lands on the document. When the host is in the page.
  4. Use when you need the “outer” root. Keep default for shadow-local logic.

Example 5 — vs ownerDocument

Creator document and current tree root are different ideas.

JavaScript
const p = document.createElement("p");
const span = document.createElement("span");
p.append(span);

console.log(span.ownerDocument === document); // true
console.log(span.getRootNode() === p);        // true
console.log(span.getRootNode() === document); // false
Try It Yourself

How It Works

  1. ownerDocument. Document that created the node.
  2. getRootNode(). Top of the tree the node is in now.
  3. Detached case. Root is p, not document.
  4. Pick the right API. Creation vs current tree membership.

Edge Cases & Pitfalls

Check these before assuming every root is document.

shadow

Default stops at ShadowRoot

Forgetting composed: true is the usual surprise when you expected the document.

detached

Detached roots are not documents

An unmounted top element is its own root until you append it into the page.

owner

Not the same as ownerDocument

Creation document vs current tree root — use the API that matches your question.

closed

Closed shadow mode

You still get a ShadowRoot from inside; outside scripts may not hold a reference when mode is closed.

Browser Support

Node.getRootNode() is Baseline Widely available (MDN, since about January 2020). Safe for modern shadow-aware DOM code.

✓ Baseline · Widely available

Node.getRootNode()

Supported in modern Chrome, Firefox, Safari, Edge, and Opera. Includes the composed option for shadow trees.

96% Modern browser support
Google Chrome getRootNode() · composed
Full support
Microsoft Edge getRootNode() · Chromium
Full support
Apple Safari getRootNode() · modern versions
Full support
Mozilla Firefox getRootNode() · modern versions
Full support
Opera getRootNode() · modern versions
Full support
Internet Explorer No getRootNode()
Unavailable
Node.getRootNode() Excellent

Bottom line: Use freely in modern apps. Prefer composed: true only when you intentionally need the outer root.

Performance Notes

ApproachCostBest for
getRootNode() onceCheapEvent / setup checks
Manual parent walkMore codeRarely better
Call every frameWastefulAvoid — cache when the tree is stable

Resolve the root when the tree changes (attach, move, open shadow) — not in a tight animation loop.

Key Takeaways

  • Role: return the root of the node’s current tree.
  • Default: Document in the page; ShadowRoot inside shadow.
  • composed: true: climb past the shadow root.
  • Detached: top node with no parent is its own root.

One line: getRootNode() finds where a node’s tree starts — document, shadow root, or a detached top.

Frequently Asked Questions

The root of the tree that contains the node — typically the Document for page nodes, a ShadowRoot inside shadow DOM (by default), or the top node of a detached tree (MDN).
No. MDN marks it Baseline Widely available (since about January 2020). It is not Deprecated, Experimental, or Non-standard.
composed: false (default) stops at a shadow root. composed: true crosses the shadow boundary and returns a root beyond it (often the document).
An HTMLDocument for the page (nodeName is often #document).
It returns the root of that DOM tree. If an element has no parent, that element is its own root (MDN Example 3).
ownerDocument is the Document that created the node. getRootNode walks to the current tree root, which may be a ShadowRoot or a detached fragment root.

Next: hasChildNodes()

Learn how node.hasChildNodes() reports whether a node has children.

hasChildNodes tutorial →

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.

10 people found this page helpful