Pure CSSMIT licensed

Floating Sidebar Stacking and Overlay Order

Why a floating sidebar with z-index: 9999 can still vanish behind a card. A transform, filter, opacity below 1 or will-change on an ancestor creates a stacking context, and z-index only orders siblings inside their own context — so the number is being compared against the wrong things. The panel and its backdrop are siblings in one deliberately isolated context, which is the arrangement that survives.

Live Demo
Plain CSSTailwind v4
Try it

Mosaic by Cruip: a complete Tailwind admin dashboard template in HTML, React, Next.js and Vue · $69

Cruip · Mosaic by Cruip · Affiliate link

View Mosaic dashboard

The code

<section class="sdb-18" aria-label="Nova stage">
  <div class="sdb-18__theme">
    <input class="sdb-18__theme-input" type="checkbox" id="sdb-18-theme">
    <label class="sdb-18__theme-label" for="sdb-18-theme">
      <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor"/></svg>
      <span class="sdb-18__sr">Toggle dark theme</span>
    </label>
  </div>

  <div class="sdb-18__scene">
    <div class="sdb-18__content" id="sdb-18-lib">
      <p class="sdb-18__scene-title">Continue watching</p>
      <div class="sdb-18__cards">
        <article class="sdb-18__card"><p>Harbour Wall</p><span>ep 4</span></article>
        <article class="sdb-18__card"><p>Field Recordings</p><span>ep 11</span></article>
        <article class="sdb-18__card"><p>Slack Water</p><span>ep 2</span></article>
        <article class="sdb-18__card"><p>Kestrel</p><span>ep 7</span></article>
        <article class="sdb-18__card"><p>Two Bells</p><span>ep 1</span></article>
        <article class="sdb-18__card"><p>Low Tide</p><span>ep 9</span></article>
      </div>
    </div>

    <div class="sdb-18__layer">
      <div class="sdb-18__backdrop" aria-hidden="true"></div>
      <nav class="sdb-18__panel" aria-label="Nova library">
        <p class="sdb-18__panel-title">Library</p>
        <ul class="sdb-18__list">
          <li><a class="sdb-18__link" href="#sdb-18-lib" aria-current="page">Continue watching</a></li>
          <li><a class="sdb-18__link" href="#sdb-18-lib">My list</a></li>
          <li><a class="sdb-18__link" href="#sdb-18-lib">Downloads</a></li>
          <li><a class="sdb-18__link" href="#sdb-18-lib">Channels</a></li>
          <li><a class="sdb-18__link" href="#sdb-18-lib">Settings</a></li>
        </ul>
      </nav>
    </div>
  </div>
</section>
.sdb-18 {
  --sdb-18-bg: #070c1a;
  --sdb-18-surf: #0e1730;
  --sdb-18-glass: rgba(20, 32, 64, 0.62);
  --sdb-18-line: #1f2c4d;
  --sdb-18-ink: #e8ecfa;
  --sdb-18-mut: #8e9bc0;
  --sdb-18-acc: #6ff2d0;
  --sdb-18-acc: oklch(88% 0.13 172);
  --sdb-18-acc-soft: #10332f;
  --sdb-18-font-display: "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  width: 100%;
  min-height: 100vh;
  display: block;
  position: relative;
  box-sizing: border-box;
  background: var(--sdb-18-bg);
  color: var(--sdb-18-ink);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height: 1.55;
}

.sdb-18 *,
.sdb-18 *::before,
.sdb-18 *::after {
  box-sizing: border-box;
}

.sdb-18:has(.sdb-18__theme-input:checked) {
  --sdb-18-bg: #eef1f8;
  --sdb-18-surf: #ffffff;
  --sdb-18-glass: rgba(255, 255, 255, 0.68);
  --sdb-18-line: #d3d9e8;
  --sdb-18-ink: #101527;
  --sdb-18-mut: #565f7a;
  --sdb-18-acc: #0a6f5c;
  --sdb-18-acc: oklch(46% 0.1 172);
  --sdb-18-acc-soft: #d3ece6;
}

