Tags: customelements



Extensible web components

Adam Onishi has written up his thoughts on web components and progressive enhancements, following on from a discussion we were having on Slack. He shares a lot of the same frustrations as I do.

Two years ago, I said:

I have conflicting feelings about Web Components. I am simultaneously very excited and very nervous.

I still feel that way. In theory, web components are very exciting. In practice, web components are very worrying. The worrying aspect comes from the treatment of backwards compatibility.

It all comes down to the way custom elements work. When you make up a custom element, it’s basically a span.


Then, using JavaScript with ShadowDOM, templates, and the other specs that together make up the web components ecosystem, you turn that inert span-like element into something all-singing and dancing. That’s great if the browser supports those technologies, and the JavaScript executes successfully. But if either of those conditions aren’t met, what you’re left with is basically a span.

One of the proposed ways around this was to allow custom elements to extend existing elements (not just spans). The proposed syntax for this was an is attribute.

<select is="fancy-select">...</select>

Browser makers responded to this by saying “Nah, that’s too hard.”

To be honest, I had pretty much given up on the is functionality ever seeing the light of day, but Monica has rekindled my hope:

Still, I’m not holding my breath for this kind of declarative extensibility landing in browsers any time soon. Instead, a JavaScript-based way of extending existing existing elements is currently the only way of piggybacking on all the accessible behavioural goodies you get with native elements.

class FancySelect extends HTMLSelectElement

But this imperative approach fails completely if custom elements aren’t supported, or if the JavaScript fails to execute. Now you’re back to having spans.

The presentation on web components at the Progressive Web Apps Dev Summit referred to this JavaScript-based extensibility as “progressively enhancing what’s already available”, which is a bit of a stretch, given how completely it falls apart in older browsers. It was kind of a weird talk, to be honest. After fifteen minutes of talking about creating elements entirely from scratch, there was a minute or two devoted to the is attribute and extending existing elements …before carrying as though those two minutes never happened.

But even without any means of extending existing elements, it should still be possible to define custom elements that have some kind of fallback in non-supporting browsers:


In that situation, you at least get a regular ol’ select element in older browsers (or in modern browsers before the JavaScript kicks in and uplifts the custom element).

Adam has a great example of this in his post:

I’ve been thinking of a gallery component lately, where you’d have a custom element, say <o-gallery> for want of a better example, and simply populate it with images you want to display, with custom elements and shadow DOM you can add all the rest, controls/layout etc. Markup would be something like:

 <img src="">
 <img src="">
 <img src="">

If none of the extra stuff loads, what do we get? Well you get 3 images on the page. You still get the content, but just none of the fancy interactivity.

Yes! This, in my opinion, is how we should be approaching the design of web components. This is what gets me excited about web components.

Then I look at pretty much all the examples of web components out there and my nervousness kicks in. Hardly any of them spare a thought for backwards-compatibility. Take a look, for example, at the entire contents of the body element for the Polymer Shop demo site:

<shop-app unresolved="">SHOP</shop-app>

This seems really odd to me, because I don’t think it’s a good way to “sell” a technology.

Compare service workers to web components.

First of all, ask the question “who benefits from this technology?” In the case of service workers, it’s the end users. They get faster websites that handle network failure better. In the case of web components, there are no direct end-user benefits. Web components exist to make developers lives easier. That’s absolutely fine, but any developer convenience gained by the use of web components can’t come at the expense of the user—that price is too high.

The next question we usually ask when we’re evaluating a technology is “how well does it work?” Personally, I think it’s just as important to ask “how well does it fail?”

Service workers work well and fail well. If a browser supports service workers, the user gets all the benefits. If a browser doesn’t support service workers, the user get the same experience they would have always had.

Web components (will) work well, but fail badly. If a browser supports web components, the user gets the experience that the developer has crafted using these new technologies. If a browser doesn’t support web components, the user gets …probably nothing. It depends on how the web components have been designed.

