One of the main purposes of Web Components is to provide encapsulation — the ability to hide HTML tag structures and CSS styles and separate them from the rest of the code on the page so that different parts don’t clash, and in this way the code stays nice and clean.

The Shadow DOM gives us scoped style encapsulation and a way to go into the outside world (as little as possible) as we choose.

But what if I want to make some style properties customizable for my component?

This article covers the basics of using CSS custom properties to penetrate Shadow DOM and make your Web components customizable.

Create an HTML element

We’ll create custom HTML elements using JavaScript classes that extend the base HTML Element. We will then call customElements.define() with the name of the label we want to create and the class we just created.

class AppCard extends HTMLElement {... }window.customElements.define('app-card', AppCard);
Copy the code

In this example, we will create this simple Material Design card that will display when we add this element to the HTML:

.

First, we create Shadow DOM root, and then assign the HTML and CSS strings to the innerHTML of Shadow DOM Root, as shown below.

class AppCard extends HTMLElement {
  constructor() {
    super(a);const shadowRoot = this.attachShadow({mode: 'open'});
    
    shadowRoot.innerHTML = `  
      
Card title
`
; }}window.customElements.define('app-card', AppCard); Copy the code

Cover to try

In this example, we want to change the background color of the card. If it’s a simple div element in HTML, you can override the Card class or access the div element through a CSS selector. However, the following attempts will not work:

// access the div 
app-card > div {
  background-color: #2196F3;
}

// override card class
app-card > .card {
  background-color: #2196F3;
}
Copy the code

Use CSS to customize properties

To solve this problem, we can use CSS custom properties (CSS variables). You can change some CSS properties in custom elements using CSS custom properties defined in CSS.

In our example, we will use the card-bg variable on the background-color property to get who is using the color defined by the custom element.

class AppCard extends HTMLElement {
  constructor() {
    super(a);const shadowRoot = this.attachShadow({mode: 'open'});
    
    shadowRoot.innerHTML = `  
      
Card title
`
; }}window.customElements.define('app-card', AppCard); Copy the code

Now we’ll customize the element using app-card and create the card-BG variable in the CSS of the Body element, assigning the hexadecimal color #2196F3 to the variable.

<html>
  <head>
    <style>
      body {
        --card-bg: #2196F3;
      }
    </style>
  </head>
  <body>
    <app-card></app-card>
  </body>
</html>
Copy the code

conclusion

Using this strategy, we can have a wrapped CSS element in your document, and we can also allow customization of some properties using CSS. You can visit a full example here.


By Cesar William Alvarenga