@media (prefers-color-scheme: light) {
  .sdb-18 {
    --sdb-18-bg: #eef1f8;
    --sdb-18-surf: #ffffff;
    --sdb-18-glass: rgba(255, 255, 255, 0.68);
    --sdb-18-line: #d3d9e8;
    --sdb-18-ink: #101527;
    --sdb-18-mut: #565f7a;
    --sdb-18-acc: #0a6f5c;
    --sdb-18-acc: oklch(46% 0.1 172);
    --sdb-18-acc-soft: #d3ece6;
  }

  .sdb-18:has(.sdb-18__theme-input:checked) {
    --sdb-18-bg: #070c1a;
    --sdb-18-surf: #0e1730;
    --sdb-18-glass: rgba(20, 32, 64, 0.62);
    --sdb-18-line: #1f2c4d;
    --sdb-18-ink: #e8ecfa;
    --sdb-18-mut: #8e9bc0;
    --sdb-18-acc: #6ff2d0;
    --sdb-18-acc: oklch(88% 0.13 172);
    --sdb-18-acc-soft: #10332f;
  }
}

@media (prefers-color-scheme: dark) {
  .sdb-18:has(.sdb-18__theme-input:checked) {
    --sdb-18-bg: #eef1f8;
    --sdb-18-surf: #ffffff;
    --sdb-18-glass: rgba(255, 255, 255, 0.68);
    --sdb-18-line: #d3d9e8;
    --sdb-18-ink: #101527;
    --sdb-18-mut: #565f7a;
    --sdb-18-acc: #0a6f5c;
    --sdb-18-acc: oklch(46% 0.1 172);
    --sdb-18-acc-soft: #d3ece6;
  }
}

.sdb-18__theme {
  position: absolute;
  inset-block-start: 0.85rem;
  inset-inline-end: 0.85rem;
  z-index: 90;
}

.sdb-18__theme-input {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.sdb-18__theme-label {
  display: grid;
  place-items: center;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border-radius: 0.9rem;
  border: 1px solid var(--sdb-18-line);
  background: var(--sdb-18-surf);
  color: var(--sdb-18-ink);
  cursor: pointer;
}

.sdb-18__theme-label svg {
  inline-size: 1.15rem;
  block-size: 1.15rem;
}

.sdb-18__theme-input:focus-visible + .sdb-18__theme-label {
  outline: 2px solid var(--sdb-18-acc);
  outline-offset: 2px;
}

.sdb-18__sr {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* isolation: isolate declares this subtree as one stacking unit deliberately,
   rather than getting a context by accident from a transform. */

.sdb-18__scene {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-block-size: 100vh;
  background: var(--sdb-18-surf);
  padding: 1.25rem;
}

@media (min-width: 46rem) {
  .sdb-18__scene {
    padding: 2rem;
  }
}

.sdb-18__content {
  min-inline-size: 0;
  padding-inline-end: 4rem;
}

@media (min-width: 46rem) {
  .sdb-18__content {
    padding-inline-end: 17rem;
  }
}

.sdb-18__scene-title {
  margin: 0 0 0.9rem;
  font-family: var(--sdb-18-font-display);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sdb-18-mut);
}

.sdb-18__cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.7rem;
}

.sdb-18__card {
  min-inline-size: 0;
  aspect-ratio: 3 / 4;
  padding: 0.7rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0.15rem;
  border-radius: 0.8rem;
  background: var(--sdb-18-bg);
  border: 1px solid var(--sdb-18-line);
}

.sdb-18__card p {
  margin: 0;
  font-size: 0.88rem;
  font-weight: 600;
  min-inline-size: 0;
}

.sdb-18__card span {
  font-size: 0.74rem;
  color: var(--sdb-18-mut);
}

.sdb-18__card:nth-child(2) {
  border-color: var(--sdb-18-acc);
}

.sdb-18__layer {
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
}

.sdb-18__backdrop {
  position: absolute;
  inset: 0;
  z-index: 30;
  background: rgba(4, 8, 20, 0.28);
}

.sdb-18__panel {
  position: absolute;
  z-index: 40;
  inset-block: 1.5rem;
  inset-inline-end: 1.5rem;
  inline-size: min(14.5rem, 62%);
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  padding: 0.8rem;
  border-radius: 1rem;
  border: 1px solid var(--sdb-18-line);
  background: var(--sdb-18-glass);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  box-shadow: 0 1.2rem 2.6rem rgba(3, 6, 16, 0.45);
}

.sdb-18__panel-title {
  margin: 0 0 0.6rem;
  font-family: var(--sdb-18-font-display);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sdb-18-mut);
}

.sdb-18__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.15rem;
}

.sdb-18__link {
  display: flex;
  align-items: center;
  min-block-size: 2.75rem;
  padding: 0.45rem 0.6rem;
  border-radius: 0.7rem;
  color: var(--sdb-18-ink);
  text-decoration: none;
  font-size: 0.88rem;
  min-inline-size: 0;
}

.sdb-18__link:hover {
  background: var(--sdb-18-acc-soft);
}

.sdb-18__link[aria-current="page"] {
  background: var(--sdb-18-acc);
  color: var(--sdb-18-bg);
  font-weight: 650;
}

.sdb-18__link:focus-visible {
  outline: 2px solid var(--sdb-18-acc);
  outline-offset: 2px;
}

@media (max-width: 32rem) {
  .sdb-18__layer {
    position: static;
  }

  .sdb-18__backdrop {
    display: none;
  }

  .sdb-18__panel {
    position: static;
    inline-size: 100%;
    margin-block-start: 1rem;
  }

  .sdb-18__content {
    padding-inline-end: 0;
  }
}
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 Sidebar Navigation 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: Floating Sidebar Stacking and Overlay Order
Source: https://codefronts.com/navigation/css-sidebar-navigation/modern-glassmorphism-floating-sidebar-design-in-css/

Why a floating sidebar with z-index: 9999 can still vanish behind a card. A transform, filter, opacity below 1 or will-change on an ancestor creates a stacking context, and z-index only orders siblings inside their own context &mdash; so the number is being compared against the wrong things. The panel and its backdrop are siblings in one deliberately isolated context, which is the arrangement that survives.
## HTML
```html
<section class="sdb-18" aria-label="Nova stage">
  <div class="sdb-18__theme">
    <input class="sdb-18__theme-input" type="checkbox" id="sdb-18-theme">
    <label class="sdb-18__theme-label" for="sdb-18-theme">
      <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8.5" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor"/></svg>
      <span class="sdb-18__sr">Toggle dark theme</span>
    </label>
  </div>

  <div class="sdb-18__scene">
    <div class="sdb-18__content" id="sdb-18-lib">
      <p class="sdb-18__scene-title">Continue watching</p>
      <div class="sdb-18__cards">
        <article class="sdb-18__card"><p>Harbour Wall</p><span>ep 4</span></article>
        <article class="sdb-18__card"><p>Field Recordings</p><span>ep 11</span></article>
        <article class="sdb-18__card"><p>Slack Water</p><span>ep 2</span></article>
        <article class="sdb-18__card"><p>Kestrel</p><span>ep 7</span></article>
        <article class="sdb-18__card"><p>Two Bells</p><span>ep 1</span></article>
        <article class="sdb-18__card"><p>Low Tide</p><span>ep 9</span></article>
      </div>
    </div>

    <div class="sdb-18__layer">
      <div class="sdb-18__backdrop" aria-hidden="true"></div>
      <nav class="sdb-18__panel" aria-label="Nova library">
        <p class="sdb-18__panel-title">Library</p>
        <ul class="sdb-18__list">
          <li><a class="sdb-18__link" href="#sdb-18-lib" aria-current="page">Continue watching</a></li>
          <li><a class="sdb-18__link" href="#sdb-18-lib">My list</a></li>
          <li><a class="sdb-18__link" href="#sdb-18-lib">Downloads</a></li>
          <li><a class="sdb-18__link" href="#sdb-18-lib">Channels</a></li>
          <li><a class="sdb-18__link" href="#sdb-18-lib">Settings</a></li>
        </ul>
      </nav>
    </div>
  </div>
</section>
```
## CSS
```css
.sdb-18 {
  --sdb-18-bg: #070c1a;
  --sdb-18-surf: #0e1730;
  --sdb-18-glass: rgba(20, 32, 64, 0.62);
  --sdb-18-line: #1f2c4d;
  --sdb-18-ink: #e8ecfa;
  --sdb-18-mut: #8e9bc0;
  --sdb-18-acc: #6ff2d0;
  --sdb-18-acc: oklch(88% 0.13 172);
  --sdb-18-acc-soft: #10332f;
  --sdb-18-font-display: "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  width: 100%;
  min-height: 100vh;
  display: block;
  position: relative;
  box-sizing: border-box;
  background: var(--sdb-18-bg);
  color: var(--sdb-18-ink);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height: 1.55;
}

.sdb-18 *,
.sdb-18 *::before,
.sdb-18 *::after {
  box-sizing: border-box;
}

.sdb-18:has(.sdb-18__theme-input:checked) {
  --sdb-18-bg: #eef1f8;
  --sdb-18-surf: #ffffff;
  --sdb-18-glass: rgba(255, 255, 255, 0.68);
  --sdb-18-line: #d3d9e8;
  --sdb-18-ink: #101527;
  --sdb-18-mut: #565f7a;
  --sdb-18-acc: #0a6f5c;
  --sdb-18-acc: oklch(46% 0.1 172);
  --sdb-18-acc-soft: #d3ece6;
}

@media (prefers-color-scheme: light) {
  .sdb-18 {
    --sdb-18-bg: #eef1f8;
    --sdb-18-surf: #ffffff;
    --sdb-18-glass: rgba(255, 255, 255, 0.68);
    --sdb-18-line: #d3d9e8;
    --sdb-18-ink: #101527;
    --sdb-18-mut: #565f7a;
    --sdb-18-acc: #0a6f5c;
    --sdb-18-acc: oklch(46% 0.1 172);
    --sdb-18-acc-soft: #d3ece6;
  }

  .sdb-18:has(.sdb-18__theme-input:checked) {
    --sdb-18-bg: #070c1a;
    --sdb-18-surf: #0e1730;
    --sdb-18-glass: rgba(20, 32, 64, 0.62);
    --sdb-18-line: #1f2c4d;
    --sdb-18-ink: #e8ecfa;
    --sdb-18-mut: #8e9bc0;
    --sdb-18-acc: #6ff2d0;
    --sdb-18-acc: oklch(88% 0.13 172);
    --sdb-18-acc-soft: #10332f;
  }
}

@media (prefers-color-scheme: dark) {
  .sdb-18:has(.sdb-18__theme-input:checked) {
    --sdb-18-bg: #eef1f8;
    --sdb-18-surf: #ffffff;
    --sdb-18-glass: rgba(255, 255, 255, 0.68);
    --sdb-18-line: #d3d9e8;
    --sdb-18-ink: #101527;
    --sdb-18-mut: #565f7a;
    --sdb-18-acc: #0a6f5c;
    --sdb-18-acc: oklch(46% 0.1 172);
    --sdb-18-acc-soft: #d3ece6;
  }
}

.sdb-18__theme {
  position: absolute;
  inset-block-start: 0.85rem;
  inset-inline-end: 0.85rem;
  z-index: 90;
}

.sdb-18__theme-input {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.sdb-18__theme-label {
  display: grid;
  place-items: center;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border-radius: 0.9rem;
  border: 1px solid var(--sdb-18-line);
  background: var(--sdb-18-surf);
  color: var(--sdb-18-ink);
  cursor: pointer;
}

.sdb-18__theme-label svg {
  inline-size: 1.15rem;
  block-size: 1.15rem;
}

.sdb-18__theme-input:focus-visible + .sdb-18__theme-label {
  outline: 2px solid var(--sdb-18-acc);
  outline-offset: 2px;
}

.sdb-18__sr {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* isolation: isolate declares this subtree as one stacking unit deliberately,
   rather than getting a context by accident from a transform. */

.sdb-18__scene {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-block-size: 100vh;
  background: var(--sdb-18-surf);
  padding: 1.25rem;
}

@media (min-width: 46rem) {
  .sdb-18__scene {
    padding: 2rem;
  }
}

.sdb-18__content {
  min-inline-size: 0;
  padding-inline-end: 4rem;
}

@media (min-width: 46rem) {
  .sdb-18__content {
    padding-inline-end: 17rem;
  }
}

.sdb-18__scene-title {
  margin: 0 0 0.9rem;
  font-family: var(--sdb-18-font-display);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sdb-18-mut);
}

.sdb-18__cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.7rem;
}

.sdb-18__card {
  min-inline-size: 0;
  aspect-ratio: 3 / 4;
  padding: 0.7rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0.15rem;
  border-radius: 0.8rem;
  background: var(--sdb-18-bg);
  border: 1px solid var(--sdb-18-line);
}

.sdb-18__card p {
  margin: 0;
  font-size: 0.88rem;
  font-weight: 600;
  min-inline-size: 0;
}

.sdb-18__card span {
  font-size: 0.74rem;
  color: var(--sdb-18-mut);
}

.sdb-18__card:nth-child(2) {
  border-color: var(--sdb-18-acc);
}

.sdb-18__layer {
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
}

.sdb-18__backdrop {
  position: absolute;
  inset: 0;
  z-index: 30;
  background: rgba(4, 8, 20, 0.28);
}

.sdb-18__panel {
  position: absolute;
  z-index: 40;
  inset-block: 1.5rem;
  inset-inline-end: 1.5rem;
  inline-size: min(14.5rem, 62%);
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  padding: 0.8rem;
  border-radius: 1rem;
  border: 1px solid var(--sdb-18-line);
  background: var(--sdb-18-glass);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  box-shadow: 0 1.2rem 2.6rem rgba(3, 6, 16, 0.45);
}

.sdb-18__panel-title {
  margin: 0 0 0.6rem;
  font-family: var(--sdb-18-font-display);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sdb-18-mut);
}

.sdb-18__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.15rem;
}

.sdb-18__link {
  display: flex;
  align-items: center;
  min-block-size: 2.75rem;
  padding: 0.45rem 0.6rem;
  border-radius: 0.7rem;
  color: var(--sdb-18-ink);
  text-decoration: none;
  font-size: 0.88rem;
  min-inline-size: 0;
}

.sdb-18__link:hover {
  background: var(--sdb-18-acc-soft);
}

.sdb-18__link[aria-current="page"] {
  background: var(--sdb-18-acc);
  color: var(--sdb-18-bg);
  font-weight: 650;
}

.sdb-18__link:focus-visible {
  outline: 2px solid var(--sdb-18-acc);
  outline-offset: 2px;
}

@media (max-width: 32rem) {
  .sdb-18__layer {
    position: static;
  }

  .sdb-18__backdrop {
    display: none;
  }

  .sdb-18__panel {
    position: static;
    inline-size: 100%;
    margin-block-start: 1rem;
  }

  .sdb-18__content {
    padding-inline-end: 0;
  }
}
```

