Generic Blog (Web) Components: Introduction and Blog Posts V1
7 min. read
A while back I wrote a set of Vue 2 components for a WordPress blog. It wasn't a complete project, was missing functionality that I couldn't figure out how to implement and I was afraid it would lock me into a framework (although I would rather get locked into Vue than any of the other frameworks I've seen out there).
Rather than work with a specific framework, I decided to revisit this as custom elements/web components.
according to [Custom Elements Everywhere](https://custom-elements-everywhere.com/) most frameworks, at least those that were tested by the site, have pretty good support for custom elements. Even React works with custom elements as long as you make some modifications. There is also an experimental React branch that fully supports custom elements but there's no guarantee that the branch will be merged into the main React codebase.
## So what are web components?
Web components are a set of technologies that enable developers to create custom HTML elements that can be used on web pages.
The component technologies for web components are:
* **Custom elements**: A set of JavaScript APIs that allow you to define custom elements and their behavior, which can then be used as desired in your user interface
* **Shadow DOM**: A set of JavaScript APIs for attaching an encapsulated "shadow" DOM tree to an element — rendered separately from the main document DOM — and controlling associated functionality. In this way, you can keep an element's features private, so they can be scripted and styled without the fear of collision with other parts of the document.
* **HTML templates**: The and elements enable you to write markup templates that are not displayed in the rendered page. These can then be reused multiple times as the basis of a custom element's structure.
The basic approach for implementing a web component generally looks something like this:
* Using the ECMAScript 2015 class syntax create a class in which you specify your web component functionality
* Register your new custom element using the `CustomElementRegistry.define()` method, passing it the element name to be defined, the class or function in which its functionality is specified
* Attach a shadow DOM to the custom element using Element.attachShadow() method
* Add child elements, event listeners, etc., to the shadow DOM using regular DOM methods.
* Define an HTML template using <template> and <slot>
* Again use regular DOM methods to clone the template and attach it to your shadow DOM.
* Use your custom element wherever you like on your page, just like you would any regular HTML element.
```js
// Create a class for the element
class PopUpInfo extends HTMLElement {
constructor() {
super();
// Create a shadow root
const shadow = this.attachShadow({mode: 'open'});
// Create structure elements
const wrapper = document.createElement('span');
wrapper.setAttribute('class', 'wrapper');
const icon = document.createElement('span');
icon.setAttribute('class', 'icon');
icon.setAttribute('tabindex', 0);
const info = document.createElement('span');
info.setAttribute('class', 'info');
const text = this.getAttribute('data-text');
info.textContent = text;
let imgUrl;
if(this.hasAttribute('img')) {
imgUrl = this.getAttribute('img');
} else {
imgUrl = 'img/default.png';
}
const img = document.createElement('img');
img.src = imgUrl;
icon.appendChild(img);
const style = document.createElement('style');
style.textContent = `
.wrapper {
position: relative;
}
.info {
font-size: 0.8rem;
width: 200px;
display: inline-block;
border: 1px solid black;
padding: 10px;
background: white;
border-radius: 10px;
opacity: 0;
transition: 0.6s all;
position: absolute;
bottom: 20px;
left: 10px;
z-index: 3;
}
img {
width: 1.2rem;
}
.icon:hover + .info, .icon:focus + .info {
opacity: 1;
}
`;
shadow.appendChild(style);
shadow.appendChild(wrapper);
wrapper.appendChild(icon);
wrapper.appendChild(info);
}
}
customElements.define('popup-info', PopUpInfo);
```
## Using the Lit library
[Lit](https://lit.dev/) is the spiritual successor to the Polymer library and it makes it easier to work with Web Components.
Instead of using plain custom elements, we'll take advantage of Lit features that will make the work easier.
An example custom element built with Lit:
```js
import {LitElement, html} from 'lit';
export class CEElement extends LitElement {
constructor() {
super();
//implementation
}
render() {
return html`This text will be red`;
}
}
window.customElements.define('c-e', CEElement);
```
## Additional specifications that enhance web components
There are additional specifications that enhance the existing web component applies
[CSS modules](https://web.dev/css-module-scripts/) and [Constructable Stylesheets](https://web.dev/constructable-stylesheets/) eliminate the need for `