Chris’ Corner: Very Simple Web Components

Let’s do a Web Components issue this week. We gotta do it. As Scott Vandehey says: HTML Web Components Are Having a Moment. Scott links to a pretty healthy stew of other people’s writing where they have their own ah-ha moments where they can picture the usefulness of native Web Components in their own work.

I can feel it, as this has been creeping up on me as well. Here’s a line of thinking that might get you there:

  • You have a bit of HTML
  • You want to apply some functionality to it
  • So wrap it in a Web Component

Honestly I think you can compare it to jQuery style thinking. “Find something; do something” — except you’ve already found it, you just need to do it.

Now, before I seem to be reductionist, Web Components can get a lot more complicated. You can opt-in to the Shadow DOM approach, which unlocks slots and more complex templating, as well as true encapsulation and such. But you don’t have to do that, you can level up to that as needed. The very basic use-case (and wow isn’t the web good at this?!) is useful, powerful, needs limited boilerplate, and no libraries or build steps.

This example is, uhh, pretty simple, but it’s an example of how my mind has flipped a bit. I wanted to make a box you could resize, that’s exactly 9:16 aspect ratio, and it would tell you the pixel dimensions. I need a little bit of HTML, a little bit of CSS, and a little bit of JavaScript. I don’t need to do that as a Web Component, but doing so is barely any more work, and helps more tightly couple the HTML and JavaScript in a way that really helps communicate intention.

I don’t have any grand plans, but I could now easily make this re-usable across, well, anywhere, by making the JavaScript importable and documenting the intended HTML to use. I should probably bundle the CSS too, but that’s a story for another day.


Let’s keep this whole “Web Components can be pretty darn simple” train rolling a little bit. In fact, I think it was Jim Nielsen who kicked the first domino on Web Components lately getting people thinking about them differently in Using Web Components on My Icon Galleries Websites.

Imagine a grid of icons. Jim wanted on-page controls, in the form of a <input type="range"> to control their size. By using a web component, he can insert that input only when the JavaScript executes, which is ideal. Then all the event listening on that range slider is also all bundled into that web component. All the while, the HTML guts of the web component, which is what will render if JavaScript doesn’t, is still a perfectly serviceable grid of icons.

This is a nice approach (over stringing together a bunch of functions in JS file) because it feels more encapsulated. All related logic and DOM manipulations are “under one roof”. Plus it works as a progressive enhancement: if the JS fails to load (or the user has it disabled) they can still navigate through different pages with lists of icons (and the <icon-list> component just works like a <div>). And if JS works, the <icon-list> component acts like a <div> with interactive super powers layered in.


Dave Rupert’s Web Component version of FitVids is even more straightforward. You probably have videos on your sites that are <iframe>s of stuff like YouTube and Vimeo. Just wrap ’em in <fit-vids> and call it a day.

<!-- import custom element -->
<script type="module" src="fit-vids.js"></script>

<!-- wrap embeds in fit-vids custom element -->
<fit-vids>
  <iframe src="http://youtube.com?v=123"></iframe>
</fit-vids>

If the JavaScript doesn’t load, all good, video is still there.

More, if somehow, say via a fetch request or the like, more videos get injected onto the page, there is no need to re-call any JavaScript to make these work. The way connectedCallback works they’ll just do their thing automatically when they arrive in the DOM.


I’ll say I’m a fan of the “Light DOM Only” approach to Web Components. But there are some relatively big things you give up when you don’t use the Shadow DOM. Namely: slots. Slots is a pretty sweet mechanism for taking the “guts” HTML of a Web Component and slotting it properly into a likely-more-complicated bit of template HTML. This means that your fallback HTML can be simpler and possibly more appropriate.

Cory LaViska explains it well, here’s some usage:

<my-button>
  Click me
  <img slot="icon" src="..." alt="...">
</my-button>

Which gets smushed with:

<template>
  #shadow-root
    <button type="button">
      <span class="icon">
        <slot name="icon"></slot>
      </span>

      <span class="label">
        <slot></slot>
      </span>
    </button>
</template>

You can imagine how the <img> there makes it into the <slot> with a matching name. And then rest of the content goes into the default slot.

Cory’s article is actually about extending this concept and building out HTML with as many slots as you need, as powered by attributes. It’s clever go read it.


Speaking of parameters, that’s an approach that some web components take. Rather than any guts HTML at all, you say what you want of the component via attributes on the element. That’s a rather JavaScript-framework-y way of doing things. An example of this is <lite-youtube> which you use entirely with attributes:

<lite-youtube 
  videoid="ogfYd705cRs" 
  playlabel="Play: Keynote (Google I/O '18)"></lite-youtube>

That doesn’t prescribe light or shadow DOM, but it does mean that no-JavaScript means nothing rendered at all.

Unless you’ve figured out some kind of server-side rendering, which is another whole bag of peanuts.


So we’ve covered lots of options already so far:

  1. All HTML needed provided in guts / Some HTML provided (likely fallback or designed for slots) / No HTML provided
  2. Light DOM / Shadow DOM
  3. Elegant Fallback / Some Fallback / No Fallback
  4. Attribute-Heavy / Attribute-Light / No Attributes

And there are more

  1. Use Framework / No Framework
  2. Lazy Load / Eager Load
  3. Client-Side Render / Server-Side Render (via Build Step)
  4. Styles via external stylesheet / Styles baked into JavaScript / No Styles

The list could go on.

Zach Leatherman attempted to simplify the taxonomy down to HTML Web Components and JavaScript Web Components. I think that’s smart to try to smash down the complexity here, but also think that’s maybe too far. Someone could probably make a decision tree that paints a middle ground taxonomy.