Skip to content
tezvyn:

CSS ::part(): Style Inside a Web Component's Shadow DOM

Source: developer.mozilla.orgMediumHow cards are made

CSS ::part(): Style Inside a Web Component's Shadow DOM

The ::part() pseudo-element lets you style specific elements inside a web component's Shadow DOM. It's a contract allowing consumers to theme designated "parts" of a component without breaking encapsulation. The main footgun: it only styles one level deep.

Why it exists

Web Components use the Shadow DOM to encapsulate their internal structure and styles, preventing them from leaking out or being affected by global CSS. But this creates a problem: what if you want to let users customize a button color or a font size? ::part() was created to solve this, providing a controlled API for styling encapsulated elements without breaking the component's integrity.

The mental model

Think of a web component as a black box. The part attribute is the component author labeling specific dials and switches on the outside of that box. The ::part() pseudo-element is how you, the consumer of the component, can turn those specific dials from your own stylesheet. You can't rewire the internals, only adjust the exposed controls.

How it works

An element inside a component's Shadow DOM is given a part attribute, like . In your main stylesheet, you can then target this element using the component's tag and the ::part() pseudo-element: my-component::part(header) { background-color: blue; }. An element can have multiple part names (e.g., part="tab active"), which you can target together like ::part(tab active). You can chain state pseudo-classes like :hover but not structural ones like :last-child.

When to use it

Use ::part() when you are building or consuming web components and need a theming strategy. It's the standard way for a component author to offer specific styling hooks to consumers without compromising the component's internal encapsulation. It's perfect for letting users tweak colors, fonts, and spacing on designated elements.

When not to use it

Don't use it to try and style arbitrary elements inside a component that haven't been exposed with a part attribute; it won't work. Also, recognize its primary limitation: ::part() only works one level deep. To style a part within a nested shadow tree, the intermediate component must explicitly forward it using the exportparts attribute. If you need to style everything, Shadow DOM might be the wrong tool for that component instance.

One canonical example

A custom <tab-control> component might have several elements for its tabs inside its Shadow DOM. The author can add part="tab" to each one. A user can then style all tabs with tab-control::part(tab) { ... }. If the author also adds an active state, like part="tab active", the user can style the active tab differently with tab-control::part(tab active) { ... }.

Interview question

What is a primary limitation of using the CSS ::part() pseudo-element for styling web components?

  • a.It only allows styling elements that are directly exposed by the component author, not arbitrary internal elements.
  • b.It prevents the use of state pseudo-classes like :hover on the targeted elements.
  • c.It compromises the encapsulation of the Shadow DOM, allowing external styles to leak into the component.
  • d.It can only apply styles to elements one level deep within the Shadow DOM.Correct
Why?

The card explicitly states, "recognize its primary limitation: ::part() only works one level deep." While it's true that ::part() only targets elements exposed by the component author (option A), the text highlights the "one level deep" constraint as its primary limitation, especially when dealing with nested shadow trees.

Just read this? Test yourself on what you have been reading.

Read the original → developer.mozilla.org

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on css — each one lists the topics its interview covers.

See open roles