It’s so much easier to get excited about implementing service workers. You’ve literally got nothing to lose and everything to gain. That’s not the case with web components. Or at least not with the way they are currently being sold.

See, this is why I think it’s so important to put some effort into designing web components that have some kind of fallback. Those web components will work well and fail well.

Look at the way new elements are designed for HTML. Think of complex additions like canvas, audio, video, and picture. Each one has been designed with backwards-compatibility in mind—there’s always a way to provide fallback content.

Web components give us developers the same power that, up until now, only belonged to browser makers. Web components also give us developers the same responsibilities as browser makers. We should take that responsibility seriously.

Web components are supposed to be the poster child for The Extensible Web Manifesto. I’m all for an extensible web. But the way that web components are currently being built looks more like an endorsement of The Replaceable Web Manifesto. I’m not okay with a replaceable web.

Here’s hoping that my concerns won’t be dismissed as “piffle and tosh” again by the very people who should be thinking about these issues.


Contrary to popular belief, web standards aren’t created by a shadowy cabal and then handed down to browser makers to implement. Quite the opposite. Browser makers come together in standards bodies and try to come to an agreement about how to collectively create and implement standards. That keeps them very busy. They don’t tend to get out very often, but when they do, the browser/standards makers have one message for developers: “We want to make your life better, so tell us what you want and that’s what we’ll work on!”

In practice, this turns out not to be the case.

Case in point: responsive images. For years, this was the number one feature that developers were crying out for. And yet, the standards bodies—and, therefore, browser makers—dragged their heels. First they denied that it was even a problem worth solving. Then they said it was simply too hard. Eventually, thanks to the herculean efforts of the Responsive Images Community Group, the browser makers finally began to work on what developers had been begging for.

Now that same community group is representing the majority of developers once again. Element queries—or container queries—have been top of the wish list of working devs for quite a while now. The response from browser makers is the same as it was for responsive images. They say it’s simply too hard.

Here’s a third example: web components. There are many moving parts to web components, but one of the most exciting to developers who care about accessibility and backwards-compatibility is the idea of extending existing elements:

It’s my opinion that, for as long as there is a dependence on JS for custom elements, we should extend existing elements when writing custom elements. It makes sense for developers, because new elements have access to properties and methods that have been defined and tested for many years; and it makes sense for users, as they have fallback in case of JS failure, and baked-in accessibility fundamentals.

So instead of having to create a whole new element from scratch like this:

<taco-button>Click me!</taco-button>

…you could piggy-back on an existing element like this:

<button is="taco-button">Click me!</button>

That way, you get the best of both worlds: the native semantics of button topped with all the enhancements you want to add with your taco-button custom element. Brilliant! Github is using this to extend the time element, for example.

I’m not wedded to the is syntax, but I do think it’s vital that there is some declarative mechanism to extend existing elements instead of creating every custom element from scratch each time.

Now it looks like that’s the bit of web components that isn’t going to make the cut. Why? Because browser makers say it’s simply too hard.

As Bruce points out, this is in direct conflict with the design principles that are supposed to be driving the creation and implementation of web standards.

It probably wouldn’t bother me so much except that browser makers still trot out the party line, “We want to hear what developers want!” Their actions demonstrate that this claim is somewhat hollow.

I don’t hold out much hope that we’ll get the ability to extend existing elements for web components. I think we can still find ways to piggy-back on existing semantics, but it’s going to take more work:

<taco-button><button>Click me!</button></taco-button>

That isn’t very elegant and I can foresee a lot of trickiness trying to sift the fallback content (the button tags) from the actual content (the “Click me!” text).

But I guess that’s what we’ll be stuck with. The alternative is simply too hard.


I’ve said it before, but I’m going to reiterate my conflicted feelings about Web Components:

I have conflicting feelings about Web Components. I am simultaneously very excited and very nervous.

There are broadly two ways that they could potentially be used:

  1. Web Components are used by developers to incrementally add more powerful elements to their websites. This evolutionary approach feels very much in line with the thinking behind the extensible web manifesto. Or:
  2. Web Components are used by developers as a monolithic platform, much like Angular or Ember is used today. The end user either gets everything or they get nothing.

