an introduction to web components. part one: making a component.

Over the past couple of months, I've been using web components to rebuild my personal website. I've learned a lot about how they work, so it's time to document some of that information for people who might want it.

the last time I wrote an article about how to use this set of technologies, it was more geared toward people who already know react or some other component system, so this time it's going to be geared toward newcomers. plus, react sucks anyway, and I think web components are the future.

this is going to be a short one! depending on how fast you'd like to go, I think it'll only take about 15-20 minutes to complete the example project. this is just a guess though, might take longer if you don't have some of the things in the initial setup section.

assumptions I'm going to make.

In order to do the stuff in this post, I'm assuming right now that you have some understanding of how to use the command line, how to use the npm cli, and how to use html / css / javascript. that's about it!

I won't assume you know much about other component systems like react, but if you already do, this post might feel pretty basic.

initial setup.

there really isn't much setup required to get started with web components (because all the stuff you actually need is included in javascript already). however, I'll show you some stuff that I use to make my development process easier. neither of these are really required, but they might be useful for you too — still, do what thou wilt.

one: sass - css preprocessor

if you're still using regular old css in 2021, you might be missing out. I'm not going to preach to you about this one, but sass makes writing css a lot more fun (and also the syntax is pretty, which is important to me at least).

again though, this isn't really required. also, you can write css straight inside web components (which I'll show you) and you can only write sass in an external file.

two: some sort of boilerplate

in all my personal web projects, I use a tool I made called jpegzilla-init (I know, really creative) to set up a foundation. if you run npm i -g jpegzilla-init, you can use it.

to set up a basic web component project here, you'd run jpegzilla-init inside your (empty) project folder and then follow the prompts (or run jpegzilla-init -w to use the default setup). then, run something to compile the sass (this is important!!). the command you can use if you used jpegzilla-init is:

sass --watch --style=compressed ./css/main.sass:./css/main.min.css

...replacing .sass with .scss if you're using scss instead of sass.

getting everything running.

ok, so now what you have to do is serve your files and get ready to build stuff. you need some kind of tool that behaves like a web server that you'll use to preview your website while you're working on it. for our purposes, the live-server npm package will do the trick! so npm i -g live-server, and then run live-server in your project directory. the site should just open in your browser, totally blank.

also — if you're using sass, now is the time to run that sass command written above. I like to make this command into an npm script in a package.json file, that way I can just type npm run sass or something and then I don't have to type out that whole long command. hell, you could even make it into a bash alias if you wanted to.

building a web component.

Now that the environment is prepared, it's time to open up your text editor and make a new web component. the baseline setup to create a new custom element for your component looks something like this:

class NewElement extends HTMLElement {}

what we're doing here is defining a new class that extends — or builds on top of — the functionality of a regular old html element.

we'll end up with an element that we can work with in the same way as all other html elements — but potentially much more powerful than the base set of elements, and greater than the sum of its parts. something reusable, modifiable, and extensible. a component that can become a part of a larger interface, just like a react component or something.

if you're using the setup from jpegzilla-init (which I recommend you do!), you'll see a file called component.js (or component.mjs). inside this file is a class that extends the native HTMLElement and gives it extra powers. the methods that you see in this class — toggleClass, setId, etc. — will be available on our new element just like regular html element methods, like querySelector.

either way, here's how we're going to create our own custom element. make a javascript file inside the folder you're storing your components inside. the name should be whatever your component is going to be called. inside that file, you're going to export a class of the same name that will extend an html element. if you're using jpegzilla-init, you'll be importing and extending the included Component class.

here's an example of what you should have after this step:

import Component from './component.mjs'
class NewElement extends Component {}
export default { element: NewElement, name: 'new-element' }

let's go through this line by line, since it's the basis of everything we'll be doing afterwards.

one: importing the base component. the base component is described above, and included in the base project. it's just an extension of javascript's HTMLElement class. if you don't feel like using my default project, you can extend HTMLElement yourself!

two: creating our new element class. in the second line we create a new element by extending the base component. again, this is just allowing us to add more functionality to the base Component class.

three: exporting the element. you'll notice that in the third line, we're exporting an object containing the actual class as well as the name of the class. the reason for this will become apparent when I show you how we're going to register each element that we create.

the mechanism for this registration is inside your main javascript file (assuming you're using the default project). you might be able to see what it's going to do, but don't worry if you don't understand it now. I'll explain it when it's time! for now, let's finish building our component.

writing the html.

the first step for writing the html structure in your custom component involves adding a method to your class called connectedCallback. this method fires whenever you add the custom element to the DOM, so this is where we can write the html. you just have to set this.innerHTML to your desired html.

connectedCallback() {
 this.innerHTML = <p>hello world</p>

now you have a custom element that displays the text 'hello world' (or whatever you decide to put in there). now we have to get the element to show up on our web page!

registering our element.

inside our main javascript file, you'll see a console log, an empty array, and a loop that iterates over that array. we can go ahead and remove the console log and import our element. something like this:

import NewElement from './components/newelement.mjs'

now, place NewElement into the elements array. this array is used as a collection of all our custom elements so that they can all be registered when the javascript loads. the actual registering is done by the customElements.define function in the loop! the function used to define custom elements enables our new element to be used like a regular element in our html document, under the name that we gave it. in this example, our element is called new-element. let's put that in our html document's <body> tag. something like this:


now, if you go back to your browser, you should see the element actually being rendered in the page. now you've gone through the whole process of creating and using a web component from beginning to end. nicely done!


This is only an introduction, so I think that at this point you have all you need to get started from scratch with web components. anything else involved with developing a site using web components isn't really specific to web components. meaning anything you can do with regular html / react / etc, you can do with web components.

I'll probably follow up this post with maybe some stuff about the shadow dom or whatever else I think could be useful or interesting. until then, have fun and good luck.

if you want to talk about this post or anything else, join my discord below and say something. I may respond instantaneously. don't be freaked out.

currently listening to:

- the flesh failures / let the sunshine in by melba moore

- HiDE iN SEW by BiS

- cold green eyes ft. roos denayer by station earth and roos denayer

- to the stage by asking alexandria

- 摩天動物園 city zoo by G.E.M.