Tailwind v4MIT licensed

Tailwind Fallback-First Glass Navbar

A glass navbar engineered to never look broken, and the port where Tailwind wins outright: the entire @supports tiering moves into the markup as supports-[backdrop-filter:blur(1px)]: utilities. The base class list is the opaque, hand-tuned fallback; the variant twins upgrade it to real frost. Both tiers sit in one class list, so neither can be forgotten.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="nbtw-19 grid place-items-center w-full min-h-svh p-5 font-nb19-sans bg-[linear-gradient(120deg,#134e5e,#71b280)]" aria-label="Fallback-first glass navbar demo">
  <nav class="flex flex-wrap items-center gap-x-5 gap-y-3 w-[min(720px,100%)] px-4.5 py-3.5 rounded-2xl text-white bg-[linear-gradient(180deg,rgba(30,50,55,.92),rgba(20,38,42,.96))] border border-white/[0.22] shadow-[inset_0_1px_0_rgba(255,255,255,.35),0_16px_38px_-22px_rgba(0,0,0,.6)] supports-[backdrop-filter:blur(1px)]:bg-none supports-[backdrop-filter:blur(1px)]:bg-[color-mix(in_oklab,white_12%,transparent)] supports-[backdrop-filter:blur(1px)]:backdrop-blur-[20px] supports-[backdrop-filter:blur(1px)]:backdrop-saturate-[1.8]" aria-label="Primary">
    <span class="text-base font-extrabold">⛬ Resilient</span>
    <div class="flex flex-wrap gap-1 ms-auto">
      <a class="flex items-center min-h-10 px-3.5 rounded-[10px] no-underline text-white/[0.86] text-[14.5px] font-semibold transition-colors duration-200 hover:bg-white/[0.16] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2 aria-[current=page]:bg-white/[0.16] aria-[current=page]:text-white" href="#nbtw-19" aria-current="page">Home</a>
      <a class="flex items-center min-h-10 px-3.5 rounded-[10px] no-underline text-white/[0.86] text-[14.5px] font-semibold transition-colors duration-200 hover:bg-white/[0.16] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-19">Support</a>
      <a class="flex items-center min-h-10 px-3.5 rounded-[10px] no-underline text-white/[0.86] text-[14.5px] font-semibold transition-colors duration-200 hover:bg-white/[0.16] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-19">Status</a>
    </div>
    <span class="text-[11px] font-bold tracking-[0.06em] uppercase text-white/60" aria-hidden="true">
      <span class="supports-[backdrop-filter:blur(1px)]:hidden">fallback tier</span>
      <span class="hidden supports-[backdrop-filter:blur(1px)]:inline">backdrop-filter tier</span>
    </span>
  </nav>
</section>
@import "tailwindcss";

@theme {
  --font-nb19-sans: system-ui, 'Segoe UI', sans-serif;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

Compiles in the browser — perfect for a CodePen or a quick test, not for production.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --font-nb19-sans: system-ui, 'Segoe UI', sans-serif;
}

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • This is the port that wins outright: the whole @supports tiering becomes supports-[backdrop-filter:blur(1px)]: utilities, and both tiers sit in one class list where neither can be forgotten.
  • Fallback-first is enforced by construction. The unprefixed utilities are the base tier, and a variant can only add to them — you cannot accidentally author the enhancement first.
  • The upgrade is per property rather than per rule, so only the three declarations that actually change are restated. A feature-query rule would force you to repeat the rest.
  • The base tier is a designed opaque gradient with an inset highlight, not a degraded leftover: on a browser without backdrop-filter nothing looks missing.
  • The tier label swaps with the same variant, which makes it obvious in a screenshot or a bug report which path rendered.
  • The limit is negation: @supports not (...) has no variant form and still has to be a CSS rule. Demo 03 is where that bites.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Fallback-First Glass Navbar
Source: https://codefronts.com/navigation/tailwind-liquid-glass-navbars/tailwind-fallback-first-glass-navbar/

