This content originally appeared on Go Make Things and was authored by Go Make Things
For the last week, we’ve been looking at why styling elements in the shadow DOM sucks so bad, and what to do about it.
So far, we’ve looked at using inline styles, external stylesheets, and CSS variables.
Today, let’s talk about parts!
Our example element
Just to recap, we have a <count-up>
element, like this…
<count-up></count-up>
Which, when the Web Component JavaScript loads, renders HTML like this…
<count-up>
#shadow-root (closed)
<button>Clicked 0 Times</button>
</count-up>
And it’s styled using inline CSS and CSS variables like this…
// Inject the HTML into the shadow DOM
this.root.innerHTML =
`<style>
button {
background-color: var(--bg-color, rebeccapurple);
border: var(--border, 0);
border-radius: var(--border-radius, 0.25em);
color: var(--color, white);
font-family: var(--font, 'PT Serif', sans-serif);
font-size: var(--font-size, 1.2em);
padding: var(--padding, 0.25em 0.5em);
}
</style>
<button>Clicked ${this.count} Times</button>`;
This can be a great approach, but it does require you to specify CSS variables for every aspect of each element that can by styled.
Let’s look at another way you can provide external access to style shadow DOM elements that’s a bit more flexible.
The [part]
attribute
The [part]
attribute on web component elements in the Shadow DOM acts like a class that users can hook into to style elements in the Shadow DOM.
Here, I’ve given the button
a [part]
attribute with a value of btn
.
// Inject the HTML into the shadow DOM
this.root.innerHTML =
`<style>
button {
background-color: var(--bg-color, rebeccapurple);
border: var(--border, 0);
border-radius: var(--border-radius, 0.25em);
color: var(--color, white);
font-family: var(--font, 'PT Serif', sans-serif);
font-size: var(--font-size, 1.2em);
padding: var(--padding, 0.25em 0.5em);
}
</style>
<button part="btn">Clicked ${this.count} Times</button>`;
The [part]
attribute can now be targeted from stylesheets in the main DOM using the ::part()
pseudo-element.
The ::part()
pseudo-element
To target a specific [part]
, pass its value into the ::part()
pseudo-element in your CSS.
For example, to style the button, I would use ::part(btn)
on the count-up
element. You can target elements with more specificity if desired to uniquely style different components.
count-up::part(btn) {
background-color: #0088cc;
border-radius: 0;
}
count-up[start-value="42"]::part(btn) {
background-color: azure;
color: #272727;
border-radius: 1em;
}
This approach gives developers the ability to style all of the properties on a Shadow DOM element, not just the ones that you’ve assigned CSS variables for.
However, it also means that developers can break your code in unexpected ways. In this example, the <button>
element is hidden, and will never be displayed in the UI.
count-up::part(btn) {
display: none;
}
Personally, I prefer to give developers more flexibility, and trust them not to break the code, but your mileage may vary.
This content originally appeared on Go Make Things and was authored by Go Make Things
Go Make Things | Sciencx (2024-11-13T14:30:00+00:00) Styling Web Component elements in the shadow DOM with parts. Retrieved from https://www.scien.cx/2024/11/13/styling-web-component-elements-in-the-shadow-dom-with-parts/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.