Using CSS ::part to Style SVG Sub-Elements
Web Components encapsulate their internal markup inside a Shadow DOM,
which inherently blocks external CSS stylesheets from modifying nested
SVG shapes. By utilizing the HTML part attribute on
internal SVG sub-elements (such as <path>,
<circle>, or <g>) and targeting
them with the CSS ::part() pseudo-element, developers can
selectively expose specific styling hooks to outside stylesheets while
maintaining DOM encapsulation.
The Problem: Shadow DOM Encapsulation and SVGs
When an SVG is embedded inside a Web Component’s Shadow Root, global
styles cannot pierce the shadow boundary to adjust SVG presentation
attributes like fill, stroke, or
opacity. Traditional solutions like CSS Custom Properties
(CSS variables) work for simple values, but they become cumbersome when
managing complex SVG layouts with multiple interactive or themeable
paths.
Exposing SVG
Elements with the part Attribute
To make an internal SVG sub-element stylable from outside the
component, assign a part attribute to the desired SVG tag
inside the Shadow DOM template.
Web Component Template Example
<my-icon>
#shadow-root (open)
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle part="background" cx="50" cy="50" r="45" />
<path part="glyph" d="M30 50 L45 65 L70 35" />
</svg>
</my-icon>In this component: - The <circle> element is
assigned part="background". - The <path>
element is assigned part="glyph".
Styling the Exposed Parts via External CSS
External stylesheets can target these exposed sub-elements directly
using the host selector combined with the ::part()
pseudo-element:
/* Style the SVG background circle */
my-icon::part(background) {
fill: #f0f4f8;
stroke: #0070f3;
stroke-width: 2px;
}
/* Style the inner glyph path */
my-icon::part(glyph) {
fill: none;
stroke: #0070f3;
stroke-width: 4px;
stroke-linecap: round;
}
/* Apply hover and state transitions externally */
my-icon:hover::part(background) {
fill: #0070f3;
}
my-icon:hover::part(glyph) {
stroke: #ffffff;
}Supported CSS Properties for SVG Parts
When targeting SVG elements through ::part(), all
standard SVG presentation attributes that map to CSS properties can be
manipulated, including:
- Fills & Strokes:
fill,fill-opacity,stroke,stroke-width,stroke-dasharray,stroke-dashoffset - Transforms & Geometry:
transform,transform-origin - Transitions & Animations:
transition,animation - Display & Visibility:
opacity,visibility,display
Nested Components and
exportparts
If an SVG is located within a nested Web Component inside another
Shadow DOM, you can forward the part to the outer context using the
exportparts attribute:
<!-- Outer Component Shadow DOM -->
<nested-icon exportparts="glyph: icon-glyph, background"></nested-icon>This allows the top-level document to access the internal SVG element
using outer-component::part(icon-glyph).
Benefits of Using
::part for SVGs
- Maintained Encapsulation: Internal structure and non-exposed elements remain fully protected from unwanted style overrides.
- Granular Theming: External developers can style distinct SVG layers without relying on complex SVG-in-CSS data URIs.
- Dynamic States: Pseudo-classes like
:hover,:active, and:focuson the host element can drive visual state changes across internal vector paths.