I always thought that the semantically appropriate way to represent a rating (e.g. a star rating) is a <meter> element. They essentially convey the same type of information, the star rating is just a different presentation.
An example of a star rating widget, from Amazon
However, trying to style a <meter> element to look like a star rating is âŚtricky at best. Not to mention that this approach wonât even work in Shadow trees (unless you include the CSS in every single shadow tree).
So, I set out to create a proper web component for star ratings. The first conundrum was, how does this relate to a <meter> element?
A few days ago I asked Twitter a seemingly simple question (I meant aria-pressed, not aria-selected but Twitter doesnât allow editsâŚ):
For background, I was implementing a web component for an app Iâm working on at work and I was getting into some pretty weird rabbit holes with my approach of generating radios and labels.
Thatâs what I thought too. I had contorted my component to generate labels and radios in the Shadow DOM from buttons in the light DOM, which resulted in awkward code and awkward CSS, but I felt I was fighting the good fight and doing the best thing for accessibility.
All this was challenged when the actual accessibility expert, LĂŠonie Watson chimed in. For those of you who donât know her, she is pretty much the expert when it comes to web accessibility and standards. She is also visually impaired herself, giving her a firsthand experience many other a11y aficionados lack. Her recommendation was contrary to what most others were saying:
This week has been Yak Shaving Galore. It went a bit like this:
Iâve been working on a web component that I need for the project Iâm working on. More on that later, but letâs call it <x-foo> for now.
Of course that needs to be developed as a separate reusable library and released as a separate open source project. No, this is not the titular component, this was only level 1 of my multi-level yak shaving⌠đ¤Śđ˝ââď¸
I wanted to showcase various usage examples of that component in its page, so I made another component for these demos: <x-foo-live>. This demo component would have markup with editable parts on one side and the live rendering on the other side.
I wanted the editable parts to autosize as you type. Hey, Iâve written a library for that in the past, itâs called Stretchy!
But Stretchy was not written in ESM, nor did it support Shadow DOM. I must rewrite Stretchy in ESM and support Shadow DOM first! Surely it wonât take more than a half hour, itâs a tiny library.
(It took more than a half hour)
Ok, now I have a nice lilâ module, but I also need to export IIFE as well, so that itâs compatible with Stretchy v1. Letâs switch to Rollup and npm scripts and ditch Gulp.
Oh look, Stretchyâs CSS is still written in Sass, even though it doesnât really need it now. Letâs rewrite it to use CSS variables, use PostCSS for nesting, and use conic-gradient() instead of inline SVG data URIs.
Ok, Stretchy v2 is ready, now I need to update its docs. Oooh, it doesnât have a README? I should add one. But I donât want to duplicate content between the page and the README. Hmmm, if onlyâŚ
I know! Iâll make a web component for rendering both inline and remote Markdown! I have an unfinished one lying around somewhere, surely it wonât take more than a couple hours to finish it?
Web Components had so much potential to empower HTML to do more, and make web development more accessible to non-programmers and easier for programmers. Remember how exciting it was every time we got new shiny HTML elements that actually do stuff? Remember how exciting it was to be able to do sliders, color pickers, dialogs, disclosure widgets straight in the HTML, without having to include any widget libraries?
The promise of Web Components was that weâd get this convenience, but for a much wider range of HTML elements, developed much faster, as nobody needs to wait for the full spec + implementation process. Weâd just include a script, and boom, we have more elements at our disposal!
Or, that was the idea. Somewhere along the way, the space got flooded by JS frameworks aficionados, who revel in complex APIs, overengineered build processes and dependency graphs that look like the roots of a banyan tree.
Perusing the components on webcomponents.org fills me with anxiety, and Iâm perfectly comfortable writing JS â I write JS for a living! What hope do those who canât write JS have? Using a custom element from the directory often needs to be preceded by a ritual of npm flugelhorn, import clownshoes, build quux, all completely unapologetically because âhere is my truckload of dependencies, yeah, whatâ. Many steps are even omitted, likely because they are âobviousâ. Often, you wade through the maze only to find the component doesnât work anymore, or is not fit for your purpose.
Besides setup, the main problem is that HTML is not treated with the appropriate respect in the design of these components. They are not designed as closely as possible to standard HTML elements, but expect JS to be written for them to do anything. HTML is simply treated as a shorthand, or worse, as merely a marker to indicate where the element goes in the DOM, with all parameters passed in via JS. I recall a wonderful talk by Jeremy Keith a few years ago about this very phenomenon, where he discussed this e-shop Web components demo by Google, which is the poster child of this practice. These are the entire contents of its <body> element:
If this is how Google is leading the way, how can we hope for contributors to design components that follow established HTML conventions?
Jeremy criticized this practice from the aspect of backwards compatibility: when JS is broken or not enabled, or the browser doesnât support Web Components, the entire website is blank. While this is indeed a serious concern, my primary concern is one of usability: HTML is a lower barrier to entry language. Far more people can write HTML than JS. Even for those who do eventually write JS, it often comes after spending years writing HTML & CSS.
If components are designed in a way that requires JS, this excludes thousands of people from using them. And even for those who can write JS, HTML is often easier: you donât see many people rolling their own sliders or using JS-based ones once <input type="range"> became widely supported, right?
Even when JS is unavoidable, itâs not black and white. A well designed HTML element can reduce the amount and complexity of JS needed to a minimum. Think of the <dialog> element: it usually does require *some* JS, but itâs usually rather simple JS. Similarly, the <video> element is perfectly usable just by writing HTML, and has a comprehensive JS API for anyone who wants to do fancy custom things.
The other day I was looking for a simple, dependency free, tabs component. You know, the canonical example of something that is easy to do with Web Components, the example 50% of tutorials mention. I didnât even care what it looked like, it was for a testing interface. I just wanted something that is small and works like a normal HTML element. Yet, it proved so hard I ended up writing my own!
Iâm not sure if this is a design issue, or a documentation issue. Perhaps for many of these web components, there are easier ways to use them. Perhaps there are vanilla web components out there that I just canât find. Perhaps Iâm looking in the wrong place and there is another directory somewhere with different goals and a different target audience.
But if not, and if Iâm not alone in feeling this way, we need a directory of web components with strict inclusion criteria:
Plug and play. No dependencies, no setup beyond including one <script> tag. If a dependency is absolutely needed (e.g. in a map component it doesnât make sense to draw your own maps), the component loads it automatically if itâs not already loaded.
Accessible by default via sensible ARIA defaults, just like normal HTML elements.
Themable via ::part(), selective inheritance and custom properties. Very minimal style by default. Normal CSS properties should just âworkâ to the the extent possible.
Only one component of a given type in the directory, that is flexible and extensible and continuously iterated on and improved by the community. Not 30 different sliders and 15 different tabs that users have to wade through. No branding, no silos of âcomponent librariesâ. Only elements that are designed as closely as possible to what a browser would implement in every way the current technology allows.
I would be up for working on this if others feel the same way, since that is not a project for one person to tackle. Whoâs with me?
UPDATE: Wow this post blew up! Thank you all for your interest in participating in a potential future effort. Iâm currently talking to stakeholders of some of the existing efforts to see if there are any potential collaborations before I go off and create a new one. Follow me on Twitter to hear about the outcome!