How to Build Your First Web Component: A Beginner‘s Guide

Web components have been around for several years now, but in 2023, they are really hitting their stride in terms of browser support and developer adoption. If you haven‘t yet explored web components, now is the perfect time to start. In this beginner‘s guide, we‘ll walk through what web components are, why they are useful, and how to build your first simple web component from scratch.

What is a Web Component?

First off, let‘s define what we mean by "web component". A web component is a custom, reusable HTML element that encapsulates its own structure, style, and behavior. Web components are based on four key technologies:

  1. Custom Elements: Lets you define your own HTML elements
  2. Shadow DOM: Provides encapsulation for the internal structure and styles of a component
  3. HTML Templates: Allows you to define reusable HTML structures
  4. ES Modules: Provides a way to package and reuse JavaScript code

The Custom Elements and Shadow DOM specs are the core of the web components model. Custom Elements provides a JavaScript API to define new HTML elements, while Shadow DOM provides a way to scope the structure and style within that custom element, shielding it from outside interference.

The beauty of web components is that they are framework agnostic – you can use them with any web framework or library, or with no framework at all. They provide a browser-native component model without the overhead and lock-in of a particular framework.

Browser Support for Web Components

As of 2023, web components have excellent support across all modern browsers. According to the Web Components project by Google, Custom Elements and Shadow DOM are supported natively in Chrome, Firefox, Edge, and Safari, covering the vast majority of internet users.

There are also polyfills available to provide web component support for older browsers if needed. Libraries like webcomponentsjs simulate the functionality of web components for browsers that don‘t yet support the native APIs.

So with wide browser support and easy polyfilling for legacy environments, there are very few barriers to adopting web components in your web projects today.

Anatomy of a Web Component

Let‘s break down the key parts of a web component:

Custom Element Class

At the core of every web component is a custom element class that extends HTMLElement. This is where you define the structure, behavior and state of your component.

A minimal custom element looks like this:

class MyElement extends HTMLElement {
  constructor() {
    super();
    // Component setup here
  }
}

customElements.define(‘my-element‘, MyElement);

The customElements.define call registers your new element with the browser so it knows how to construct it when it encounters the associated tag.

Lifecycle Methods

Custom elements can define special lifecycle methods that are called by the browser at different points:

  • constructor: Called when the element is first created or upgraded
  • connectedCallback: Called when the element is inserted into the DOM
  • disconnectedCallback: Called when the element is removed from the DOM
  • attributeChangedCallback: Called when an observed attribute‘s value changes

These lifecycle hooks allow you to set up, tear down, and react to changes in your element.

Attributes and Properties

Like regular HTML elements, custom elements can accept attributes to configure their behavior. Inside the element class, you can access and modify these attributes using the standard getAttribute, setAttribute, hasAttribute methods.

You can also define your own properties on the element class to manage internal state and provide an API for the component. To make the usage more idiomatic, it‘s common to link attributes and properties so they stay in sync.

Shadow DOM

Shadow DOM allows you to scope the internal structure and styles of a component inside a shadow root. This provides encapsulation and protects your component from external interference.

We won‘t be using Shadow DOM in our example, but it‘s a key feature to be aware of as you advance with web components.

Tutorial: Building a Current Date Web Component

With the key concepts explained, let‘s put them into practice by building a simple web component that displays the current date. We‘ll call it <current-date>.

Defining the Custom Element Class

First, we create a class for our custom element that extends HTMLElement:

class CurrentDate extends HTMLElement {
  connectedCallback() {
    const now = new Date();
    this.textContent = now.toLocaleDateString();
  }
}

Inside the connectedCallback, which is invoked when the element is inserted into the DOM, we get the current date using the Date object and format it to a locale-specific date string using toLocaleDateString().

We then set this formatted date string as the textContent of our element, so it will be rendered.

Registering the Custom Element

Next we need to register our custom element with the browser using customElements.define:

customElements.define(‘current-date‘, CurrentDate);

This tells the browser that when it encounters a <current-date> tag, it should construct an instance of our CurrentDate class to represent it.

Using the Custom Element in HTML