The second scenario is a much more revolutionary approach—sweep aside the web that has come before, and usher in a new golden age of Web Components. Personally, I’m not comfortable with that kind of year-zero thinking. I prefer evolution over revolution:

Revolutions sometimes change the world to the better. Most often, however, it is better to evolve an existing design rather than throwing it away. This way, authors don’t have to learn new models and content will live longer. Specifically, this means that one should prefer to design features so that old content can take advantage of new features without having to make unrelated changes. And implementations should be able to add new features to existing code, rather than having to develop whole separate modes.

The evolutionary model is exemplified by the design of HTML 5.

The revolutionary model is exemplified by the design of XHTML 2.

I really hope that the Web Components model goes down the first route.

Up until recently, my inner Web Components pendulum was swinging towards the hopeful end of my spectrum of anticipation. That was mainly driven by the ability of custom elements to extend existing HTML elements.

So, for example, instead of creating a new element like this:


…you can piggyback off the existing semantics of the button element like this:

<button is="taco-button">...</button>

For a real-world example, see Github’s use of <time is="time-ago">.

I wrote about creating responsible Web Components:

That means we can use web components as a form of progressive enhancement, turbo-charging pre-existing elements instead of creating brand new elements from scratch. That way, we can easily provide fallback content for non-supporting browsers.

I’d like to propose that a fundamental principle of good web component design should be: “Where possible, extend an existing HTML element instead of creating a new element from scratch.”

Peter Gasston also has a great post on best practice for creating custom elements:

It’s my opinion that, for as long as there is a dependence on JS for custom elements, we should extend existing elements when writing custom elements. It makes sense for developers, because new elements have access to properties and methods that have been defined and tested for many years; and it makes sense for users, as they have fallback in case of JS failure, and baked-in accessibility fundamentals.

But now it looks like this superpower of custom elements is being nipped in the bud:

It also does not address subclassing normal elements. Again, while that seems desirable the current ideas are not attractive long term solutions. Punting on it in order to ship a v1 available everywhere seems preferable.

Now, I’m not particularly wedded to the syntax of using the is="" attribute to extend existing elements …but I do think that the ability to extend existing elements declaratively is vital. I’m not alone, although I may very well be in the minority.

Bruce has outlined some use cases and Steve Faulkner has enumerated the benefits of declarative extensibility:

I think being able to extend existing elements has potential value to developers far beyond accessibility (it just so happens that accessibility is helped a lot by re-use of existing HTML features.)

Bruce concurs:

Like Steve, I’ve no particularly affection (or enmity) towards the <input type="radio" is="luscious-radio"> syntax. But I’d like to know, if it’s dropped, how progressive enhancement can be achieved so we don’t lock out users of browsers that don’t have web components capabilities, JavaScript disabled or proxy browsers. If there is a concrete plan, please point me to it. If there isn’t, it’s irresponsible to drop a method that we can see working in the example above with nothing else to replace it.

He adds:

I also have a niggling worry that this may affect the uptake of web components.

I think he’s absolutely right. I think there are many developers out there in a similar position to me, uncertain exactly what to make of this new technology. I was looking forward to getting really stuck into Web Components and figuring out ways of creating powerful little extensions that I could start using now. But if Web Components turn out to be an all-or-nothing technology—a “platform”, if you will—then I will not only not be using them, I’ll be actively arguing against their use.

I really hope that doesn’t happen, but I must admit I’m not hopeful—my inner pendulum has swung firmly back towards the nervous end of my anticipation spectrum. That’s because I’m getting the distinct impression that the priorities being considered for Web Components are those of JavaScript framework creators, rather than web developers looking to add incremental improvements while maintaining backward compatibility.

If that’s the case, then Web Components will be made in the image of existing monolithic MVC frameworks that require JavaScript to do anything, even rendering content. To me, that’s a dystopian vision, one I can’t get behind.