Jump to content
Slate Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Marble
Slate Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Marble
Sign in to follow this  
Rss Bot

Web components: The ultimate guide

Recommended Posts

With web components, developers now have the ability to create their own HTML elements. In this ultimate guide, you'll learn everything you need to know. On this page, we'll cover what exactly web components are, the benefits of using them, and the elements that make them up. 

Then you'll learn how to build your own components in two short tutorials – on page 2 you'll learn how to building a component with the HTML templates and shadowDOM APIs, and on page 3 you'll got one step further and learn how to build a customised, built-in element.

Finally on page 4 you'll find some frameworks and tools to get you started, and examples of existing elements to try to today. 

While you're here, you might also want to take a look at our guide to the top HTML APIs, and how to use them.

What are web components?

Developers love components. They are a great way to define blocks of code that can be dropped in and reused anywhere they are required. Over the years, there have been a few attempts to convey this idea on the web, with varying degrees of success.

Mozilla's XML Binding Language and Microsoft's HTML Component specifications date back all the way to Internet Explorer 5 almost 20 years ago. Unfortunately, both attempts proved unwieldy, failed to gain traction in other browsers, and ultimately were removed. While they may not be around today, their concepts formed the basis of the modern approaches in use.

JavaScript frameworks such as React, Vue or Angular follow a similar approach. One of the main reasons for their success is the ability to contain common logic in an easily shareable pattern in one form or another.

While these frameworks can improve the developer experience, they do so at a cost. Language features such as JSX need to be compiled, and many frameworks rely on a runtime to manage all of their abstractions. Wouldn't it be easier if there was a way to get the benefit without all that heavy weight? Web components allow us to do just that. 

The 4 pillars of web components

The concept of a web component consists of three APIs – Custom elements, HTML templates and the shadow DOM – with JavaScript modules gluing them together. By combining the benefits that these technologies provide, it's possible to start building custom HTML elements that look and behave just like their native counterparts.

Using a web component is much like using any other existing HTML element. They can be configured using attributes, queried for using JavaScript, and even styled through CSS. As long as the browser knows they exist, they are treated no differently.

This also allows web components to play well with other frameworks and libraries. By using the same communication mechanisms as any other element, they can be used alongside any framework that exists today or in the future.

Most importantly of all, these are all built upon web standards. The web is built on a concept of backwards compatibility, and by building a web component today, it will carry on working for years to come.

But before going any further, we should take a look at what makes up these specifications, and how you can get creating and using one today.

web components

There are four main elements that make up web components

01. Custom Elements

Key features:

  • Define an element's behaviour
  • React to attribute changes
  • Augment existing elements

When you hear people talk about 'web components,' quite often they are referring to the workings underneath – the custom elements API.

With this API, it is possible to create classes that power the inner workings of an element. They detail exactly what to do when an element is added, updated or removed.

Each custom element has a similar structure. They extend an existing HTMLElement class, which provides the groundwork for how an element should behave.

Inside, there are a few methods called reactions that are called in response to something about that element changing. For example, connectedCallback will be called when the new element appears on screen. These work similarly to the lifecycle methods found in most JavaScript frameworks.

Updating the attributes on an element can change how it behaves. When an update happens, the attributeChangedCallback reaction will fire, which details the change. This will only happen for an attribute that is defined inside the observedAttributes array.

An element needs to be defined before the browser can do anything with it. The define method here takes two arguments – the tag name, and the class it should use. All tag names must contain a - character to avoid any clashes with any future native elements.

The element can then be written anywhere in the page as a regular HTML tag. Once a browser has an element defined, it then finds any of these matching tags and links up their behaviour to the class in a process known as 'upgrading'.

There are two types of custom element – 'autonomous' or 'customised built-in'. Autonomous custom elements, which have been covered up until now, are not related to any existing element. Much like a <div> or <span> they do not provide any meaning to their content.

A customised built-in element – as the name implies – can enhance an existing element with new functionality. They maintain that element's normal semantic behaviours, while also being open to change. If an <input> element was customised, for example, it would still be picked up and submitted as part of a form.

The class of customised built-in component extends the class of the element it is customising. The definition also needs to define the tag of that element through its third argument.

They are also used slightly differently. Instead of a new tag, they extend the existing tag by using the is attribute. The browser can read this, and upgrade them in the same way as it can an autonomous component.

While most browsers support autonomous custom elements, Only Chrome and Firefox support customised built-in elements. If used in a browser that does not support them, they will fall back to the regular versions of the elements they customise, which can make them safe to use.

02. HTML Templates

  • Create ready-made structures
  • Inert until called upon
  • Contains HTML, CSS and JS

Historically, browser-based templating involved stitching strings together in JavaScript, or using a library like Handlebars to parse a block special markup. More recently, the HTML templates specification defined the <template> tag, which can contain anything likely to be reused.

On its own, it has no appearance and remains inert, meaning nothing inside is parsed or executed until told to, including requests for external media such as images or video. JavaScript cannot query the contents either, as browsers will only see it as an empty element.

A regular query will pick up the <template> element itself. The importNode method creates a copy of its contents, with the second argument telling it to take a deep copy of everything. Finally, it can be added to the document like any other element.

