Tailwind v4MIT licensed

Tailwind Liquid Glass Bottom Accessory Bar

The iOS 26 bottom-accessory pattern: a now-playing mini-player floating above the tab bar, two glass surfaces sharing one material at two elevations. This is also the port's most honest lesson — with no @apply, the shared frost recipe is typed twice, and the notes explain why that is the right call rather than a workaround.

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-05 relative block w-full min-h-svh overflow-hidden font-nb05-sans bg-[conic-gradient(from_120deg_at_70%_30%,#ff6a3d,#ff2d78,#7a2bff,#ff6a3d)] bg-[length:200%_200%] animate-nb05-bg motion-reduce:animate-none" aria-label="Liquid glass bottom accessory bar demo">
  <div class="min-h-svh grid place-items-center p-6 pb-50">
    <p class="max-w-[34ch] text-center text-white text-base font-semibold leading-[1.6] [text-shadow:0_2px_12px_rgba(0,0,0,.3)]">Now-playing accessory floats above the tab bar — two glass surfaces, one material, and the frost recipe typed twice because utilities have no shared class.</p>
  </div>
  <div class="absolute inset-x-3 bottom-3 flex flex-col gap-2">
    <div class="relative flex items-center gap-3 px-3 py-2.5 rounded-[20px] text-white bg-[color-mix(in_oklab,white_16%,transparent)] border border-white/40 shadow-[inset_0_1px_0_rgba(255,255,255,.55),0_20px_40px_-22px_rgba(0,0,0,.6)] backdrop-blur-[26px] backdrop-saturate-[1.8]" role="group" aria-label="Now playing">
      <span class="flex-none size-[46px] rounded-xl bg-[linear-gradient(135deg,#ffd36b,#ff5ea8)] shadow-[inset_0_1px_0_rgba(255,255,255,.6)]" aria-hidden="true"></span>
      <span class="flex flex-col min-w-0">
        <span class="text-[14.5px] font-bold truncate">Solar Fields</span>
        <span class="text-[12.5px] text-white/80 truncate">Nova — Aurora EP</span>
      </span>
      <span class="absolute inset-x-3 bottom-1 h-[3px] rounded-[3px] bg-white/[0.28]" aria-hidden="true"><span class="block w-[42%] h-full rounded-[3px] bg-white"></span></span>
      <span class="ms-auto flex items-center gap-1">
        <button class="size-11 rounded-xl border-0 bg-transparent text-white text-[17px] cursor-pointer transition-colors duration-200 hover:bg-white/[0.18] focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" type="button" aria-label="Previous">⏮</button>
        <button class="size-11 rounded-xl border-0 bg-nb05-accent text-white text-base cursor-pointer transition-colors duration-200 hover:bg-[color-mix(in_oklab,var(--color-nb05-accent)_85%,white)] focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" type="button" aria-label="Play">⏵</button>
        <button class="size-11 rounded-xl border-0 bg-transparent text-white text-[17px] cursor-pointer transition-colors duration-200 hover:bg-white/[0.18] focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" type="button" aria-label="Next">⏭</button>
      </span>
    </div>
    <nav class="flex justify-around p-2 rounded-[22px] bg-[color-mix(in_oklab,white_16%,transparent)] border border-white/40 shadow-[inset_0_1px_0_rgba(255,255,255,.55),0_20px_40px_-22px_rgba(0,0,0,.6)] backdrop-blur-[26px] backdrop-saturate-[1.8]" aria-label="Primary">
      <a class="flex flex-col items-center justify-center gap-[3px] min-w-14 min-h-11 rounded-[14px] no-underline text-white/[0.82] text-[11px] font-semibold transition-[background-color,color] duration-200 hover:bg-white/[0.12] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2 aria-[current=page]:bg-white/20 aria-[current=page]:text-white" href="#nbtw-05" aria-current="page"><span class="text-[19px]" aria-hidden="true">⌂</span>Home</a>
      <a class="flex flex-col items-center justify-center gap-[3px] min-w-14 min-h-11 rounded-[14px] no-underline text-white/[0.82] text-[11px] font-semibold transition-[background-color,color] duration-200 hover:bg-white/[0.12] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-05"><span class="text-[19px]" aria-hidden="true">◎</span>Radio</a>
      <a class="flex flex-col items-center justify-center gap-[3px] min-w-14 min-h-11 rounded-[14px] no-underline text-white/[0.82] text-[11px] font-semibold transition-[background-color,color] duration-200 hover:bg-white/[0.12] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-05"><span class="text-[19px]" aria-hidden="true">♪</span>Library</a>
      <a class="flex flex-col items-center justify-center gap-[3px] min-w-14 min-h-11 rounded-[14px] no-underline text-white/[0.82] text-[11px] font-semibold transition-[background-color,color] duration-200 hover:bg-white/[0.12] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-05"><span class="text-[19px]" aria-hidden="true">⌕</span>Search</a>
    </nav>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-nb05-accent: #f0522f;
  --color-nb05-accent: oklch(0.66 0.2 20);
  --font-nb05-sans: system-ui, 'Segoe UI', sans-serif;
  --animate-nb05-bg: nb05-bg 20s ease-in-out infinite;
}

@keyframes nb05-bg {
  50% {
    background-position: 100% 100%;
  }
}

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 {
  --color-nb05-accent: #f0522f;
  --color-nb05-accent: oklch(0.66 0.2 20);
  --font-nb05-sans: system-ui, 'Segoe UI', sans-serif;
  --animate-nb05-bg: nb05-bg 20s ease-in-out infinite;
}

@keyframes nb05-bg {
  50% {
    background-position: 100% 100%;
  }
}

What changed in the port

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

  • The shared frost recipe is typed on both bars. That is the port's real cost, and it is smaller than it looks: the duplication is local and visible, where a shared class is indirection you have to go and read.
  • If a third surface appears, promote the pieces to @theme (--color-nb05-glass, --color-nb05-rim) so bg-nb05-glass carries the recipe. Two repetitions is fine; four is a signal.
  • min-w-0 on the metadata column is what makes truncate work — a flex child's default min-width:auto otherwise refuses to shrink and pushes the transport controls out of the bar.
  • size-11 replaces a width/height pair and states the 44px touch target as one thing, which makes it much harder to break later.
  • Both bars sit in one positioned stack (absolute inset-x-3 bottom-3 flex flex-col gap-2), so they share elevation instead of being pinned independently and colliding at some viewport height.
  • The progress line is decorative and aria-hidden; the group carries the accessible name, so nothing about the visual shortcut is announced as content.
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 Liquid Glass Bottom Accessory Bar
Source: https://codefronts.com/navigation/tailwind-liquid-glass-navbars/tailwind-liquid-glass-bottom-accessory-bar/

The iOS 26 bottom-accessory pattern: a now-playing mini-player floating above the tab bar, two glass surfaces sharing one material at two elevations. This is also the port's most honest lesson &mdash; with no @apply, the shared frost recipe is typed twice, and the notes explain why that is the right call rather than a workaround.
## HTML
```html
<section class="nbtw-05 relative block w-full min-h-svh overflow-hidden font-nb05-sans bg-[conic-gradient(from_120deg_at_70%_30%,#ff6a3d,#ff2d78,#7a2bff,#ff6a3d)] bg-[length:200%_200%] animate-nb05-bg motion-reduce:animate-none" aria-label="Liquid glass bottom accessory bar demo">
  <div class="min-h-svh grid place-items-center p-6 pb-50">
    <p class="max-w-[34ch] text-center text-white text-base font-semibold leading-[1.6] [text-shadow:0_2px_12px_rgba(0,0,0,.3)]">Now-playing accessory floats above the tab bar — two glass surfaces, one material, and the frost recipe typed twice because utilities have no shared class.</p>
  </div>
  <div class="absolute inset-x-3 bottom-3 flex flex-col gap-2">
    <div class="relative flex items-center gap-3 px-3 py-2.5 rounded-[20px] text-white bg-[color-mix(in_oklab,white_16%,transparent)] border border-white/40 shadow-[inset_0_1px_0_rgba(255,255,255,.55),0_20px_40px_-22px_rgba(0,0,0,.6)] backdrop-blur-[26px] backdrop-saturate-[1.8]" role="group" aria-label="Now playing">
      <span class="flex-none size-[46px] rounded-xl bg-[linear-gradient(135deg,#ffd36b,#ff5ea8)] shadow-[inset_0_1px_0_rgba(255,255,255,.6)]" aria-hidden="true"></span>
      <span class="flex flex-col min-w-0">
        <span class="text-[14.5px] font-bold truncate">Solar Fields</span>
        <span class="text-[12.5px] text-white/80 truncate">Nova — Aurora EP</span>
      </span>
      <span class="absolute inset-x-3 bottom-1 h-[3px] rounded-[3px] bg-white/[0.28]" aria-hidden="true"><span class="block w-[42%] h-full rounded-[3px] bg-white"></span></span>
      <span class="ms-auto flex items-center gap-1">
        <button class="size-11 rounded-xl border-0 bg-transparent text-white text-[17px] cursor-pointer transition-colors duration-200 hover:bg-white/[0.18] focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" type="button" aria-label="Previous">⏮</button>
        <button class="size-11 rounded-xl border-0 bg-nb05-accent text-white text-base cursor-pointer transition-colors duration-200 hover:bg-[color-mix(in_oklab,var(--color-nb05-accent)_85%,white)] focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" type="button" aria-label="Play">⏵</button>
        <button class="size-11 rounded-xl border-0 bg-transparent text-white text-[17px] cursor-pointer transition-colors duration-200 hover:bg-white/[0.18] focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" type="button" aria-label="Next">⏭</button>
      </span>
    </div>
    <nav class="flex justify-around p-2 rounded-[22px] bg-[color-mix(in_oklab,white_16%,transparent)] border border-white/40 shadow-[inset_0_1px_0_rgba(255,255,255,.55),0_20px_40px_-22px_rgba(0,0,0,.6)] backdrop-blur-[26px] backdrop-saturate-[1.8]" aria-label="Primary">
      <a class="flex flex-col items-center justify-center gap-[3px] min-w-14 min-h-11 rounded-[14px] no-underline text-white/[0.82] text-[11px] font-semibold transition-[background-color,color] duration-200 hover:bg-white/[0.12] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2 aria-[current=page]:bg-white/20 aria-[current=page]:text-white" href="#nbtw-05" aria-current="page"><span class="text-[19px]" aria-hidden="true">⌂</span>Home</a>
      <a class="flex flex-col items-center justify-center gap-[3px] min-w-14 min-h-11 rounded-[14px] no-underline text-white/[0.82] text-[11px] font-semibold transition-[background-color,color] duration-200 hover:bg-white/[0.12] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-05"><span class="text-[19px]" aria-hidden="true">◎</span>Radio</a>
      <a class="flex flex-col items-center justify-center gap-[3px] min-w-14 min-h-11 rounded-[14px] no-underline text-white/[0.82] text-[11px] font-semibold transition-[background-color,color] duration-200 hover:bg-white/[0.12] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-05"><span class="text-[19px]" aria-hidden="true">♪</span>Library</a>
      <a class="flex flex-col items-center justify-center gap-[3px] min-w-14 min-h-11 rounded-[14px] no-underline text-white/[0.82] text-[11px] font-semibold transition-[background-color,color] duration-200 hover:bg-white/[0.12] hover:text-white focus-visible:outline-2 focus-visible:outline-white focus-visible:outline-offset-2" href="#nbtw-05"><span class="text-[19px]" aria-hidden="true">⌕</span>Search</a>
    </nav>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-nb05-accent: #f0522f;
  --color-nb05-accent: oklch(0.66 0.2 20);
  --font-nb05-sans: system-ui, 'Segoe UI', sans-serif;
  --animate-nb05-bg: nb05-bg 20s ease-in-out infinite;
}

@keyframes nb05-bg {
  50% {
    background-position: 100% 100%;
  }
}
```

How this works

Two surfaces, one material. Both bars carry the same fill, rim, shadow and backdrop-blur-[26px] backdrop-saturate-[1.8]. That is what makes them read as one piece of glass at two elevations rather than two unrelated panels:

class="bg-[color-mix(in_oklab,white_16%,transparent)] border border-white/40
       shadow-[inset_0_1px_0_rgba(255,255,255,.55),0_20px_40px_-22px_rgba(0,0,0,.6)]
       backdrop-blur-[26px] backdrop-saturate-[1.8]"   /* on BOTH bars */

The repetition is the port. The CSS version shares this with a selector list. Utilities have no equivalent, and reaching for @apply to recreate it gives back the indirection Tailwind exists to remove. Type it twice, or promote the pieces to @theme colours (bg-nb05-glass) if the recipe outgrows two elements.

Truncation needs min-w-0. A flex child defaults to min-width:auto, so a long track title refuses to shrink and pushes the transport controls off the bar. min-w-0 on the metadata column plus truncate on each line is the whole fix.

Touch targets are non-negotiable. Every transport control is size-11 — 44px — and every tab is min-h-11 min-w-14, which is what keeps a dense mini-player usable with a thumb.

Make it yours

  • Detach the accessory into a floating pill with mx-4 rounded-full; the shared frost needs no change.
  • Recolour the play control by editing --color-nb05-accent — the fill and its hover mix both read it.
  • Bind real playback by writing the fill's width as an inline style from your player state; keep the track aria-hidden and expose progress in text elsewhere.
  • Promote the glass recipe to @theme tokens if a third surface appears; two repetitions is fine, four is a signal.
  • Swap the column tabs for icon-only by deleting the label spans — keep the aria-labels, which are already there.

Gotchas — read before shipping

  • Keep both bars inside one positioned stack. Pinning them separately is how the accessory ends up overlapping the tab bar at some viewport height.
  • truncate does nothing without min-w-0 on the flex child — the most common cause of a mini-player that overflows.
  • Transport buttons below 44px fail WCAG 2.2 target-size guidance and feel broken with a thumb, however good they look.
  • The artwork here is a gradient placeholder. Give the real thing an <img> with genuine alt text, or keep it decorative and label the group instead.
  • Two stacked backdrop-filter surfaces are two blur passes. On low-end hardware, consider dropping the accessory's blur and keeping only its tint.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Tailwind v4 sets the floor. Both bars degrade to tinted solids without backdrop-filter, and the layout — stack, targets, truncation — is unaffected.

Techniques used in this demo

Plain CSSno Tailwind surface

HTML & JSno Tailwind involved

Search CodeFronts

Loading…