Westbrook Johnson

thinks he might

write more:

someday,

here.

Basic styling of custom elements

First published: 2022-11-27

Modified: 2023-12-30

At its most basic, styling a custom element works just like any other HTML Element, you take a selector that points to the element and write styles for it:

custom-element {
// ...apply styles here
}

And by basic, here, I mean really basic:

const template = document.createElement("template");
template.innerHTML = /*html*/`
<slot></slot>
`
;

class CustomElement extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: "open"
});
this.shadowRoot.appendChild(
template.content.cloneNode(true)
);
}
}

customElements.define('custom-element', CustomElement);

With this element, we are talking about a host that is merely a wrapper for the content that is slotted into it. Above there are not even default styles that the custom element ships with, particularly no display rules, which leave the custom element as little more than a <span>. Not having default styles, applying whatever CSS you'd like to the host from the outside should be something to which a developer with any experience applying CSS should be accustomed.

Things may get a little more interesting when the custom element is delivered with default styles. Here we apply a CSSStyleSheet object (as imported directly from CSS, thanks to import attributes) to the adoptedStyleSheets array on our custom element's shadow root.

/* custom-element.js */
import styles from './custom-element.css' with { type: 'css' };
// ... previous example code omitted for brevity

class CustomElement extends HTMLElement {
constructor() {
// ... previous example code omitted for brevity

this.shadowRoot.adoptedStyleSheets = [styles];
}
}

In this way, the following styles might be applied to our custom element.

/* custom-element.css */
:host {
display: block;
color: red;
border: 1px solid;
padding: 30px;
font-size: 30px;
}

Et voilà! We have the following custom element...

This is a custom element!

If, perchance, you specifically chose this custom element for its beautifully styled defaults, then "ship it!" If you're looking to shape the visual delivery of the custom element to your own devices, you only need to address the element in your site (or parent element) styles to do so.

/* site.css */
custom-element {
color: green;
border: none;
padding: 1em 2em;
font-size: 2rem;
}

This buys us the following, equally beautiful, delivery of our custom element.

This is a styled custom element!

Have you learned a lot? Learned a little? I have, particularly in that I took this post as an opportunity to start building a new blog for myself. Hopefully, you have, too, and we can take the learnings we've done together in all sorts of new directions. I'm thinking that in some indeterminate future time I might write about more complex styling approaches to custom elements. See you then!


Editors note: some of the APIs outlined in the examples above are not yet available cross-browser. While these are the target APIs that browsers have agreed to, in order to support cross-browser delivery of this article, live demo code is modified from the example to work fully cross-browser.