CSS Parts in Shadow DOM — Complete Guide
DodaTech
Updated 2026-06-28
1 min read
In this tutorial, you will learn about CSS Parts in Shadow Dom. We cover key concepts, practical examples, and best practices to help you master this topic.
CSS parts expose internal shadow elements for external styling via the ::part() pseudo-element, enabling customization without breaking Encapsulation.
What You'll Learn
- How to define parts with the part attribute
- How to style parts with ::part()
- How to use exportparts for nested trees
- The difference between parts and custom properties
Why It Matters
Custom properties provide theming values, but sometimes you need to target specific elements. CSS parts give controlled access to internal elements.
flowchart LR A[Shadow Element] --> B[part=button] C[External CSS] --> D[::part(button)] D --> B B --> E[Styled but encapsulated]
Defining and Styling Parts
class PartDemo extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
.btn { display: inline-flex; align-items: center; gap: 4px; }
</style>
<button part="button" class="btn">
<span part="icon">\u2605</span>
<span part="label"><slot></slot></span>
</button>
`;
}
}
customElements.define('part-demo', PartDemo);
/* External styling */
part-demo::part(button) {
background: #3498db;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
part-demo::part(button):hover {
background: #2980b9;
}
part-demo::part(icon) {
font-size: 1.2em;
}
Exporting Parts from Nested Components
// Inner component defines parts
class InnerComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = '<div part="inner-box">Inner Content</div>';
}
}
customElements.define('inner-component', InnerComponent);
// Outer component exports inner parts
class OuterComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
// exportparts: "inner-box: outer-inner-box"
this.shadowRoot.innerHTML = `
<inner-component exportparts="inner-box: outer-inner-box"></inner-component>
`;
}
}
customElements.define('outer-component', OuterComponent);
// Usage: outer-component::part(outer-inner-box) { background: yellow; }
Common Mistakes
- Defining parts on elements that do not need external styling
- Not documenting available parts
- Forgetting to export nested parts with exportparts
Practice Questions
- What attribute exposes an element for styling? The
partattribute. - How do nested components expose parts? Using the
exportpartsattribute.
Mini Project
Create a modal component with parts for overlay, dialog, header, body, footer, close button, and title. Allow users to style each part. Document the parts.
What's Next
Lesson 10: Slot Change Events
← Previous
CSS Custom Properties in Shadow DOM — Complete Guide
Next →
Slot Change Events — Complete Guide
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro