CSS Parts — Complete Guide
In this tutorial, you will learn about CSS Parts. We cover key concepts, practical examples, and best practices to help you master this topic.
CSS parts expose specific Shadow Dom elements for external styling, giving users controlled access to internal component elements without breaking Encapsulation.
What You'll Learn
- How to expose shadow elements with the part attribute
- How to style exposed parts with ::part()
- How to use part hierarchies with ::part()
- How part theming differs from CSS custom properties
Why It Matters
CSS custom properties are great for theming values, but they cannot target specific elements. CSS parts let users style the component's internal elements directly, like changing the icon size or the button padding.
flowchart LR A[Component] --> B[part=button] A --> C[part=icon] A --> D[part=label] E[External CSS] --> F[::part(button)] E --> G[::part(icon)]
Defining Parts
class SplitButton extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
.container { display: inline-flex; border-radius: 4px; overflow: hidden; }
.main-btn { padding: 8px 16px; background: #3498db; color: white; border: none; cursor: pointer; }
.toggle-btn { padding: 8px 12px; background: #2980b9; color: white; border: none; cursor: pointer; border-left: 1px solid rgba(255,255,255,0.3); }
</style>
<div class="container">
<button part="main-button" class="main-btn"><slot></slot></button>
<button part="toggle-button" class="toggle-btn">\u25BC</button>
</div>
`;
}
}
customElements.define('split-button', SplitButton);
Styling Parts
/* External CSS */
split-button::part(main-button) {
background: #e74c3c;
font-weight: bold;
text-transform: uppercase;
}
split-button::part(toggle-button) {
background: #c0392b;
font-size: 10px;
}
split-button::part(main-button):hover {
background: #c0392b;
}
Part Hierarchies
class NestedPanel extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<my-card exportparts="header: card-header, body: card-body">
<span slot="header">Panel Title</span>
<p>Panel content</p>
</my-card>
`;
}
}
customElements.define('nested-panel', NestedPanel);
Common Mistakes
- Exposing too many parts (breaks encapsulation)
- Not documenting available parts for users
- Using part names that conflict with other components
Practice Questions
- What attribute exposes an element for styling? The
partattribute. - How do nested components expose parts? Using the
exportpartsattribute.
Mini Project
Build a modal component with exposed parts for overlay, container, header, body, footer, and close button. Allow users to style each part independently.
What's Next
Lesson 13: CSS Theming
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro