CSS Module 1 – How CSS works
CSS browser support: Baseline and the Snapshot
What Baseline's limited, newly and widely available mean, how they differ from CSS Snapshot 2026, and how to decide when a feature needs a fallback.
What you will learn
- Read a feature's Baseline status (limited, newly available, widely available) and what it means for production
- Distinguish specification stability (CSS Snapshot 2026) from browser support (Baseline)
- Decide whether a feature needs nothing, a fallback, a feature query or should wait
Before you start
What you’ll learn · Before you start
What you will learn
- Read a feature's Baseline status (limited, newly available, widely available) and what it means for production
- Distinguish specification stability (CSS Snapshot 2026) from browser support (Baseline)
- Decide whether a feature needs nothing, a fallback, a feature query or should wait
Before you start
On this page
Before you use a CSS feature on a real site, you need to know which browsers support it. The quickest dependable answer is the feature’s Baseline status, which MDN’s reference pages and Can I Use show for each feature. Baseline comes from the web-features project of the W3C’s WebDX Community Group and has three levels. Limited availability: at least one of the main browsers does not support it yet. Newly available: the current versions of Chrome, Edge, Firefox and Safari, on computers and on phones, all support it. Widely available: it has been newly available for 30 months, long enough for most people’s browsers to have caught up.
Baseline is about browsers, not about specifications. CSS Snapshot 2026 sorts specifications by how stable they are, and the two answers often differ. This lesson reads real statuses from the web-features data, shows why a test engine is not a browser, and ends with a rule for what to do with each status.
The three Baseline statuses
Baseline is computed for seven browsers, the core browser set: Chrome on computers and on Android, Edge on computers, Firefox on computers and on Android, and Safari on macOS and on iOS.
- Limited availability. At least one core browser has not shipped the feature, or ships only part of it.
- Newly available. The current stable release of every core browser supports it. The day the last of them shipped it is the feature’s keystone date, and features are grouped into Baseline years by that date: a feature that became newly available in 2023 is part of “Baseline 2023”.
- Widely available. At least 30 months have passed since the keystone date, and the latest Firefox Extended Support Release supports the feature too. By then, most visitors have updated to a browser that has it.
How :has() became Baseline
Text description of the diagram
The diagram follows the :has() selector through the Baseline statuses, from top to bottom, using the web-features data.
- In 2022, Safari 15.4 and Safari on iOS 15.4 shipped :has().
- Later in 2022, Chrome 105, Chrome Android 105 and Edge 105 shipped it.
- The feature had limited availability, because Firefox did not have it yet.
- In 2023, Firefox 121 and Firefox for Android 121 shipped it, the last two of the seven core browsers. The release date of that last browser is the feature's keystone date.
- From that date the feature was Baseline newly available, part of Baseline 2023.
- 30 months later, in 2026, it became Baseline widely available.
The definition is deliberately narrow. Baseline does not promise that every visitor has a browser with the feature, and it says nothing about screen readers or other assistive technology, which it leaves out of scope. Browsers outside the core set, such as other Chromium-based browsers, usually follow the engine they are built on, but the Baseline project itself says to test in them when they make up a large share of your visitors, and to treat app webviews as a case of their own.
Real statuses from the web-features data
The web-features project publishes its data as an npm package, and it is the source of the Baseline badges on MDN
and Can I Use.
The program below reads a small extract of web-features 3.42.0, saved beside it as features.json, covering 18
features this track teaches:
// The Baseline status of features this track uses, read from features.json: a few fields of web-features' data
// (the source of Baseline statuses), kept beside this file. It prints each feature's status and Baseline year,
// checks the 30-month rule against the data, says what a limited feature is missing, and sorts the features for a
// site that has to work for every visitor today.
import { readFileSync } from "node:fs";
const data = JSON.parse(readFileSync("features.json", "utf8"));
const features = Object.values(data.features);
const STATUS = { high: "widely available", low: "newly available", false: "limited availability" };
const year = (date) => (date ? date.slice(0, 4) : "-");
const monthsBetween = (a, b) => {
const [ya, ma, da] = a.split("-").map(Number);
const [yb, mb, db] = b.split("-").map(Number);
return (yb - ya) * 12 + (mb - ma) - (db >= da ? 0 : 1);
};
// Print a list of names over several lines, each at most 68 characters wide.
function wrap(prefix, names) {
const lines = [];
let line = prefix;
for (const [i, name] of names.entries()) {
const word = name + (i < names.length - 1 ? "," : "");
if (line.length + word.length + 1 > 68 && line.trim()) {
lines.push(line);
line = " ";
}
line += (line.endsWith(" ") ? "" : " ") + word;
}
lines.push(line);
return lines.join("\n");
}
console.log(`Baseline status of ${features.length} features, from ${data.source.split(" (")[0]}\n`);
console.log(`${"feature".padEnd(26)}${"status".padEnd(22)}Baseline year`);
for (const f of features) console.log(`${f.name.padEnd(26)}${STATUS[f.baseline].padEnd(22)}${year(f.baseline_low_date)}`);
// Widely available is defined as 30 months after newly available. Check that the data agrees.
const wide = features.filter((f) => f.baseline === "high");
const thirty = wide.filter((f) => monthsBetween(f.baseline_low_date, f.baseline_high_date) === 30);
console.log(`\nWidely available 30 months after newly available: ${thirty.length} of ${wide.length} features`);
// A limited feature lacks complete support in at least one of the seven core browsers.
console.log("\nLimited availability: where complete support is missing");
for (const f of features.filter((x) => x.baseline === false)) {
const missing = Object.keys(data.browsers).filter((b) => !f.support[b]).map((b) => data.browsers[b]);
console.log(wrap(` ${f.name}: missing in`, missing));
if (f.parts && f.parts.interoperable > 0) {
console.log(` (${f.parts.interoperable} of its ${f.parts.total} parts already work in every core browser)`);
}
}
// One way to decide, for a site that must work for every visitor today.
const names = (status) => features.filter((f) => f.baseline === status).map((f) => f.name);
console.log("\nFor a site that must work for every visitor today");
console.log(wrap(" use it:", names("high")));
console.log(wrap(" use it with a fallback, or as an extra:", names("low")));
console.log(wrap(" wait, or add it as an extra behind @supports:", names(false))); Output
Baseline status of 18 features, from web-features 3.42.0
feature status Baseline year
Flexbox widely available 2015
Grid widely available 2017
Logical properties widely available 2021
Cascade layers widely available 2022
Container queries (size) widely available 2023
Oklab and OkLCh widely available 2023
Subgrid widely available 2023
Nesting widely available 2023
:has() widely available 2023
text-wrap: balance newly available 2024
light-dark() newly available 2024
Popover newly available 2025
View transitions newly available 2025
@scope newly available 2026
contrast-color() newly available 2026
Anchor positioning limited availability -
if() limited availability -
corner-shape limited availability -
Widely available 30 months after newly available: 9 of 9 features
Limited availability: where complete support is missing
Anchor positioning: missing in Chrome, Chrome Android, Edge,
Firefox, Firefox for Android
(323 of its 325 parts already work in every core browser)
if(): missing in Firefox, Firefox for Android, Safari,
Safari on iOS
corner-shape: missing in Firefox, Firefox for Android, Safari,
Safari on iOS
For a site that must work for every visitor today
use it: Flexbox, Grid, Logical properties, Cascade layers,
Container queries (size), Oklab and OkLCh, Subgrid, Nesting,
:has()
use it with a fallback, or as an extra: text-wrap: balance,
light-dark(), Popover, View transitions, @scope,
contrast-color()
wait, or add it as an extra behind @supports: Anchor positioning,
if(), corner-shape
Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node baseline_report.mjs
The line after the table is a check, not a definition copied from the documentation: for every widely available
feature in the extract, the data’s two dates are exactly 30 months apart. :has() and nesting, both part of Baseline
2023, reached widely available in 2026, so a site that wants only widely available features can now use both without
fallbacks.
Anchor positioning shows why a status covers a whole feature. Of its 325 parts, the separate properties, values and
script interfaces that the data tracks, 323 already work in the current release of every core browser, among them
anchor-name, position-anchor, position-area and the anchor() function, which together place a tooltip next to
its anchor. The two missing pieces are two values of position-visibility, which only Safari 27 has.
That one gap keeps the whole feature at limited availability. If your design uses only parts that are already newly
available, judge it by those parts, which MDN’s browser compatibility tables list one by one.
Specification stability is a different question
The CSS Working Group’s yearly snapshot answers another question: how settled a specification is, for the people who build browsers. It does not look at which browsers have shipped anything. The two scales often disagree. Here is where CSS Snapshot 2026 places each feature’s specification, and the feature’s status in web-features 3.42.0:
- Flexbox: Flexbox Level 1 is part of the official definition of CSS; widely available.
- Subgrid: Grid Level 2 is a reliable Candidate Recommendation; widely available.
- Cascade layers: Cascade Level 5 is a reliable Candidate Recommendation; widely available.
:has(): Selectors Level 4 is listed under rough interoperability; widely available.- Nesting: Nesting Level 1 is listed under rough interoperability; widely available.
- View transitions: View Transitions Level 1 is listed as fairly stable; newly available.
@scope: Cascade Level 6 is not in the snapshot; newly available.- Anchor positioning: Anchor Positioning Level 1 is not in the snapshot; limited availability.
:has() is a good example. Selectors Level 4 is still listed among modules with “rough interoperability”, because
details of the specification are not finished, and the snapshot separately lists :has() among the features cleared
for wide release before their specification is final. Browsers shipped it, so for an author it now has the same
status as Flexbox: widely available.
The reverse also happens: a stable specification can describe something no browser supports yet. For deciding what to
use on a site, ask Baseline; read the snapshot to learn which specifications are likely to change.
What browser makers are working on: Interop 2026
Every year, engineers from the companies behind the browser engines, including Apple, Google, Microsoft and Mozilla,
agree on a list of focus areas to make work the same everywhere, measured by shared tests on the Interop dashboard. The
CSS focus areas of Interop 2026 are anchor positioning, attr(), contrast-color(), container style queries, custom
highlights, dialogs and popovers, media pseudo-classes such as :playing, scroll-driven animations, scroll snap,
shape(), view transitions and zoom. A feature on that list is likely to move towards Baseline, but the list is a
plan, not a support status: until the data says newly available, treat the feature as limited.
A test engine is not a browser
Automated tests often run in the engines of a tool such as Playwright, and it is tempting to read their results as
browser support. Playwright’s own documentation says its WebKit is built from the latest WebKit sources, often before
those changes reach Safari. Here is one check, CSS.supports() for four limited features, run in Playwright 1.63.0’s
three engines (Chromium 153, Firefox 155 and WebKit 26.6), next to what web-features says about Safari:
| Check | Accepted by | Safari, per web-features |
|---|---|---|
corner-shape: squircle |
Chromium, WebKit | Not supported |
if() |
Chromium, WebKit | Not supported |
attr() with a type |
Chromium, Firefox, WebKit | Not supported |
position-visibility: anchor-valid |
WebKit | Safari 27 only |
Playwright’s WebKit accepted three features that no released Safari supports. A test that passes there does not show that Safari supports a feature, so support claims in this track come from the web-features data, never from test runs.
Deciding what to do with a feature
Combine the status with one more question: does the page still work for someone whose browser lacks the feature?
- Widely available: use it, whether or not the page depends on it.
- Newly available: if the page works without it, use it as an extra, which older browsers skip; if the page needs it, write a fallback first and the newer value after it.
- Limited availability: if the page works without it, add it behind an
@supportsquery; if the page needs it, wait, or reach the same result another way.
Here are those cases in one stylesheet:
/* Widely available: use it as it is. */
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
gap: 1rem;
}
/* Newly available, and the page works without it: an extra that older browsers skip. */
.card-title {
text-wrap: balance;
}
/* Newly available, and the page needs a value: a fallback first, the newer value after it. */
:root {
color-scheme: light dark;
}
.card {
color: #1e293b;
background: #f1f5f9;
color: light-dark(#1e293b, #e2e8f0);
background: light-dark(#f1f5f9, #1e293b);
border-radius: 12px;
}
/* Limited availability: only behind a feature query, together with the change it depends on. */
@supports (corner-shape: squircle) {
.card {
border-radius: 24px;
corner-shape: squircle;
}
} - Grid is widely available, so it is used as it is.
text-wrap: balanceis newly available, but a title that wraps the ordinary way is still fine, so it needs no fallback: older browsers drop the declaration and nothing breaks.light-dark()is newly available and the card needs colours, so a plain colour comes first. A browser withoutlight-dark()drops the second declarations and keeps the first, which is the error recovery from the first lesson of this module at work.corner-shapehas limited availability, and it changes how a radius looks, so the larger radius that only suits squircle corners goes inside@supports (corner-shape: squircle)with it. A browser that fails the query keeps the 12px rounded corners. Run in Playwright’s three engines, the query matched in Chromium 153 and in WebKit 26.6, and not in Firefox 155; Safari, per the data, would not match it either.
A rule of thumb for a public site: widely available features need no thought, newly available features need a fallback whenever the page depends on them, and limited ones are extras at most. A site whose visitors you know, such as an internal tool used only with the latest Chrome, can go further; check your own analytics before you do.
Try it: the same stylesheet in two browsers
Open the HTML, CSS & JS Playground in two different browsers, for example Chrome and Firefox, or a phone and a
computer. Paste support-tiers.css into each with a few cards, such as
<div class="cards"><div class="card"><h2 class="card-title">…</h2></div></div>, and compare them. Inspect a card
in each browser: in a browser without corner-shape, the @supports rule does not appear in the Styles pane at all,
and the card keeps its 12px radius. Then switch the operating system or DevTools to the dark colour scheme and watch
light-dark() change the colours. The quiz below then asks you to classify six uses of features for a site that must
work for every visitor.
Check yourself
10 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.
Interview questions
What is the difference between Baseline “newly available” and “widely available”?
Both describe browser support in the Baseline core set: Chrome and Edge on computers, Chrome on Android, Firefox on computers and Android, and Safari on macOS and iOS. Newly available means the current stable release of every one of them supports the feature; the day the last one shipped it is the keystone date. Widely available means at least 30 months have passed since then, and the latest Firefox Extended Support Release supports it too, so most visitors have updated to a browser that has it. In practice, a newly available feature is safe for visitors on current browsers but needs a fallback when the page depends on it; a widely available one can be used without one. Neither status covers assistive technology or promises every last visitor.
Key takeaways
- Baseline has three statuses: limited availability, newly available (every core browser’s current release supports it) and widely available (30 months after that).
- The core browser set is Chrome, Edge, Firefox and Safari on computers, plus Chrome, Firefox and Safari on phones.
- A status covers the whole feature: anchor positioning stays limited because of 2 of its 325 parts.
- CSS Snapshot 2026 sorts specifications by stability, not by browser support;
:has()and nesting are widely available while their specifications are still listed as roughly interoperable. - Test engines can run ahead of the browsers people use: Playwright’s WebKit accepts features Safari has not shipped.
- Widely available: use it; newly available: a fallback when the page needs it; limited: an extra behind
@supports, or wait.
References
- Baseline (W3C WebDX Community Group)
- Baseline (the full definition, web-features documentation) (W3C WebDX Community Group)
- web-features (the data and its npm package) (W3C WebDX Community Group)
- Supported browsers (Baseline) (W3C WebDX Community Group)
- CSS Snapshot 2026 (W3C CSS Working Group)
- CSS Conditional Rules Module Level 3 (@supports) (W3C CSS Working Group)
- Interop 2026 (web-platform-tests Interop team)
- Browsers (Playwright documentation) (Microsoft (Playwright))
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress