Tabs in HTML?
I’ve been having some really interesting chats with Brian about tabs, markup, progressive enhancement and accessibility. Here’s a braindump of his current thinking which is well worth perusing.
I’ve been having some really interesting chats with Brian about tabs, markup, progressive enhancement and accessibility. Here’s a braindump of his current thinking which is well worth perusing.
A very handy web component from Paul—this works exactly like a regular YouTube embed, but is much more performant.
I’ve often said that the goal of a good library should be to make itself redundant. jQuery is the poster child for that, and this article points to web components as the way to standardise what’s already happening in JavaScript frameworks:
Remember when
document.querySelector
first got wide browser support and started to end jQuery’s ubiquity? It finally gave us a way to do natively what jQuery had been providing for years: easy selection of DOM elements. I believe the same is about to happen to frontend frameworks like Angular and React.
The article goes on to give a good technical overview of custom elements, templates, and the Shadow DOM, but I was surprised to see it making reference to the is
syntax for extending existing HTML elements—I’m pretty sure that that is, sadly, dead in the water.
You really don’t need jQuery any more …and that’s thanks to jQuery.
Here, the Github team talk through their process of swapping out jQuery for vanilla JavaScript, as well as their forays into web components (or at least the custom elements bit).
A good explanation of web components, complete with some code examples.
Web Components are not a single technology. Instead, they are series of browser standards defined by the W3C allowing developers to build components in a way the browser can natively understand. These standards include:
- HTML Templates and Slots – Reusable HTML markup with entry points for user-specific markup
- Shadow DOM – DOM encapsulation for markup and styles
- Custom Elements – Defining named custom HTML elements with specific behaviour
In which Brian takes a long winding route through an explanation of why the is
attribute for custom elements is dead before he demonstrates the correct way to use web components:
<!-- instead of writing this -->
<input type="radio" is="x-radio">
<!-- you write this -->
<x-radio>
<input type="radio">
</x-radio>
Sadly, none of the showcase examples I’ve seen for web components do this.
One of the things we’d hoped to enable via Web Components was a return to ctrl-r web development. At some level of complexity and scale we all need tools to help cope with code size, application structure, and more. But the tender, loving maintainance of babel and webpack and NPM configurations that represents a huge part of “front end development” today seems…punitive. None of this should be necessary when developing one (or a few) components and composing things shouldn’t be this hard. The sophistication of the tools needs to get back to being proportional with the complexity of the problem at hand.
I completely agree with Alex here. But that’s also why I was surprised and disheartened when I linked to Monica’s excellent introduction to web components that a package manager seemed to be a minimum requirement.
A really great introduction to web components by Monica. But I couldn’t help but be disheartened by this:
Web components tend to have dependencies on other web components, so you need a package manager to herd all them cats.
For me, this kind of interdependence lessens the standalone nature of web components—it just doesn’t feel quite so encapsulated to me. I know that this can be solved with build tools, but now you’ve got two problems (and one more dependency).
Really, really smart thinking from Paul here, musing on the power relationship between the creators of custom elements and the users of custom elements.
This is nice example of a web component that degrades gracefully—if custom elements aren’t supported, you still get the markdown content, just not converted to HTML.
<ah-markdown>
## Render some markdown!
</ah-markdown>
An in-depth look at the current Shadow DOM spec. It’s well-written but I don’t think this will really click with me until I start playing around with it for myself.
It’s good to see that the examples have some thought given to fallback content.
There’s also a corresponding tutorial on custom elements
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
.
<fancy-select></fancy-select>
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 span
s). 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:
@adactio I will go to every standards meeting until I get it done, because otherwise we are hosed for <form> and web components.
— Monica Dinosaurescu (@notwaldorf) June 16, 2016
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 span
s.
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:
<fancy-select>
<select>...</select>
</fancy-select>
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:
<o-gallery>
<img src="">
<img src="">
<img src="">
</o-gallery>
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.
Adam and I share the same hopes and frustrations with web components. They can be written in a resilient, layered way that allows for progressive enhancement, but just about every example out there demonstrates a “my way or the highway” approach to using them.
We were chatting about this in the Design Systems slack channel, and it helped clarify some of my thoughts. I’ll try to poop out a blog post about this soon.
A good introduction to custom elements, one piece of the web components stack.
That said, when using custom elements—or anything involving JavaScript, for that matter—you should always design experiences for progressive enhancement, and plan for the possibility that JavaScript isn’t enabled or available.
Hmmm …that’s kind of hard when JavaScript is required to make custom elements work at all.
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:
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:
<taco-button>...</taco-button>
…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.