A glass navbar engineered to never look broken, and the port where Tailwind wins outright: the entire @supports tiering moves into the markup as supports-[backdrop-filter:blur(1px)]: utilities. The base class list is the opaque, hand-tuned fallback; the variant twins upgrade it to real frost. Both tiers sit in one class list, so neither can be forgotten.
## HTML
```html
<section class="nbtw-19 grid place-items-center w-full min-h-svh p-5 font-nb19-sans bg-[linear-gradient(120deg,#134e5e,#71b280)]" aria-label="Fallback-first glass navbar demo">
  <nav class="flex flex-wrap items-center gap-x-5 gap-y-3 w-[min(720px,100%)] px-4.5 py-3.5 rounded-2xl text-white bg-[linear-gradient(180deg,rgba(30,50,55,.92),rgba(20,38,42,.96))] border border-white/[0.22] shadow-[inset_0_1px_0_rgba(255,255,255,.35),0_16px_38px_-22px_rgba(0,0,0,.6)] supports-[backdrop-filter:blur(1px)]:bg-none supports-[backdrop-filter:blur(1px)]:bg-[color-mix(in_oklab,white_12%,transparent)] supports-[backdrop-filter:blur(1px)]:backdrop-blur-[20px] supports-[backdrop-filter:blur(1px)]:backdrop-saturate-[1.8]" aria-label="Primary">
    <span class="text-base font-extrabold">⛬ Resilient</span>
    <div class="flex flex-wrap gap-1 ms-auto">
      <a class="flex items-center min-h-10 px-3.5 rounded-[10px] no-underline text-white/[0.86] text-[14.5px] font-semibold transition-colors duration-200 hover:bg-white/[0.16] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2 aria-[current=page]:bg-white/[0.16] aria-[current=page]:text-white" href="#nbtw-19" aria-current="page">Home</a>
      <a class="flex items-center min-h-10 px-3.5 rounded-[10px] no-underline text-white/[0.86] text-[14.5px] font-semibold transition-colors duration-200 hover:bg-white/[0.16] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-19">Support</a>
      <a class="flex items-center min-h-10 px-3.5 rounded-[10px] no-underline text-white/[0.86] text-[14.5px] font-semibold transition-colors duration-200 hover:bg-white/[0.16] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-19">Status</a>
    </div>
    <span class="text-[11px] font-bold tracking-[0.06em] uppercase text-white/60" aria-hidden="true">
      <span class="supports-[backdrop-filter:blur(1px)]:hidden">fallback tier</span>
      <span class="hidden supports-[backdrop-filter:blur(1px)]:inline">backdrop-filter tier</span>
    </span>
  </nav>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --font-nb19-sans: system-ui, 'Segoe UI', sans-serif;
}
```

How this works

Both tiers, one class list. This is the port that removes a whole category of mistake — the fallback cannot be an afterthought when it is the base value of the same utility:

class="bg-[linear-gradient(180deg,rgba(30,50,55,.92),rgba(20,38,42,.96))]
       supports-[backdrop-filter:blur(1px)]:bg-none
       supports-[backdrop-filter:blur(1px)]:bg-[color-mix(in_oklab,white_12%,transparent)]
       supports-[backdrop-filter:blur(1px)]:backdrop-blur-[20px]
       supports-[backdrop-filter:blur(1px)]:backdrop-saturate-[1.8]"

The base tier is designed, not defaulted. A vertical gradient with an inset top highlight and a soft outer shadow gives a solid bar the read of a glass pane. Nothing about it looks like a browser missing a feature, which is the entire point of fallback-first authoring.

The upgrade is per property. A feature-query rule forces you to restate everything you want in the enhanced tier; a feature-query variant upgrades exactly the three declarations that change. The rest of the bar is written once.

The visible label is a debugging affordance. Two spans, one shown per tier, so you can confirm which path a browser took at a glance — useful when testing with backdrop-filter disabled in about:config.

Make it yours

  • Tune each tier independently: the base fill for opaque contexts, the variant fill for frosted ones. They are separate values on the same property.
  • Add a third tier for SVG refraction by combining variants (supports-[filter:url(#x)]:) on a decorative layer, as demo 03 does.
  • Test the fallback by disabling layout.css.backdrop-filter.enabled in Firefox — the label tells you which tier rendered.
  • Raise the base tier's opacity if your backdrop is especially busy; there is no blur there to soften it.
  • Point both tiers at @theme colours if the same two-tier glass appears on several components.

Gotchas — read before shipping

  • Author the fallback as the base value, never as an override. The variant can only add, which is exactly the discipline you want.
  • A negated feature query has no variant. @supports not (...) still has to be a CSS rule — see demo 03 for the case where that matters.
  • The arbitrary variant's condition must be a valid declaration: supports-[backdrop-filter:blur(1px)], not supports-[backdrop-filter] alone, or the query is meaningless.
  • The base tier's fill is a background-image gradient and the enhanced fill is a background-color, so the upgrade needs supports-[backdrop-filter:blur(1px)]:bg-none to clear the gradient — otherwise the opaque image paints straight over the frost and nothing appears to change.
  • Keep contrast valid in the opaque tier. Without blur, text sits directly on whatever the backdrop provides.
  • Do not test only in Chrome. The fallback tier is the whole product of this demo and it is invisible in a browser that supports everything.
  • Long variant prefixes are verbose by nature. That is the trade for having both tiers visible in one place; extract a component if it becomes unreadable.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Tailwind v4 sets the floor for the sheet itself; within that floor, the @supports tiering does exactly what the hand-written version did — every browser gets a polished bar, and the ones with backdrop-filter get the frost.

Techniques used in this demo

HTML & JSno Tailwind involved

Search CodeFronts

Loading…