Now we‘re ready to use our <current-date> element in HTML:

<h2>Today‘s Date</h2>
<current-date></current-date>

That‘s it! When this HTML is parsed by the browser, it will recognize the <current-date> tag and construct an instance of our CurrentDate class. The connectedCallback will be invoked, populating the element with the current date string.

Testing the Component

Let‘s put it all together in a complete HTML file:

<!DOCTYPE html>
<html>
<head>
  <title>Current Date Web Component</title>
</head>
<body>
  <h2>Today‘s Date</h2>
  <current-date></current-date>

  <script type="module">
    class CurrentDate extends HTMLElement {
      connectedCallback() {
        const now = new Date();
        this.textContent = now.toLocaleDateString();
      }
    }

    customElements.define(‘current-date‘, CurrentDate);
  </script>
</body>
</html>

If you load this in a browser, you should see the heading "Today‘s Date" followed by the current date rendered by our web component. Congratulations, you just built your first web component!

Potential Enhancements

Our <current-date> component works, but it‘s pretty basic. Here are some ideas for how you could enhance it:

Formatting the Date

Instead of using the browser default locale string format, you could use the Intl.DateTimeFormat object to control the format more precisely. For example:

const formatter = new Intl.DateTimeFormat(‘en-US‘, {
  year: ‘numeric‘, month: ‘long‘, day: ‘numeric‘  
});

this.textContent = formatter.format(now);

This would format the date like: "October 19, 2023".

Accepting a Date via an Attribute

Right now the component always shows the current date, but it could be more flexible if it accepted a date to display via an attribute. You could change the implementation to look for a date attribute and parse it:

connectedCallback() {
  const dateStr = this.getAttribute(‘date‘);
  const date = dateStr ? new Date(dateStr) : new Date();
  this.textContent = formatter.format(date);
}

Then you could use it like:

<current-date date="2023-12-25"></current-date>

Using the <time> Element

For better accessibility and machine-readability, you could wrap the formatted date text in a <time> element with a machine-readable datetime attribute:

const timeEl = document.createElement(‘time‘);
timeEl.dateTime = date.toISOString();
timeEl.textContent = formatter.format(date);
this.appendChild(timeEl);

This would produce:

<current-date>
  <time datetime="2023-10-19T00:00:00.000Z">October 19, 2023</time>
</current-date>

These are just a few possibilities – the great thing about web components is that you have the full power of JavaScript, HTML, and CSS to build them however you like!

Web Components vs Component Libraries/Frameworks

You may be wondering how web components compare to component-based libraries and frameworks like React, Vue, or Angular.

The key difference is that web components are a web standard, not tied to any particular framework. This makes them more portable and interoperable. You can use web components inside a React or Vue app, or you can use them standalone with no framework at all.

The tradeoff is that web components are lower-level and more bare-bones compared to full-featured component frameworks. With React or Vue, you get a complete system for defining components, managing state, handling events, routing, and more. With web components, you‘re just getting the component encapsulation and lifecycle – everything else is up to you.

So web components are a great choice when you want to create reusable, framework-agnostic components. But for building complex applications, you may still want to reach for a more opinionated and full-featured component framework.

Conclusion

In this guide, we‘ve covered the fundamentals of web components and walked through creating a simple <current-date> component.

To recap, web components are custom HTML elements that encapsulate their own structure, style, and behavior. They are framework-agnostic and have good browser support as of 2023.

The key technologies behind web components are:

  1. Custom Elements for defining new HTML elements
  2. Shadow DOM for encapsulating the internal DOM and styles
  3. HTML Templates for defining reusable HTML structures
  4. ES Modules for sharing and reusing code

We built our <current-date> component by extending HTMLElement, defining a connectedCallback to set up the element, and registering it with customElements.define.

While our example was simple, it illustrates the basic anatomy and lifecycle of a web component. From here, you can build web components as simple or as complex as you need.

Web components are a powerful tool to have in your toolkit as a modern web developer. They enable creating reusable, standards-based components that can be shared across projects and teams.

I hope this guide has given you a solid foundation in web components and inspired you to start building your own. Happy coding!

Similar Posts