Templates can contain anything an HTML page can, including CSS and JavaScript. As soon as the element is applied to the page, those styles apply and the scripts execute. Bear in mind that these will run globally and so can override styles and values if care isn't taken.

The best part about templates is that they are not just limited to web components. The examples here apply to any web page, but become particularly powerful when paired with web components, in particular the shadow DOM.

03. Shadow DOM

  • Avoid styles leaking out
  • Naming becomes simpler
  • Keep implementation logic inside

The Document Object Model – or 'DOM' – is how the browser interprets the structure of a page. By reading through the HTML, it builds up an idea on what elements in the page contain what content, and uses that to decide what to show. When using something like document.getElementById() the browser is actually looking through the DOM.

That may be okay for the layout of a page, but what about the implementation details inside an element? Pages shouldn't need to worry about what makes up the interface inside a <video> element for example. That is where the shadow DOM comes in.

A shadow DOM is created when applied to an element. Any content can be added to the shadow DOM just like the regular – or 'light' – DOM, but it has no effect on what's happening outside of it. Likewise, nothing in the light DOM can access the shadow DOM directly. This means we can add classes, styles and scripts anywhere in the shadow DOM without worrying about clashes.

The best use of the shadow DOM with web components comes when coupled with a custom element. By having a shadow DOM in charge of the content, any time this component is reused, its styles and structure will not affect the rest of the page. 

04. ES and HTML Modules

  • Add in where needed
  • No build step requirement
  • Keep everything in one place

While the previous three specifications have had relatively straightforward paths to success, the packaging and reusability of them has long been a sticking point.

Originally, the HTML Imports specification defined a way for browsers to include HTML documents, much like CSS or JavaScript is already today. This would allow custom elements, along with their templates and shadow DOM, to live elsewhere and imported as needed.

Firefox chose not to implement HTML Imports in its browser, and instead favoured a newer specification around JavaScript module importing.

Modules do not apply their content globally by default. By marking certain variables, functions or classes as exported, they can then be imported by anything that needs them and used as if they were local.

This is a great help to web components, as a custom element containing a template and a shadow DOM can be exported from one file and added to another. As long as it gets defined somewhere along the line, it is ready to use.

An extension to this specification has been proposed to bring back some of the ease of HTML imports, alongside module imports. They will allow web components to be written using declarative and semantic HTML. Spearheaded by Microsoft, this feature is soon coming to Chrome and the Chromium-powered Edge browser.

Next page: How to build you own components

While there are a lot of complicated things you can achieve with web components, simply getting up and running actually involves very little code. Take your first steps into web components with a couple of short examples.

web components

This component enables you to display user comments, using the HTML templates and shadow DOM APIs

This first tutorial (below) focuses on building a component to display user comments by making use of the HTML templates and shadow DOM APIs.

Jump to page 3 to learn how to save yourself time by using custom elements.

01. Provide a template

The component needs a generic template it can copy in order to generate its markup. This can live anywhere that the custom element class itself can access through its unique ID.

Add the <template> element directly in the HTML of the page. Any styles written here will only affect the component.

02. Add in markup

Along with the styles, the template contains the structure of the component's internals. In this case, it is set of <div> containers for layout purposes.

All dynamic content is passed in through slots. Add in slots for the user's avatar, name and message, and give them appropriate names to reference later.

03. Default slot content

web components

Fallback content will appear when no information is supplied for a slot

The data passed into the slot will override whatever sits inside it in the template. If there is nothing supplied for that slot, it displays the fallback content instead.

In this case, if no username is supplied, the comment will display a 'no name' message in its place.

04. Create the class

Custom elements start life as a class that extends the generic HTMLElement class. As part of the setup process, it creates its own shadow root to render its content into. Keep it open in order to access it in the next step. 

Finally, tell the browser about the new UserComment component class. 

05. Apply shadow content

When the browser finds a <user-comment> element, it is going to populate the shadow root with the content of the template. The second argument tells the browser to copy all of the template, not just the first layer.

Add that markup to the shadow root, which will immediately update the visuals of this component.

06. Use the component

Back in the HTML, the component is now ready to use. Add the <user-comment> tag and add any relevant data inside.

As all slots are named, anything else that is passed through outside of a slot will be ignored. Everything inside those slots is copied in exactly as supplied, including related styling.

Next page: How to create a customised built-in element

Custom elements can also extend existing ones. It helps to save time by not having to recreate some of the behaviour that's already in the browser. This tutorial shows you how to extend the <time> element to display relative times that machines can understand.

web components

Extend the <time> element to display relative times that machines can understand

01. Create the class

Custom built-in elements start life exactly the same as autonomous ones, but instead of extending HTMLElement, they use an existing element as a starting point.

This component uses HTMLTimeElement – the class that <time> elements use. It includes all the behaviour around the datetime attribute, including the format it expects that data to be supplied in.

02. Define the element

Again, much like autonomous custom elements, these also need to be registered with the browser using the define method. One added detail is the third argument, which takes an options object.

For now, this object only has one key, which is used to define exactly which built-in element it customises. It takes the tag name, and will cause an error if it doesn't exist.

