JavaScript Element part Property

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

What You’ll Learn

Element.part is a read-only instance property that returns a DOMTokenList of CSS part identifiers. These names let external stylesheets reach into shadow DOM via the ::part() pseudo-element. Learn how to read, add, remove, and toggle parts—with five examples and try-it labs.

01

Kind

Instance property

02

Access

Read-only (object)

03

Type

DOMTokenList

04

Reflects

part attribute

05

Status

Baseline widely

06

Used with

::part() CSS

Introduction

Shadow DOM encapsulates styles, but sometimes the component author wants to let outside CSS customize specific pieces. That is where CSS Shadow Parts come in: add a part attribute to an element inside a shadow tree, and external selectors like my-elem::part(heading) can style it.

The Element.part property exposes those identifiers as a DOMTokenList, similar to classList. You can read, add, remove, replace, or toggle part names programmatically.

JavaScript
const el = this.shadowRoot.querySelector(".tab");
console.log(el.part);       // DOMTokenList ["tab"]
el.part.add("active");      // now "tab active"
el.part = "tab selected";   // shorthand assignment
💡
Beginner tip

Think of part like classList, but for exposing shadow internals to the page’s CSS via ::part().

Understanding the Property

MDN: the read-only part property of the Element interface contains a DOMTokenList object representing the part identifier(s) of the element. It reflects the element’s part content attribute. These can be used to style parts of a shadow DOM via the ::part pseudo-element.

  • Read-only object — you cannot replace the DOMTokenList, but you can mutate it or assign a string to el.part.
  • Reflects attribute — mirrors the HTML part attribute.
  • Empty by defaultlength === 0 when no part attribute is set.
  • Baseline — widely available since July 2020 (MDN).

📝 Syntax

JavaScript
element.part

Value

A DOMTokenList object. If the part attribute is not set or empty, the returned list has length === 0.

ItemDetail
TypeDOMTokenList
AccessRead-only (object), but list is mutable
ReflectsHTML part attribute
CSS companion::part(name) pseudo-element
💡
Assignment shorthand

You can write el.part = "tab active" instead of calling add() / remove(). This replaces the entire list.

📋 MDN Shadow Parts Example Shape

MDN’s shadow-part example finds elements with a part attribute, then toggles part identifiers on click:

JavaScript
const tabs = [];
const children = this.shadowRoot.children;

for (const elem of children) {
  if (elem.getAttribute("part")) {
    tabs.push(elem);
  }
}

tabs.forEach((tab) => {
  tab.addEventListener("click", (e) => {
    tabs.forEach((t) => { t.part = "tab"; });
    e.target.part = "tab active";
  });
  console.log(tab.part);
});

Related learning: ::part(), exportparts, and innerHTML.

⚡ Quick Reference

GoalCode / note
Read partsel.part → DOMTokenList
Add a partel.part.add("active")
Remove a partel.part.remove("active")
Toggleel.part.toggle("active")
Replace allel.part = "tab selected"
CSS usagemy-elem::part(tab) { color: blue; }

🔍 At a Glance

Four facts about Element.part.

Kind
read-only

Instance

Type
DOMTokenList

Like classList

CSS hook
::part()

Shadow styling

Baseline
widely

Jul 2020+

Examples Gallery

Examples follow MDN Element: part. Labs use inline shadow DOM so you can experiment safely.

📚 Getting Started

Read part names and mutate the list.

Example 1 — Read Part Names

Log the DOMTokenList returned by part.

JavaScript
const el = document.querySelector("[part]");
console.log(el.part);          // DOMTokenList
console.log(el.part.length);   // number of parts
console.log(el.part.value);    // space-separated string
Try It Yourself

How It Works

The getter returns a live DOMTokenList reflecting the part attribute. Each space-separated token is a part name.

Example 2 — Add & Remove Parts

Use add() and remove() to change part names at runtime.

JavaScript
const el = document.querySelector("[part='tab']");
el.part.add("active");
console.log(el.part.value); // "tab active"
el.part.remove("active");
console.log(el.part.value); // "tab"
Try It Yourself

How It Works

Just like classList, calling add() appends a token and remove() strips one. The underlying part attribute updates automatically.

📈 Toggle & Tab Switching

Practical patterns from MDN’s shadow-part example.

Example 3 — Toggle a Part

Switch a part name on and off with toggle().

JavaScript
const el = document.querySelector("[part='tab']");
el.part.toggle("active");
console.log(el.part.contains("active")); // true
el.part.toggle("active");
console.log(el.part.contains("active")); // false
Try It Yourself

How It Works

toggle() adds the token if missing or removes it if present, then returns a boolean indicating whether the token is now in the list.

Example 4 — MDN Tab Switch Pattern

Reset all tabs to "tab", then mark the clicked one as "tab active".

