Home / Blog / Modern CSS in 2026

Modern CSS in 2026: What Actually Shipped

Published August 26, 2026 · 12 min read · by the CSS DNA team

Quick answer: :has(), container queries and CSS nesting are safe everywhere. Anchor positioning and @starting-style work in all three engines but are recent enough to need a fallback. @function is Chromium-only. And native CSS mixins have not shipped in any browser — despite a run of 2026 articles saying otherwise.

Every January a wave of “CSS features coming this year” posts arrives, and most of them are a list of specification drafts with no support column. That is how @mixin ended up in a dozen “what shipped in 2026” listicles while remaining unimplemented in every browser on earth.

This is the version with the support column. Four tiers: what is genuinely safe, what is new enough to guard, what only Chromium has, and what has not shipped at all. Plus a probe that tests your own browser, live, as you read.

Let’s start with the correction

MDN’s page for CSS custom functions and mixins states it plainly: “CSS mixins are not currently supported in any browser.” The same note covers @apply, @contents and @env — none of them are implemented anywhere.

What did ship is the neighbouring feature, and the confusion is understandable because they live in the same specification. @function shipped in Chrome and Edge 139. It lets you define a named function that takes arguments and returns a value:

@function --negate(--value) {
  result: calc(var(--value) * -1);
}

.card {
  margin-top: --negate(var(--gap));
}

That is real, and it works today in Chromium. Firefox and Safari have not shipped it. So @function is a progressive enhancement, not a Sass replacement — and @mixin, the part that would actually replace Sass mixins, is still a draft. Chrome originally targeted version 136 for @function and delayed it to 139, which is a fair signal of how much of this area is still moving.

The general rule. If an article lists a CSS feature without naming the browsers and versions that support it, treat the entry as a specification, not a shipping feature. Baseline status is public data; leaving it out is a choice.

What does your browser support right now?

This runs CSS.supports() and a stylesheet parse test against your current browser. Nothing is sent anywhere — the answer comes from the engine rendering this page.

Live support check

Your browser, this second.