03. Set the time

As the components set the value of the element in multiple places, it should have a method to call that contains that logic. Inside that method, the component tells the timeago library what that time is and sets its return value as the contents of that element.

Finally, set the title attribute, which allows users to hover their cursor over the text to see the exact time being referenced.

04. Update on connection

The component can use that new method to set the time on the element as soon as it appears on the page. Customised built-in elements cannot have an attached shadow DOM. As there is no other setup required, the component does not need any constructor.

05. Check attribute changes

At the moment, if the page wanted to update the time programmatically, our component would not react. It does not know it should be watching for changes to the datetime attribute.

By defining observed attributes, the attributeChangedCallback will run each time one of them changes. In this case, the component can run the setTime method again.

06. Add to the page

web components: text saying 'in 1 month'

The final result

As this element is an extension of a built-in element, the implementation is a little different. To use our new element, create a <time> tag with an extra is attribute. This should match the name given when defining the component. For browsers that do not support customised built-in elements, they will display the fallback content that is inside instead.

Next page: Tools and frameworks to try

01. LitElement

web components: LitElement

LitElement provides helper methods and classes to create web components

Spearheaded by Justin Fagnani at Google, LitElement aims to supersede Polymer Classic as the premier approach to web components. It provides helper methods and classes to create web components, without the required boilerplate setup. It has dramatically increased in popularity since its first stable release in February 2019.

02. Stencil

Stencil is a compile-time tool from the Ionic framework team. It will analyse each component, optimise it as best as it can, and return a version that can be used across different browsers and frameworks. It includes added behaviour such as JSX, which handles data binding like a React project.

03. Vue web component wrapper

While the Vue framework can work with web components without issue, using an existing Vue component as a web component elsewhere is trickier. This library will wrap the single-file component and map all the necessary bindings automatically, or the Vue CLI can take care of all the heavy lifting.

04. Angular Elements

Similar to Vue, there is another wrapper to allow web components to be created using the power of Angular. The createCustomElement function links the APIs used with custom elements with the equivalent Angular syntax. Add this as part of the application bootstrap process and the rest is taken care of.

05. Skate

web components

Skate works with other templating languages

By providing guidance alongside a thin layer on top of existing native functionality, Skate can provide great benefit with a smaller footprint than other libraries. Much of this comes from the ability to work with other templating languages like Preact, and drop in modules for additional functionality, such as server-side rendering.

06. Svelte

Svelte compiles its components into regular JavaScript and avoids shipping a runtime like other frameworks, which results in smaller files. While not required, Svelte components can be built as web components without needing any external tools. Define a tag name in the module configuration and Svelte will do the rest. 

07. X-Tag

web components

X-Tag is useful for tying components with those in other frameworks

The X-Tag project has gone through many iterations over the years. Now, this Microsoft-backed library mirrors much of the custom element specification, with its own approaches to style and templating. It is particularly useful when needing to support older browsers, or when tying components together with those in other frameworks.

08. Slim

While Slim is a relatively unknown library, it provides added functionality, such as one-way data binding and automatic re-rendering out of the box. It's fast and small too – weighing in at only 3.4Kb gzipped. Other directives can be dropped in as and when they are needed to keep things lean.

Feel the benefits of web components right away with these elements.

01. Wired

web components: wired

Wired can help you mock up a page quickly

Most sites and applications go through several iterations before becoming a finished product. A lot of these start life as a prototype sketched on a notepad, or created inside a graphical application. Wouldn't it be better if these lived inside the browser to get an idea of how it works in the real world?

Wired is a set of web components that generate an interface with a hand drawn look using rough.js under the hood. Buttons, inputs and more are ready to be dropped in where needed and linked up for basic interactions to mock up a page in no time. 

02. Material Components

web components: material components

These components are a work in progress

The team behind Google's Material Design pattern already have an implementation for the web. Currently, they're working to have them consumable through web components to be dropped in without extra configuration. Complex patterns such as tabs and drawers have been created with more on the way.

03. Brightspace UI

The company behind the Brightspace learning tool has made a set of its components open source for all to use. These include buttons, tables and inputs all with a focus on performance and accessibility. Any bugs the team come across are fixed and pushed out to help anyone else using them.

04. Vaadin

web components: Vaadin

These pre-built components can help get you started

The Vaadin platform is a set of pre-built UI components ready to be used to create an entire application. There's plenty available to help you get off the ground, including grid layouts, tooltips and progress bars. The paid-for pro components also include charts and text editors, configurable for all needs.

05. Animated Content Placeholder

Skeleton loading is a great way to improve perceived loading times. They act as a placeholder for incoming content that may take a while, such as a news feed or gallery. This component builds out a skeleton by using web components as the building blocks to mimic the loaded state.

06. Gluon-font-awesome

This is a lightweight wrapper around the popular Font Awesome icon library. Icons can be dropped in using a <font-awesome> tag, while the component handles the importing and loading of the font awesome library. It is built using Gluon – a lightweight framework providing convenience on top of native custom elements.

This article was originally published in creative web design magazine Web Designer. Buy issue 287 or subscribe.

Read more:

View the full article

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×