JavaScript
const tabs = this.shadowRoot.querySelectorAll("[part]");
tabs.forEach((tab) => {
  tab.addEventListener("click", (e) => {
    tabs.forEach((t) => { t.part = "tab"; });
    e.target.part = "tab active";
  });
});
Try It Yourself

How It Works

Assigning a string to el.part replaces all tokens at once. The outer CSS rule my-tabs::part(active) { font-weight: bold; } instantly highlights the active tab.

Example 5 — Support Snapshot

Feature-detect part and review key facts.

JavaScript
console.log({
  supported: "part" in Element.prototype,
  returns: "DOMTokenList (like classList)",
  cssHook: "::part(name)",
  status: "Baseline Widely available (MDN)"
});
Try It Yourself

How It Works

Widely supported since 2020. If you target older browsers, check "part" in Element.prototype before using it.

🚀 Common Use Cases

  • Theming a web component’s internals from the host page CSS.
  • Toggling active / selected states on shadow-DOM tabs or navigation items.
  • Exposing specific inner elements for consumer customization without breaking encapsulation.
  • Building design-system components that ship default styles but allow overrides via ::part().
  • Combining with exportparts to re-export parts from nested shadow trees.

🔧 How It Works

1

Author adds part attribute

Elements inside a shadow tree get part="name".

HTML
2

el.part reflects the attribute

Returns a live DOMTokenList you can read or mutate.

JS
3

External CSS uses ::part(name)

Selects the inner element from outside the shadow boundary.

CSS
4

Shadow part is styled

Encapsulation preserved; only named parts are exposed.

📝 Notes

  • Not Deprecated, Experimental, or Non-standard on MDN (Baseline Widely available since July 2020).
  • The property itself is read-only, but you can assign a string to el.part (sets value) or call add(), remove(), toggle(), replace().
  • ::part() does not pierce nested shadow boundaries. Use exportparts on intermediate hosts to re-export inner parts.
  • Setting part on regular (non-shadow) elements has no CSS effect; ::part() only works across shadow boundaries.
  • Related: outerHTML, innerHTML, prefix, JavaScript hub.

Browser Support

Element.part is Baseline Widely available (MDN: across browsers since July 2020). Logos use the shared browser-image-sprite.png sprite from this project.

Baseline Widely available

Element.part

Read-only — DOMTokenList of CSS shadow part identifiers; styled externally via ::part().

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
part Baseline

Bottom line: Use Element.part to expose shadow DOM internals for external CSS theming via the ::part() pseudo-element.

Conclusion

Element.part returns a DOMTokenList of CSS part identifiers that let external stylesheets reach into shadow DOM via ::part(). Use it to build customizable web components without sacrificing encapsulation.

Continue with prefix, outerHTML, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Use descriptive part names (heading, body, icon)
  • Document which parts your component exposes
  • Use exportparts for nested shadow trees
  • Combine part with classList for internal + external styling
  • Feature-detect before relying on part in legacy environments

❌ Don’t

  • Expose every internal element as a part (breaks encapsulation)
  • Rely on part for non-shadow-DOM elements (no CSS effect)
  • Expect ::part() to pierce nested shadows without exportparts
  • Use generic names like div1 or span2
  • Forget that IE does not support this property

Key Takeaways

Knowledge Unlocked

Five things to remember about part

DOMTokenList of CSS shadow part names—style internals from outside.

5
Core concepts
📝 02

DOMTokenList

like classList

Type
🔍 03

::part()

CSS companion

Use
04

Baseline

widely available

Status
🎯 05

Shadow only

no effect outside

Tip

❓ Frequently Asked Questions

It returns a read-only DOMTokenList of the element's CSS part identifiers (reflecting the part HTML attribute). These names let external CSS style shadow DOM internals via the ::part() pseudo-element.
No. MDN marks Element.part as Baseline Widely available (since July 2020). It is not Deprecated, Experimental, or Non-standard.
Yes. Although the property itself is read-only (you cannot replace the DOMTokenList object), you can call add(), remove(), replace(), and toggle() on it, or assign a string directly to el.part which sets its value.
It is a CSS pseudo-element that selects elements inside a shadow tree which have been exposed via the part attribute. For example, my-element::part(tab) targets elements with part="tab" inside my-element's shadow DOM.
You can set a part attribute on any element, but ::part() styling only works across shadow boundaries. On regular elements the attribute has no visual effect.
The part attribute names parts on direct shadow children. The exportparts attribute on the shadow host re-exports part names from nested shadow trees so outer CSS can reach them.
Did you know?

::part() deliberately does not match descendant parts in nested shadow trees. The exportparts attribute lets intermediate hosts forward inner part names outward, keeping the API surface explicit and intentional.

Next: prefix

Learn how Element.prefix reads the namespace alias of an XML element.

prefix →

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