Web Components Are Easier Than You Think
By John Rhea
Translation: Chi Ling student
preface
I went to a tech conference and saw some big names demonstrate Web Components, which was pretty nice, but seemed a bit too complicated — HTML code with almost a thousand lines of JavaScript code for single-digit lines. Inevitably, the big guys will gloss over the fact that Web Components require a lot of JavaScript code to work, or dive into seemingly insignificant details. At this point my eyes start to glaze over and I start to stare.
But in a recent reference project, in order to make learning HTML easier, I, a perfectionist, decided that I had to cover every HTML tag in the specification. This is the first time I’ve introduced
and
tags in addition to those in the conference presentation. I had to dig into them in order to write something that was both accurate and interesting.
In the process, I’ve learned a few things — Web Components aren’t as complex as we remember.
Web Components has come a long way since my last daze at tech Talk, and perhaps my initial fear of it prevented me from learning more about it (or was it both daze and fear?). .
I’ll use this article to tell you: Yes, you can create a Web Component!
Don’t be dazed, don’t be scared, try it now.
from<template>
start
is an HTML tag that can be used to create a Web Component HTML template. Templates don’t need a lot of HTML code, they can be very simple:
<template>
<p>The Zombies are coming!</p>
</template>
Copy the code
The
tag is important because it must be used as the root element to hold all the HTML templates together. Like the foundation of a high-rise building, it is the foundation upon which Web Components are built. This code is then used as an HTML template for the Web Component < apocalyptic-Warning > as a warning of a zombie apocalypse.
Then there is<slot>
, like
, is an HTML tag. In this case,
is used to wrap the content that
will render to the page.
<template>
<p>The <slot>Zombies</slot> are coming!</p>
</template>
Copy the code
Here we add the word “Zombies” to the
tag of the HTML template. If nothing is done to the
tag, the contents of the
tag are displayed by default. In this example the word “Zombies” will be displayed by default.
Using the
tag is more like a placeholder, and we can either use the placeholder directly or define something else to replace it, usually using the name attribute to implement the ability to exact substitution.
<template>
<p>The <slot name="whats-coming">Zombies</slot> are coming!</p>
</template>
Copy the code
The name attribute tells the Web Component what should go where in the template. Now there’s a
tag with the name whats-coming. In addition to “Zombies”, the
part of the tag has the flexibility to place other content. Assuming “Zombies” is the highest level of warning, it can also be replaced with “Robots”, “Werewolves”, or even “Web Components”.
Use the Web Component
Technically, we’ve already written the Web Component, and we can put it anywhere we want.
<apocalyptic-warning>
<span slot="whats-coming">Halitosis Laden Undead Minions</span>
</apocalyptic-warning>
<template>
<p>The <slot name="whats-coming">Zombies</slot> are coming!</p>
</template>
Copy the code
In this case, the < apocalyptic-Warning > Web Component is put on the page just like any other HTML tag. But it also places a tag in the middle, which references the name attribute of the
tag. The content in this
tag is what replaces “Zombies” when the component is rendered.
It is important to note that custom tags must be hyphenated in their names to prevent collisions with new HTML published tags.
There is still some work to be done to get
to be replaced, and it is time to write the JavaScript code.
Registered Web Component
As I said, it does take some JavaScript code to make the above code work, but it’s not as complicated as I thought it would be — thousands of lines of JavaScript, deep into detail. Hopefully I can convince you to learn Web Components with this JavaScript code as well.
You need a constructor to register the custom tag; if you don’t register it, the Web Component is as still and lifeless as a stone statue.
This is the constructor you will use:
// Define the custom tag with an appropriate name in this case
customElements.define(
'apocalyptic-warning'.// Make sure that this custom tag has all the default attributes and methods of the built-in HTML tag (HTMLElement inherited)
class extends HTMLElement {
The constructor is called when a new custom tag is created
constructor() {
// Calling the parent constructor, the HTMLElement constructor, is guaranteed to behave exactly the same as creating the built-in HTML tag
super(a);// Get
and save it in warning
const warning = document.getElementById('warningtemplate');
// Get the contents of warning and save it in myWarning
const mywarning = warning.content;
const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(
mywarning.cloneNode(true)); }});Copy the code
I left detailed comments on every line of the code above, except the last:
const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(
mywarning.cloneNode(true));Copy the code
This line of code does a number of things: first, use the custom tag and create a Shadow DOM, {mode: ‘open’} means that JavaScript code outside root can access and manipulate the Shadow DOM, which can be interpreted as a backdoor to the Web Component.
Here you create a Shadow DOM and add a node to it that is a deep copy of the previous HTML template, including all the tags and text content of the template. After the template is added to the Shadow DOM of the custom tag, the
position is taken over by the content matching the name attribute.
Now let’s look at the effect of placing two instances of the same component and changing just one tag to render different content.
Demo (due to mining restrictions, can only jump to Codepen view)
Add styles to the Web Component
As you may have noticed in the Demo, we definitely have the ability to style Web Components using CSS. We can actually include a
<template id="warningtemplate">
<style>
p {
background-color: pink;
padding: 0.5 em;
border: 1px solid red;
}
</style>
<p>The <slot name="whats-coming">Zombies</slot> are coming!</p>
</template>
Copy the code
As such, due to the Shadow DOM, styles are applied directly to the current Web Component without global style contamination.
Now, in my mind’s eye, I think of the custom tag as a copy of
, and then I insert my added content into
, and use Shadow DOM to inject it into the page. But that’s just what you see on the front end; it doesn’t actually work that way in the DOM. While the content of a custom tag appears in its original place, Shadow DOM is more like a mask placed at the top of the custom tag.
Technically, the inserted content is outside of
, so any descendant selectors and classes written inside the
apocalyptic-warning span {
color: blue;
}
Copy the code
Demo (due to mining restrictions, can only jump to Codepen view)
But beware! Styles in CSS files do not have access to tags in
and Shadow DOM.
Put them together
Let’s take a look at an example of creating a zombie profile card, just like the profile you might need after a zombie apocalypse. To be able to style the default content and anything inserted into it, we need both the
Now the JavaScript code is exactly the same, except that we use the Web Component name
.
customElements.define(
'zombie-profile'.class extends HTMLElement {
constructor() {
super(a);const profile = document.getElementById('zprofiletemplate');
const myprofile = profile.content;
const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(
myprofile.cloneNode(true)); }});Copy the code
Here is the HTML template, including the wrapped CSS:
<template id="zprofiletemplate">
<style>
img {
width: 100%;
max-width: 300px;
height: auto;
margin: 0 1em 0 0;
}
h2 {
font-size: 3em;
margin: 0 0 0.25 em 0;
line-height: 0.8;
}
h3 {
margin: 0.5 em 0 0 0;
font-weight: normal;
}
.age..infection-date {
display: block;
}
span {
line-height: 1.4;
}
.label {
color: # 555;
}
li.ul {
display: inline;
padding: 0;
}
li::after {
content: ', ';
}
li:last-child::after {
content: ' ';
}
li:last-child::before {
content: ' and ';
}
</style>
<div class="profilepic">
<slot name="profile-image"
><img src="https://assets.codepen.io/1804713/default.png" alt=""
/></slot>
</div>
<div class="info">
<h2><slot name="zombie-name" part="zname">Zombie Bob</slot></h2>
<span class="age"
><span class="label">Age:</span> <slot name="z-age">37</slot></span
>
<span class="infection-date"
><span class="label">Infection Date:</span>
<slot name="idate">September 12, 2025</slot></span
>
<div class="interests">
<span class="label">Interests: </span>
<slot name="z-interests">
<ul>
<li>Long Walks on Beach</li>
<li>brains</li>
<li>defeating humanity</li>
</ul>
</slot>
</div>
<span class="z-statement"
><span class="label">Apocalyptic Statement: </span>
<slot name="statement">Moooooooan!</slot></span
>
</div>
</template>
Copy the code
This is the CSS style set for the
tag and its descendants in our main CSS file. Note the repetitions here, which are used to make sure that the replaced tag has the same style as the tag in the template.
zombie-profile {
width: calc(50% - 1em);
border: 1px solid red;
padding: 1em;
margin-bottom: 2em;
display: grid;
grid-template-columns: 2fr 4fr;
column-gap: 20px;
}
zombie-profile img {
width: 100%;
max-width: 300px;
height: auto;
margin: 0 1em 0 0;
}
zombie-profile li,
zombie-profile ul {
display: inline;
padding: 0;
}
zombie-profile li::after {
content: ', ';
}
zombie-profile li:last-child::after {
content: ' ';
}
zombie-profile li:last-child::before {
content: ' and ';
}
Copy the code
It’s all in one now!
Demo (due to mining restrictions, can only jump to Codepen view)
There are still a few questions and other nuances, but I hope you now know Web Components better and are more comfortable with it than you were a few minutes ago. Just like we did here, try it out. Perhaps you can add custom Components everywhere in your work to get the feel and meaning of Web Components.
What are you more afraid of now? Web Components or zombie Apocalypse? A few minutes ago I would have said I was more afraid of Web Components, but now I’m proud to say that the zombie apocalypse is the only thing I’m worried about.
Other tutorials worth following: Ruan Yifeng: Getting Started with Web Components
–