A look at web components
Although web components have been around for several years in the web development world, it hasn’t been something that I’ve heard mentioned a lot. On the surface, web components look like an easy way to create and reuse elements and patterns for websites. But how easy are they to set up and use?
What are web components?
Web components is the name given to a range of technologies that allow developers to create their own HTML elements using JavaScript. These elements can be reused, with styling and functionality remaining unique to them. From delving in and creating a few components, I’d say that they are similar to shortcodes in WordPress and to an extent, content types in TerminalFour.
The technologies that are using in web components are:
- Custom elements – A JavaScript API that lays down the foundation for creating, designing, and using new elements. This is done using the
customElements.define
function. - Shadow DOM (Document Object Model) – Allows a separate, hidden DOM to be attached to an element. Elements using the shadow DOM can use their own styling and functionality that is separate from the styling and functionality used for elements on the rest of the page.
- HTML templates – Allows developers to write the standard HTML code that will be output only when using the new custom elements.
How they are created
On the JavaScript side, a class is created for the custom element and holds all the functionality, including querying and manipulating the shadow DOM. The element is then registered with its unique tag name along with the class.
Finally, an element is created with the template tag and is attached to the shadow DOM in the class of the component. Here is where the element’s HTML and CSS is written.
To include this web component on a webpage, the newly created HTML element can simply be inserted alongside other HTML elements with any relevant attributes.
Creating a web component
Since this was a new technology for me, I thought I would try to create my own web component. I decided to create a navbox web component that was based on the navbox DPL pattern.
Starting off with the HTML template in JavaScript, the template element is created, and I add in most of the navbox code from the DPL. The styling for the element is added inline and will be added before the navbox’s HTML in the innerHTML property.
const navbox = document.createElement('template');
navbox.innerHTML = `
`;
You may notice I’ve included an element that isn’t present in the DPL navbox code – the slot element. The slot element gives the template code more flexibility, and is simply a placeholder for users to add in their own content.
The Navbox class attaches itself to the shadow DOM and appends the HTML template element to it, where we can now query and manipulate the HTML.
class Navbox extends HTMLElement {
constructor() {
super();
this.attachShadow({mode:'open'});
this.shadowRoot.appendChild(navbox.content.cloneNode(true));
const navboxSize = this.shadowRoot.querySelector('.col-sm-4');
if (this.getAttribute('large') == 'true') {
navboxSize.classList.remove('col-sm-4');
navboxSize.classList.add('col-sm-6');
}
this.shadowRoot.querySelector('span').innerText = this.getAttribute('title');
this.shadowRoot.querySelector('a').href = this.getAttribute('url');
if (this.getAttribute('image') && this.getAttribute('alt-text')) {
this.createImgDiv(this.getAttribute('image'));
}
}
createImgDiv(image) {
const navboxImageDiv = document.createElement('div');
const navboxImg = document.createElement('img');
navboxImg.src = image;
const navboxTitle = this.shadowRoot.querySelector('.navbox__title');
const navboxDiv = this.shadowRoot.querySelector('.navbox');
navboxImageDiv.classList.add('navbox__image');
navboxImageDiv.appendChild(navboxImg);
// Add to navbox before title
navboxDiv.insertBefore(navboxImageDiv, navboxTitle);
}
}
The class also adds in data and creates elements based on what attributes were added to the HTML element. The only required attributes for the navbox are the title and the url.
Finally, the last line in the JavaScript file is to define the custom element tag and pass in the Navbox class to handle all of the functionality. In this instance, I’ve named the custom element sta-navbox.
window.customElements.define('sta-navbox', Navbox);
Within the HTML file, the sta-navbox element can now be used with its attributes. To make use of the slot element in the HTML template in the JavaScript file, slot gets added as an attribute to an element (a div element in this case) and it must be equal to the slot name in the template.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
To see the web component in action, you can view the code on JSFiddle.
Conclusion
From the short time that I’ve looked into web components, the main advantages that I see are:
- Easier to use for end users – For users that want to use DPL patterns but aren’t too confident in using HTML, converting these patterns into simple web components may be easier for users to use.
- Separate styling – I think components having their own separate styling that isn’t affected by other page CSS is great. I can see that being useful for having uniformity when creating WordPress plugins, as each theme’s styling could affect the look and output of a plugin.
- Performance – If we were to convert each of the DPL patterns into web component files, users can load in the components/patterns they need rather than loading in the entire DPL.
- Self-contained code – Much like content types in T4, editing the code in one place updates the output of all of the components which would save time when needing to make changes.
Some of the disadvantages I found were:
- Finding the component quite cumbersome to set up. I find that it’s much easier to type out the raw html than creating the elements in JavaScript and adding in the classes and attributes that way.
- With most of the code being written in JavaScript, if the file doesn’t get loaded in, the component won’t appear.
- Writing CSS within JavaScript isn’t ideal. Although, I have read that you can use and link CSS files within the template section but that is something that I would need to look into more.
This look into web components has coincided with the start of DPL 2.0 development and while not being implemented at the moment, it could be something to keep in mind when developing, creating, and updating patterns.