How this works

z-index is not global, and that is the whole bug. An element's z-index only orders it against siblings within its nearest stacking context. If an ancestor forms a context, everything inside it paints as one unit, and a child's 9999 is compared only with its context-mates — not with that card two containers over. The number is not being ignored; it is being applied in a scope you did not intend.

Plenty of ordinary declarations create a stacking context. transform, filter, backdrop-filter, perspective, opacity below 1, will-change naming any of them, contain: paint, isolation: isolate, and any positioned element with a z-index other than auto. This is why the bug so often appears with an animation: someone adds transform for a hover lift, and a floating panel elsewhere in that subtree quietly loses its ability to escape.

The fix is structural, not numerical. Raise the number and nothing changes. Instead, move the floating panel out of the offending context — typically to a portal near the end of <body> — or remove the ancestor's context-forming declaration. Once the panel and the backdrop are siblings in one context, ordering them is trivial: backdrop below, panel above, and neither needs a number above single digits.

The trap after that is the backdrop. Putting the scrim inside the panel means it can never cover content outside the panel's context; putting it in a different context from the panel means one of the two ends up on the wrong side of the content. Backdrop and panel belong together, and isolation: isolate on their shared parent is the honest way to say "this subtree is one stacking unit" without borrowing a transform to do it.

Make it yours

  • Change the panel's edge by swapping inset-inline-end for inset-inline-start; the stacking rules are identical on either side.
  • Tune the glass with the two backdrop-filter values; keep the -webkit- prefixed line for Safari below 18.
  • Raise the opaque fallback background if contrast on the glass drops below 4.5:1 over your busiest content.
  • Replace isolation: isolate with nothing at all if the panel is already a direct child of <body> — you only need it when you are deliberately scoping.
  • Add a blur to the backdrop instead of the panel for the opposite reading, where the page recedes rather than the panel advancing.
  • Move the panel to a portal near the end of <body> if an ancestor in your app already forms a stacking context.

Gotchas — read before shipping

  • A transform on an ancestor creates a stacking context, so a floating panel inside it cannot paint above anything outside it — regardless of how large its z-index is.
  • will-change: transform creates the context too, which makes this bug appear from a pure performance change with no visual intent.
  • A backdrop in a different stacking context from its panel always ends up on the wrong side of something. Keep them as siblings.
  • backdrop-filter needs the -webkit- prefix for Safari below 18, and it also creates a stacking context itself — so the glass panel is both victim and cause.

Browser support

ChromeSafariFirefoxEdge
111+15.4+121+111+

backdrop-filter is the notable feature: Chrome 76, Safari 18 unprefixed with -webkit- back to 9, Firefox 103 — both forms ship here. oklch() and the :has() toggle set the stated floor. Engines without backdrop-filter get the opaque translucent background declared before it, so the panel stays legible; the stacking behaviour being taught has no version floor at all.

Techniques used in this demo

Search CodeFronts

Loading…