Running…

    How Baseline actually works

    Baseline is a status label for web features, maintained by the W3C WebDX Community Group, describing how broadly a feature is supported across Chrome, Edge, Firefox and Safari. It has two levels, and the difference is the whole point:

    • Baseline Newly available — the feature works in all three engines as of some date. Usable, but anyone who has not updated their browser will miss it.
    • Baseline Widely available30 months have passed since that date. At that point the long tail of un-updated browsers has largely aged out, and you can generally use the feature without a fallback.

    Thirty months is a long time, and it is the number that turns “supported in all browsers” into “safe to ship without thinking about it.” Container queries became newly available in February 2023 and widely available in August 2025. :has() became newly available in December 2023 and crossed into widely available in June 2026 — this year.

    Tier 1: Safe to use with no fallback

    All Baseline Widely available. Use them the way you use flexbox.

    FeatureWhat it replacesStatus
    :has()A JavaScript listener that adds a class to a parentWidely available, June 2026
    Container queriesMedia queries for components that move between layoutsWidely available, August 2025
    CSS NestingSass, for the nesting half of what Sass doesWidely available
    aspect-ratioThe padding-top percentage hackWidely available
    SubgridManual width matching between grid childrenWidely available
    clamp()Breakpoint-by-breakpoint font sizingWidely available
    :is(), :where()Long selector lists, and specificity workaroundsWidely available
    @layerSpecificity wars and !importantWidely available
    OKLCH colorHex ramps that go muddy in the middleWidely available

    :where() deserves a specific mention because it is the cheapest fix in modern CSS: it contributes zero specificity. Wrapping a reset or a library override in :where() means anything you write later can beat it with a single class. That is the direct antidote to the jagged specificity graph that most stylesheets develop.

    Tier 2: Shipped everywhere, but recently — guard it

    These work in all three engines and are Baseline Newly available. The feature is real; the risk is the user on a browser from last year.

    FeatureChrome / EdgeFirefoxSafari
    Anchor positioning12514726
    @starting-style11712917.5
    Style queries (custom properties)11115118

    Anchor positioning is the headline of 2026 — it had the largest year-over-year usage increase of any feature in the State of CSS 2026 survey, up 15%. It tethers one element’s position to another’s without JavaScript, which retires the reason most sites load a positioning library for tooltips, dropdowns and popovers. Firefox enabled it by default in version 147; Safari shipped it in 26. Can I Use puts global coverage around 84%.

    That 84% is exactly why you guard it:

    .tooltip {
      /* fallback: fine everywhere */
      position: absolute;
      inset-block-start: 100%;
    }
    
    @supports (anchor-name: --x) {
      .trigger { anchor-name: --trigger; }
      .tooltip {
        position-anchor: --trigger;
        position-area: block-end center;
        position-try-fallbacks: flip-block;
      }
    }

    @starting-style is the other one worth adopting now. It defines the styles an element has before its first render, which finally makes it possible to animate something in from display: none without a JavaScript timing hack:

    dialog[open] {
      opacity: 1;
      transition: opacity .25s, display .25s allow-discrete;
    }
    
    @starting-style {
      dialog[open] { opacity: 0; }
    }

    It reached all three engines in August 2024 with Firefox 129, so it is close to the widely-available line but not across it yet.

    Tier 3: Chromium only — enhancement, not architecture

    Real, shipping, and available to roughly two thirds of users. Use them where absence degrades gracefully; never build a layout that requires them.

    • @function — Chrome and Edge 139. Custom functions with arguments and a result.
    • Scroll-driven animationsanimation-timeline: scroll() and view(). A scroll progress bar in three lines of CSS, with no scroll listener and no layout thrash.
    • field-sizing: content — textareas that grow with their content, replacing a well-worn JavaScript snippet.
    • Cross-document view transitions — animate between two full page loads on a multi-page site.

    Scroll-driven animations are the standout here, because the fallback is simply “nothing moves” — which is an acceptable outcome, and is what a user with prefers-reduced-motion should get anyway.

    Tier 4: Not shipped, whatever you read

    FeatureReality
    @mixin / @applyNo browser support anywhere. Draft specification.
    @contents, @envNo browser support anywhere.
    if()Among the least-used features in State of CSS 2026, on limited support.
    Gap decorationsAlso among the least-used, for the same reason.
    sibling-count()Awareness rose 22% year over year — awareness, not support.

    The sibling-count() line is worth pausing on, because it captures the whole problem. A feature can be the most-discussed thing in CSS and still be unusable. Discussion volume and support are independent variables, and only one of them decides whether your layout works.

    What developers are really using

    From the State of CSS 2026 survey, the most-used features by share of respondents:

    FeatureHave used it
    :has()83.7%
    aspect-ratio81.3%
    CSS Nesting70.6%
    scroll-behavior68.2%
    Viewport-relative units59.8%

    Note what is absent. Nothing exotic. The features that won are the ones that removed a specific, daily annoyance — a parent selector, an aspect-ratio hack, a build step for nesting. :has() is both the most used and the most loved, which is unusual; normally the most-loved feature is one people have barely tried.

    How to see what a site actually ships

    Reading about features is one thing. The more useful exercise is opening a site you admire and finding out which of these it really uses — because production CSS is a much better guide to what is safe than any survey.

    This counts modern features in the page’s own stylesheets:

    const CSS_TEXT = [...document.styleSheets]
      .flatMap(s => { try { return [...s.cssRules] } catch { return [] } })
      .map(r => r.cssText).join('\n');
    
    const CHECKS = {
      ':has()':               /:has\(/,
      'container queries':    /@container|container-type/,
      'nesting':              /&\s*[.:#\[]/,
      'anchor positioning':   /anchor-name|position-anchor|position-area/,
      '@starting-style':      /@starting-style/,
      'cascade layers':       /@layer/,
      'OKLCH color':          /oklch\(/,
      'scroll-driven anim.':  /animation-timeline/,
      'subgrid':              /subgrid/,
      'clamp()':              /clamp\(/,
      '!important':           /!important/
    };
    
    console.table(Object.entries(CHECKS).map(([feature, re]) => ({
      feature,
      found: re.test(CSS_TEXT) ? 'yes' : 'no'
    })));

    The try / catch matters: reading cssRules from a cross-origin stylesheet throws a SecurityError, and one uncaught throw kills the loop. Catching per sheet means a site serving CSS from a CDN still reports on everything same-origin.

    Want this without the console? CSS DNA reads any page’s live styles and reports the palette, type scale, spacing, breakpoints, motion and custom properties in one click — then exports them as Tailwind, CSS variables, SCSS or design tokens. Add it free, and every site you open becomes a reference.

    The honest summary

    CSS in 2026 did absorb a genuine amount of what used to be JavaScript: parent selection, component-level responsiveness, entry animations, tethered positioning, scroll-linked motion. That part of the excitement is earned.

    What has not happened is the wholesale replacement of the preprocessor. Nesting is native and colour functions are native, but mixins are not, and the practical shape of a 2026 stylesheet is still mostly Tier 1 features with a handful of guarded enhancements. Build with that and the site works for everyone — which was always the actual goal.

    Frequently asked questions

    Are native CSS mixins supported in browsers?

    No. MDN states that CSS mixins are not currently supported in any browser, along with the related @apply, @contents and @env at-rules. The related @function rule did ship, in Chrome and Edge 139, but it returns a value rather than applying a block of declarations.

    What does Baseline “widely available” mean?

    Baseline Widely available means 30 months have passed since a feature became supported in Chrome, Edge, Firefox and Safari. That interval allows un-updated browsers to age out, so a widely available feature can generally be used without a fallback. Baseline Newly available means all three engines support it, but only recently.

    Is the :has() selector safe to use in 2026?

    Yes. :has() became Baseline Newly available in December 2023 and reached Baseline Widely available in June 2026. It is also the most-used feature in the State of CSS 2026 survey at 83.7%.

    Which browsers support CSS anchor positioning?

    Chrome and Edge from version 125, Firefox from 147, and Safari from 26. Can I Use puts global coverage at roughly 84%, so wrap it in @supports (anchor-name: --x) and provide a static fallback position.

    What is @starting-style used for?

    @starting-style defines the styles an element has before its first render, which lets you transition an element in from display: none without a JavaScript timing hack. It reached all three engines in August 2024 — Chrome 117, Safari 17.5, Firefox 129.

    Does modern CSS replace Sass?

    Partly. Nesting, custom properties, colour manipulation and cascade layers are all native now. Mixins are not supported in any browser, and @function is Chromium-only, so projects relying on those still need a preprocessor.

    How do I check which CSS features a website uses?

    Walk document.styleSheets, join every rule’s cssText, and test it against patterns such as /:has\(/ or /@container/. Wrap each sheet in try / catch, because reading rules from a cross-origin stylesheet throws a SecurityError.

    How do I feature-detect a CSS feature in the browser?

    Use CSS.supports() for properties — CSS.supports('anchor-name: --a') — and the selector() form for selectors, as in CSS.supports('selector(:has(a))'). At-rules are not covered by either, so test those by inserting the rule into a stylesheet and checking whether it parsed.

    See what any site is really made of

    Colors, type scale, spacing, breakpoints, motion and custom properties — read from the live page in one click, exported as Tailwind, CSS, SCSS, JSON or design tokens.

    Add CSS DNA to Chrome — Free