A Modern Take on Browser Feature Readiness
Stumbling through old blog posts can lead to unexpected places. While researching @namespace for a CSS reference entry, I found myself on a post from 2010 about something called “HTML5 Readiness.” The project, built by Paul Irish and Divya Manian, visualized browser support for features like media queries, transitions, and the video and audio tags using a rainbow metaphor. Each browser that shipped a feature added a segment to the rainbow.
Looking back at that site now, it’s striking how much has changed. If the project were still active, every feature would be fully colored in. But it also raises a question: what would a modern equivalent look like, given the steady stream of new CSS and HTML features, many still unsupported across browsers?

That question led to building Web Readiness, a 2025 spin on the original concept. The site tracks the features I’m most excited about and displays their browser support in a similar rainbow layout. It’s still early, so the rainbow is sparse:

Data from the Web Features API
The obvious starting point for support data was the web-platform-dx repository, which powers the Chrome team’s <baseline-status> component. That component is designed for embedding support information directly into blog posts, but it would be tedious to use for a whole page of features.
Instead, I pulled data directly from the Web Features API at https://api.webstatus.dev/v1/features/ and rendered it myself.
Building Each Ray as a Web Component
The project was also an excuse to dig into Web Components. Each ray of the rainbow is a custom element with a short lifecycle:
- Get instantiated.
- Read the feature ID from a
data-featureattribute. - Fetch its data from the Web Features API.
- Display its support as a list.
The simplified code for that looks like this:
class BaselineRay extends HTMLElement {
constructor() {
super();
}
static get observedAttributes() {
return ["data-feature"];
}
attributeChangedCallback(property, oldValue, newValue) {
if (oldValue !== newValue) {
this[property] = newValue;
}
}
async #fetchFeature(endpoint, featureID) {
// Fetch Feature Function
}
async connectedCallback() {
// Call fetchFeature and Output List
}
}
customElements.define("baseline-ray", BaselineRay);
Animation Without a Library
Design isn’t my strong suit, so I compensated with motion. The page’s initial load uses timed keyframes for a welcome animation. The transition between the rainbow and list views is trickier, since it depends on user interaction and needs JavaScript.
Same-Document View Transitions seemed like the natural fit, but fighting browser default transitions and sparse documentation pushed me to the Web Animation API instead. It allows triggering transitions declaratively, which fits the use case well.
Positioning with sibling-index() and sibling-count()
To rotate and position each ray, I wanted the sibling-index() and sibling-count() CSS functions. They return an element’s index among siblings and total number of siblings. Chrome has announced intent to ship both, but they’re not broadly available yet.
Previous attempts at polyfilling these functions were CSS-only. This time I used a simpler JavaScript approach: observe the rays and set custom properties for index and count. It’s slightly overkill since the number of rays doesn’t change, but it’s straightforward:
const elements = document.querySelector(".rays");
const updateCustomProperties = () => {
let index = 0;
for (let element of elements.children) {
element.style.setProperty("--sibling-index", index);
index++;
}
elements.style.setProperty("--sibling-count", elements.children.length - 1);
};
updateCustomProperties();
const observer = new MutationObserver(updateCustomProperties);
const config = {attributes: false, childList: true, subtree: false};
observer.observe(elements, config);
Armed with those values, positioning each ray across a 180-degree arc becomes:
baseline-ray ul{
--position: calc(180 / var(--sibling-count) * var(--sibling-index) - 90);
--rotation: calc(var(--position) * 1deg);
transform: translateX(-50%) rotate(var(--rotation)) translateY(var(--ray-separation));
transform-origin: bottom center;
}
Hover State Without JavaScript
The browser captions below the rainbow have a hover effect: the matching browser’s ray segment brightens while the others fade. Since the captions aren’t siblings or parents of the rainbow in the DOM, this looked like a job for JavaScript. But the :has() selector handles it cleanly.
The rule checks whether the nearest common ancestor—possibly a <section>, <main>, or the whole <body>—contains a caption element being hovered. If so, it boosts the matching ray section’s size and reduces opacity on the rest.
Watching the Rainbow Grow
The plan is to let the site run and snapshot it periodically, like the original HTML5 Readiness project did. The goal is to see the rainbow fill in as features reach baseline support across browsers. If there’s a feature worth tracking that isn’t listed, the project is open to suggestions.



