Cory Rylan

My name is . Google Developer Expert, speaker, and Software Developer at VMware Clarity Design System.

Follow @coryrylan
Web Components

Using Modern Web Components

Cory Rylan

- 5 minutes

This post is a two-part blog series covering how to use and build Web Components. Part one covers how Web Components are used in various JavaScript frameworks as a consumer. Part two will cover how to create your own reusable Web Component.

Web Components are a collection of native browser APIs that enable developers to build reusable UI components natively in the browser. Web Components work just like regular DOM elements. This compatibility opens the door to reusable UI components. This reusability is excellent for all sorts of use cases such as Design Systems, Micro Frontends, or anywhere the component needs to work regardless of a JavaScript framework.

Building Web Components can be tricky as they are built using a collection of independent low-level APIs. Because these APIs are built into the browser, we can use lightweight libraries to provide syntactic sugar and eliminate some of the boilerplate. One of the major benefits of using Web Components is regardless of how you build the component, it uses the same standard shared public APIs as any other Web Component.

The Public APIs of a Web Component

Web Components work just like HTML elements. We can interact with these elements via HTML Attributes, JavaScript Properties, Custom Events and CSS. For our example, we will use an Alert box to demonstrate each of these public APIs.

Web Component built with Lit

Web Components are constructed using two main APIs. Custom Elements and Shadow DOM. The Custom Elements API provides a way to register our own custom HTML tags to the browser. The Shadow DOM API provides a way to encapsulate our component CSS in a way that is not global. These APIs together give us a fully encapsulated and reusable HTML element.

Web Components have five primary public APIs developers will use to communicate and customize the component.

  1. Content Slots
  2. HTML Attributes
  3. CSS Custom Properties/Parts
  4. JavaScript Properties
  5. Custom Events

 

Content Slot API

The Contents Slot API is an API provided by the Shadow DOM. This API allows us to project or render HTML from the light DOM of our HTML into the template or Shadow DOM of the Web Component. Most JavaScript frameworks have similar project features like React children and Angular Content Project.

Content Slots work great for container-style components such as Modals, Cards, and Alerts. Given our alert example, we can render content in the alert template.

Web Component Content Projection
<ui-alert>
<p>Hello there!</p>
</ui-alert>

HTML Attributes

We can further customize our Web Components by providing custom HTML Attributes. Attributes can be used as a way to configure or pass information into our Web Component.

Web Component alert boxes built with Lit
<ui-alert status="success">
<p>Hello there!</p>
</ui-alert>

In this example, we can style our Web Component based on a status success attribute. It's important to note HTML Attributes can only resolve string values. Since the attribute is in HTML, it's all parsed as strings. If you want to pass values other than strings, the Web Component can provide JavaScript properties for other types like Objects and Arrays.

JavaScript Properties

A common misconception is that Web Components can only use strings. However, this is false. Web Components can use any JavaScript type via properties, just like HTML elements and other framework components. For example, we could provide a dissmissable HTML attribute and dissmissable JavaScript boolean property to determine if our alert should show the dismiss button.

If we use plain JavaScript, setting the property would look something like this,

import 'alert.js';

const alert = document.querySelector('ui-alert');
alert.dismissable = true;

Here we use a boolean, but we could also pass any JavaScript type to the property of the component. All JavaScript frameworks support this behavior as this is a standard DOM element API. React is the only tool currently that does not properly support the full DOM spec and requires a shim/wrapper layer. See custom-elements-everywhere.com for details. This issue, however, is fairly easy to work around as Lit provides a package to solve this.

Here are some examples of setting properties in other frameoworks,

<!-- Angular -->
<ui-alert [dismissable]="true"></ui-alert>

<!-- Vue -->
<ui-alert :dismissable="true"></ui-alert>

<!-- Preact (uses properties and attr as fallback) -->
<ui-alert dismissable="true"></ui-alert>

As we can see, the current frameworks already enable us to set Properties and Attributes on elements without any extra work.

Custom Events

We can pass data in via HTML Attributes and JavaScript properties. We can also listen for updates from Web Components via Custom Events. For example, our alert can emit an event when the user clicks the dismiss button.

import 'alert.js';

const alert = document.querySelector('ui-alert');
alert.addEventListener('closeChange', event => {
console.log(event);
});

With Custom Events, we can now react to updates from our elements. Custom Events work just like DOM events, so all frameworks with the exception to React support this out of the box.

<!-- Angular -->
<ui-alert (closeChange)="someMethod()"></ui-alert>

<!-- Vue -->
<ui-alert @closeChange="someMethod"></ui-alert>

<!-- Preact -->
<ui-alert onCloseChange={this.someMethod}></ui-alert>

React does not properly support Custom Events, so the wrapper shim for React is required. See custom-elements-everywhere.com.

CSS Custom Properties and Parts

Lastly, styling Web Components works a bit differently than plain HTML and CSS. Because of the Shadow DOM, global CSS does not apply to the component, and the component CSS does not apply to any global element. This is very useful for style consistency and encapsulation. However, if we want to allow a component to be customized, we can use CSS Custom Properties and CSS Parts to create public theming APIs.

For example, if we want to allow our alert background or color to be changed, we can create a CSS Custom Property to assign a value to the component.

ui-alert {
--background: purple;
--color: white;
}

CSS Custom properties, however, only map a single CSS property at a time. We can give more flexibility by exposing elements within our Web Component template via CSS Parts.

ui-alert::part(close-button) {
width: 50px;
height: 50px;
}

With CSS Parts, the user of our component now has access to style any CSS property of that given element. We will see how to enable these APIs in a Web Component in Part two of this series.

Part Two, Building a Web Component

Now that we have covered all the major Public APIs of a Web Component, we will cover how to build a Web Component in part two of our blog series, Build your first Web Component with Lit.

View Demo Code   
 

No spam. Short occasional updates on Web Development articles, videos, and new courses in your inbox.

Related Posts

Lit Web Components

Reusable a11y with Web Components and Lit Controllers

Learn how to leverage Lit to build accessible Web Components easily.

Read Article
Web Components

Accessibility with ID Referencing and Shadow DOM

Learn how accessibility behavior can change when using Shadow DOM and Web Components.

Read Article
Web Components

Simple CSS Custom Property APIs with Web Components

Learn how CSS Shorthand Properties and CSS Custom Properties can simplify Web Component theming APIs.

Read Article