36 CSS Search Bars
35 / 36

All 36 in 36 CSS Search Bars

  1. 01Command Palette Cmd+K Search Bar
  2. 02Algolia-Style Instant Search with Highlighted Results Dropdown
  3. 03E-Commerce Product Search Bar with Category Scope Dropdown
  4. 04Header Navbar Integrated Sticky Search Bar
  5. 05SaaS Dashboard Command Search with Recent and Suggested
  6. 06Minimal CSS Search Bar with Animated Underline
  7. 07CSS Rounded Pill Search Bar with Submit Button
  8. 08Glassmorphism CSS Search Bar (Backdrop Blur)
  9. 09Neon Glow CSS Search Bar (Cyberpunk)
  10. 10CSS Search Bar with Animated Caret Highlight
  11. 11CSS Search Bar with Voice Input Microphone Button
  12. 12CSS Search Bar with Loading Spinner Indicator
  13. 13CSS Search Bar with Clear Button (X on Type)
  14. 14Animated Expanding CSS Search Bar on Focus
  15. 15CSS Search Bar with Autocomplete Suggestions Dropdown
  16. 16CSS Search Bar with Keyboard Shortcut Hint (Cmd K / Ctrl K)
  17. 17CSS Search Bar with Filter Chip Tags
  18. 18CSS Search Bar with Recent Searches Dropdown
  19. 19CSS Search Bar with Rotating Placeholder Text
  20. 20CSS People Search Bar with Avatar Chips
  21. 21Neo-Brutalist CSS Search Bar with Offset Stamp
  22. 22Compact Toolbar CSS Search Bar (Docs / Wiki)
  23. 23Hero Section CSS Search Bar with CTA
  24. 24CSS Search Bar with Side Category Indicator
  25. 25Floating CSS Search Bar with Drop Shadow (Elevated)
  26. 26CSS Search + Filter Sidebar Combo Bar
  27. 27CSS Search Bar with Inline Loading Progress Bar
  28. 28CSS Search Bar with Dual-Tone Border Outline
  29. 29CSS Glitch Search Bar with RGB Split Effect
  30. 30Mobile-First Compact CSS Search Bar
  31. 31CSS Search Bar with Focus Ring Bloom Animation
  32. 32CSS Search Bar Combo with Scope Selector
  33. 33CSS Search Bar with Inset Pressed 3D Effect
  34. 34CSS Search Bar with Animated Border Trace
  35. 35Floating Card CSS Search Bar (Modal Style)
  36. 36Aurora Gradient CSS Search Bar
Light JSMIT licensed

Floating Card CSS Search Bar (Modal Style)

Search-as-overlay: click the header field and a raised card floats above a dimmed, blurred page with a large input and recent result cards. A native <dialog> handles focus trapping, Escape and the backdrop — the pattern behind Notion, Vercel and most editorial sites.

Live Demo
Try it

Nucleo: 44,000+ SVG icons in five families · All Icons Bundle $149

Nucleo · Affiliate link

Get the Nucleo bundle

The code

<div class="sb-35">
  <button class="sb-35__theme" type="button" aria-pressed="false" aria-label="Switch to dark theme">
    <svg class="sb-35__moon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M20 14.2A8.2 8.2 0 0 1 9.8 4 8.4 8.4 0 1 0 20 14.2"/></svg>
    <svg class="sb-35__sun" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="4"/><path d="M12 3.4v2M12 18.6v2M3.4 12h2M18.6 12h2M6 6l1.4 1.4M16.6 16.6 18 18M18 6l-1.4 1.4M7.4 16.6 6 18"/></svg>
  </button>
  <div class="sb-35__stage">
    <div class="sb-35__page">
      <header class="sb-35__header">
        <span class="sb-35__brand"><span class="sb-35__mark" aria-hidden="true"></span>Atlas</span>
        <button class="sb-35__trigger" id="sb-35-open" type="button" aria-haspopup="dialog" aria-expanded="false">
          <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="6.3" stroke="currentColor" stroke-width="1.8"/><path d="m15.9 15.9 4.3 4.3" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
          <span>Search Atlas</span>
        </button>
      </header>
      <div class="sb-35__body" aria-hidden="true">
        <span class="sb-35__sk sb-35__sk--wide"></span>
        <span class="sb-35__sk"></span>
        <span class="sb-35__sk sb-35__sk--short"></span>
      </div>
    </div>

    <dialog class="sb-35__modal" id="sb-35-modal" aria-label="Search Atlas">
      <div class="sb-35__field" role="search">
        <svg class="sb-35__ico" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="6.4" stroke="currentColor" stroke-width="1.8"/><path d="m16 16 4.2 4.2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
        <label class="sb-35__vh" for="sb-35-input">Search Atlas</label>
        <input class="sb-35__input" id="sb-35-input" type="search" placeholder="Search articles, guides and people&hellip;" autocomplete="off">
        <button class="sb-35__close" id="sb-35-close" type="button" aria-label="Close search">
          <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="m7 7 10 10M17 7 7 17" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
        </button>
      </div>
      <p class="sb-35__h">Recently viewed</p>
      <ul class="sb-35__grid">
        <li class="sb-35__card"><span class="sb-35__tag">Guide</span>Designing search that feels instant<span class="sb-35__meta">8 min read</span></li>
        <li class="sb-35__card"><span class="sb-35__tag">Doc</span>Q3 revenue forecast<span class="sb-35__meta">Updated 2h ago</span></li>
        <li class="sb-35__card"><span class="sb-35__tag">Person</span>Priya Sharma<span class="sb-35__meta">Product lead</span></li>
        <li class="sb-35__card"><span class="sb-35__tag">Guide</span>Onboarding checklist<span class="sb-35__meta">12 steps</span></li>
      </ul>
    </dialog>
  </div>
</div>
.sb-35 {
  --bg: #f2f3f7;
  --card: #ffffff;
  --ink: #131722;
  --muted: #6a7180;
  --line: #e4e7ee;
  --acc: #2c5cff;
  --wash: rgba(44,92,255,.10);
  --ring: #2c5cff;
  --shadow: rgba(19,23,34,.2);
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  box-sizing: border-box;
  font-family: system-ui,-apple-system,"Segoe UI",sans-serif;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

.sb-35 *,
.sb-35 *::before,
.sb-35 *::after {
  box-sizing: border-box;
}

.sb-35__stage {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: clamp(1rem,4vw,3rem);
}

.sb-35__vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.sb-35__page {
  inline-size: min(46rem,100%);
  padding: 1rem 1.1rem 2.4rem;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--card);
  box-shadow: 0 24px 50px -34px var(--shadow);
}

.sb-35__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.sb-35__brand {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font: 700 1rem/1 inherit;
  letter-spacing: -.02em;
}

.sb-35__mark {
  inline-size: 20px;
  block-size: 20px;
  border-radius: 6px;
  background: conic-gradient(from 200deg,#2c5cff,#7c3aed 45%,#06b6d4 80%,#2c5cff);
}

.sb-35__trigger {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  min-block-size: 44px;
  padding-inline: .9rem;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: #fafbfd;
  color: var(--muted);
  cursor: pointer;
  font: 500 .9rem/1 inherit;
  transition: border-color .18s, color .18s, background .18s;
}

.sb-35__trigger:hover {
  border-color: var(--acc);
  color: var(--ink);
  background: var(--card);
}

.sb-35__trigger svg {
  inline-size: 17px;
  block-size: 17px;
}

.sb-35__body {
  display: grid;
  gap: .7rem;
  margin-block-start: 1.6rem;
}

.sb-35__sk {
  block-size: .85rem;
  border-radius: 6px;
  background: #eef0f5;
  inline-size: 78%;
}

.sb-35__sk--wide {
  inline-size: 100%;
  block-size: 1.6rem;
}

.sb-35__sk--short {
  inline-size: 52%;
}

.sb-35__modal {
  inline-size: min(42rem,92vw);
  max-block-size: min(34rem,84svh);
  margin-block-start: 10vh;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 2px 4px rgba(19,23,34,.08), 0 12px 24px -8px rgba(19,23,34,.14), 0 40px 80px -24px var(--shadow), inset 0 1px 0 rgba(255,255,255,.7);
  flex-direction: column;
}

.sb-35__modal[open] {
  display: flex;
}

.sb-35__modal::backdrop {
  background: rgba(10,12,20,.5);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

@supports (transition-behavior: allow-discrete) {
  .sb-35__modal {
    opacity: 0;
    translate: 0 12px;
    scale: .98;
    transition: opacity .24s cubic-bezier(.2,.9,.25,1), translate .24s cubic-bezier(.2,.9,.25,1), scale .24s, overlay .24s allow-discrete, display .24s allow-discrete;
  }

  .sb-35__modal[open] {
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }

  @starting-style {
    .sb-35__modal[open] {
      opacity: 0;
      translate: 0 12px;
      scale: .98;
    }
  }
}

.sb-35__field {
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: 1rem 1rem 1rem 1.25rem;
  border-block-end: 1px solid var(--line);
}

.sb-35__ico {
  inline-size: 21px;
  block-size: 21px;
  flex: none;
  color: var(--muted);
}

.sb-35__input {
  flex: 1;
  min-inline-size: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: 400 1.05rem/1.3 inherit;
}

.sb-35__input::placeholder {
  color: var(--muted);
}

.sb-35__input:focus {
  outline: none;
}

.sb-35__input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.sb-35__close {
  display: grid;
  place-items: center;
  inline-size: 36px;
  block-size: 36px;
  flex: none;
  border: 0;
  border-radius: 10px;
  background: #f2f4f8;
  color: var(--muted);
  cursor: pointer;
  transition: background .16s, color .16s;
}

.sb-35__close:hover {
  background: #e7eaf1;
  color: var(--ink);
}

.sb-35__close svg {
  inline-size: 15px;
  block-size: 15px;
}

.sb-35__h {
  margin: 1rem 1.25rem .5rem;
  color: var(--muted);
  font: 600 .68rem/1 inherit;
  letter-spacing: .09em;
  text-transform: uppercase;
}

.sb-35__grid {
  list-style: none;
  margin: 0;
  padding: 0 1rem 1.1rem;
  display: grid;
  gap: .6rem;
  grid-template-columns: repeat(auto-fit,minmax(15rem,1fr));
  overflow: auto;
  overscroll-behavior: contain;
}

.sb-35__card {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  padding: .85rem .9rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #fbfcfe;
  cursor: pointer;
  font: 600 .92rem/1.3 inherit;
  text-wrap: pretty;
  transition: border-color .16s, translate .16s, background .16s;
}

.sb-35__card:hover {
  border-color: var(--acc);
  background: var(--card);
  translate: 0 -1px;
}

.sb-35__tag {
  align-self: start;
  padding: .16rem .4rem;
  border-radius: 5px;
  background: var(--wash);
  color: var(--acc);
  font: 600 .66rem/1 inherit;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.sb-35__meta {
  color: var(--muted);
  font: 400 .78rem/1 inherit;
}

.sb-35 :focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.sb-35__input:focus-visible {
  outline: none;
}

.sb-35[data-theme="dark"] {
  --bg: #0a0c12;
  --card: #141821;
  --ink: #e9ecf4;
  --muted: #878e9e;
  --line: #232936;
  --acc: #7c9cff;
  --wash: rgba(124,156,255,.14);
  --ring: #7c9cff;
  --shadow: rgba(0,0,0,.8);
}

.sb-35[data-theme="dark"] .sb-35__trigger,
.sb-35[data-theme="dark"] .sb-35__card {
  background: #101520;
}

.sb-35[data-theme="dark"] .sb-35__sk {
  background: #1b2230;
}

.sb-35[data-theme="dark"] .sb-35__close {
  background: #1b2230;
}

.sb-35[data-theme="dark"] .sb-35__modal {
  box-shadow: 0 40px 80px -24px #000, inset 0 1px 0 rgba(255,255,255,.05);
}

@media (prefers-color-scheme: dark) {
  .sb-35:not([data-theme="light"]) {
    --bg: #0a0c12;
    --card: #141821;
    --ink: #e9ecf4;
    --muted: #878e9e;
    --line: #232936;
    --acc: #7c9cff;
    --wash: rgba(124,156,255,.14);
    --ring: #7c9cff;
    --shadow: rgba(0,0,0,.8);
  }

  .sb-35:not([data-theme="light"]) .sb-35__trigger,
    .sb-35:not([data-theme="light"]) .sb-35__card {
    background: #101520;
  }

  .sb-35:not([data-theme="light"]) .sb-35__sk {
    background: #1b2230;
  }

  .sb-35:not([data-theme="light"]) .sb-35__close {
    background: #1b2230;
  }

  .sb-35:not([data-theme="light"]) .sb-35__modal {
    box-shadow: 0 40px 80px -24px #000, inset 0 1px 0 rgba(255,255,255,.05);
  }
}

@media (prefers-reduced-motion: reduce) {
  .sb-35 *,
    .sb-35 *::before,
    .sb-35 *::after {
    transition: none !important;
    animation: none !important;
  }
}

@media (forced-colors: active) {
  .sb-35__modal,
    .sb-35__page,
    .sb-35__trigger,
    .sb-35__card {
    border: 1px solid CanvasText;
  }
}

.sb-35__theme {
  position: absolute;
  inset-block-start: clamp(.75rem,2vw,1.25rem);
  inset-inline-end: clamp(.75rem,2vw,1.25rem);
  z-index: 50;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  display: grid;
  place-items: center;
  cursor: pointer;
  padding: 0;
  border-radius: 999px;
  border: 1px solid rgba(0,0,0,.12);
  color: currentColor;
  background: rgba(255,255,255,.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  transition: background .25s ease, transform .25s cubic-bezier(.16,1,.3,1), border-color .25s ease;
}

.sb-35[data-theme="dark"] .sb-35__theme {
  background: rgba(20,20,28,.72);
  border-color: rgba(255,255,255,.15);
  color: #fff;
}

@media (prefers-color-scheme: dark) {
  .sb-35:not([data-theme="light"]) .sb-35__theme {
    background: rgba(20,20,28,.72);
    border-color: rgba(255,255,255,.15);
    color: #fff;
  }
}

.sb-35__theme:hover {
  transform: translateY(-1px);
  border-color: rgba(0,0,0,.24);
}

.sb-35[data-theme="dark"] .sb-35__theme:hover,
.sb-35:not([data-theme="light"]) .sb-35__theme:hover {
  border-color: rgba(255,255,255,.3);
}

.sb-35__theme:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.sb-35__theme svg {
  grid-area: 1/1;
  inline-size: 1.1rem;
  block-size: 1.1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sb-35__sun {
  display: none;
}

.sb-35__theme[aria-pressed="true"] .sb-35__sun {
  display: block;
}

.sb-35__theme[aria-pressed="true"] .sb-35__moon {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .sb-35__theme {
    transition: none;
  }

  .sb-35__theme:hover {
    transform: none;
  }
}
(() => {
  const root = document.querySelector('.sb-35');
  if (!root) return;
  const dlg = root.querySelector('#sb-35-modal');
  const trigger = root.querySelector('#sb-35-open');
  const input = root.querySelector('#sb-35-input');

  const open = () => { dlg.showModal(); trigger.setAttribute('aria-expanded', 'true'); input.focus(); };
  trigger.addEventListener('click', open);
  root.querySelector('#sb-35-close').addEventListener('click', () => dlg.close());
  dlg.addEventListener('click', (e) => { if (e.target === dlg) dlg.close(); });   /* backdrop click */
  dlg.addEventListener('close', () => { trigger.setAttribute('aria-expanded', 'false'); trigger.focus(); });
  document.addEventListener('keydown', (e) => {
    if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); dlg.open ? dlg.close() : open(); }
  });
})();
(()=>{const r=document.querySelector('.sb-35');if(!r)return;const t=r.querySelector('.sb-35__theme');if(!t)return;const dark=()=>(r.dataset.theme||(matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'))==='dark';const sync=()=>{t.setAttribute('aria-pressed',String(dark()));t.setAttribute('aria-label',dark()?'Switch to light theme':'Switch to dark theme');};t.addEventListener('click',()=>{r.dataset.theme=dark()?'light':'dark';sync();});matchMedia('(prefers-color-scheme: dark)').addEventListener('change',()=>{if(!r.dataset.theme)sync();});sync();})();
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 Search Bar 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 Card CSS Search Bar (Modal Style)
Source: https://codefronts.com/components/css-search-boxes/floating-card/

Search-as-overlay: click the header field and a raised card floats above a dimmed, blurred page with a large input and recent result cards. A native <dialog> handles focus trapping, Escape and the backdrop — the pattern behind Notion, Vercel and most editorial sites.
## HTML
```html
<div class="sb-35">
  <button class="sb-35__theme" type="button" aria-pressed="false" aria-label="Switch to dark theme">
    <svg class="sb-35__moon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M20 14.2A8.2 8.2 0 0 1 9.8 4 8.4 8.4 0 1 0 20 14.2"/></svg>
    <svg class="sb-35__sun" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="4"/><path d="M12 3.4v2M12 18.6v2M3.4 12h2M18.6 12h2M6 6l1.4 1.4M16.6 16.6 18 18M18 6l-1.4 1.4M7.4 16.6 6 18"/></svg>
  </button>
  <div class="sb-35__stage">
    <div class="sb-35__page">
      <header class="sb-35__header">
        <span class="sb-35__brand"><span class="sb-35__mark" aria-hidden="true"></span>Atlas</span>
        <button class="sb-35__trigger" id="sb-35-open" type="button" aria-haspopup="dialog" aria-expanded="false">
          <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="6.3" stroke="currentColor" stroke-width="1.8"/><path d="m15.9 15.9 4.3 4.3" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
          <span>Search Atlas</span>
        </button>
      </header>
      <div class="sb-35__body" aria-hidden="true">
        <span class="sb-35__sk sb-35__sk--wide"></span>
        <span class="sb-35__sk"></span>
        <span class="sb-35__sk sb-35__sk--short"></span>
      </div>
    </div>

    <dialog class="sb-35__modal" id="sb-35-modal" aria-label="Search Atlas">
      <div class="sb-35__field" role="search">
        <svg class="sb-35__ico" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><circle cx="11" cy="11" r="6.4" stroke="currentColor" stroke-width="1.8"/><path d="m16 16 4.2 4.2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
        <label class="sb-35__vh" for="sb-35-input">Search Atlas</label>
        <input class="sb-35__input" id="sb-35-input" type="search" placeholder="Search articles, guides and people&hellip;" autocomplete="off">
        <button class="sb-35__close" id="sb-35-close" type="button" aria-label="Close search">
          <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="m7 7 10 10M17 7 7 17" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
        </button>
      </div>
      <p class="sb-35__h">Recently viewed</p>
      <ul class="sb-35__grid">
        <li class="sb-35__card"><span class="sb-35__tag">Guide</span>Designing search that feels instant<span class="sb-35__meta">8 min read</span></li>
        <li class="sb-35__card"><span class="sb-35__tag">Doc</span>Q3 revenue forecast<span class="sb-35__meta">Updated 2h ago</span></li>
        <li class="sb-35__card"><span class="sb-35__tag">Person</span>Priya Sharma<span class="sb-35__meta">Product lead</span></li>
        <li class="sb-35__card"><span class="sb-35__tag">Guide</span>Onboarding checklist<span class="sb-35__meta">12 steps</span></li>
      </ul>
    </dialog>
  </div>
</div>
```
## CSS
```css
.sb-35 {
  --bg: #f2f3f7;
  --card: #ffffff;
  --ink: #131722;
  --muted: #6a7180;
  --line: #e4e7ee;
  --acc: #2c5cff;
  --wash: rgba(44,92,255,.10);
  --ring: #2c5cff;
  --shadow: rgba(19,23,34,.2);
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  box-sizing: border-box;
  font-family: system-ui,-apple-system,"Segoe UI",sans-serif;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

.sb-35 *,
.sb-35 *::before,
.sb-35 *::after {
  box-sizing: border-box;
}

.sb-35__stage {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: clamp(1rem,4vw,3rem);
}

.sb-35__vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.sb-35__page {
  inline-size: min(46rem,100%);
  padding: 1rem 1.1rem 2.4rem;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--card);
  box-shadow: 0 24px 50px -34px var(--shadow);
}

.sb-35__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.sb-35__brand {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font: 700 1rem/1 inherit;
  letter-spacing: -.02em;
}

.sb-35__mark {
  inline-size: 20px;
  block-size: 20px;
  border-radius: 6px;
  background: conic-gradient(from 200deg,#2c5cff,#7c3aed 45%,#06b6d4 80%,#2c5cff);
}

.sb-35__trigger {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  min-block-size: 44px;
  padding-inline: .9rem;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: #fafbfd;
  color: var(--muted);
  cursor: pointer;
  font: 500 .9rem/1 inherit;
  transition: border-color .18s, color .18s, background .18s;
}

.sb-35__trigger:hover {
  border-color: var(--acc);
  color: var(--ink);
  background: var(--card);
}

.sb-35__trigger svg {
  inline-size: 17px;
  block-size: 17px;
}

.sb-35__body {
  display: grid;
  gap: .7rem;
  margin-block-start: 1.6rem;
}

.sb-35__sk {
  block-size: .85rem;
  border-radius: 6px;
  background: #eef0f5;
  inline-size: 78%;
}

.sb-35__sk--wide {
  inline-size: 100%;
  block-size: 1.6rem;
}

.sb-35__sk--short {
  inline-size: 52%;
}

.sb-35__modal {
  inline-size: min(42rem,92vw);
  max-block-size: min(34rem,84svh);
  margin-block-start: 10vh;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 2px 4px rgba(19,23,34,.08), 0 12px 24px -8px rgba(19,23,34,.14), 0 40px 80px -24px var(--shadow), inset 0 1px 0 rgba(255,255,255,.7);
  flex-direction: column;
}

.sb-35__modal[open] {
  display: flex;
}

.sb-35__modal::backdrop {
  background: rgba(10,12,20,.5);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

@supports (transition-behavior: allow-discrete) {
  .sb-35__modal {
    opacity: 0;
    translate: 0 12px;
    scale: .98;
    transition: opacity .24s cubic-bezier(.2,.9,.25,1), translate .24s cubic-bezier(.2,.9,.25,1), scale .24s, overlay .24s allow-discrete, display .24s allow-discrete;
  }

  .sb-35__modal[open] {
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }

  @starting-style {
    .sb-35__modal[open] {
      opacity: 0;
      translate: 0 12px;
      scale: .98;
    }
  }
}

.sb-35__field {
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: 1rem 1rem 1rem 1.25rem;
  border-block-end: 1px solid var(--line);
}

.sb-35__ico {
  inline-size: 21px;
  block-size: 21px;
  flex: none;
  color: var(--muted);
}

.sb-35__input {
  flex: 1;
  min-inline-size: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: 400 1.05rem/1.3 inherit;
}

.sb-35__input::placeholder {
  color: var(--muted);
}

.sb-35__input:focus {
  outline: none;
}

.sb-35__input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.sb-35__close {
  display: grid;
  place-items: center;
  inline-size: 36px;
  block-size: 36px;
  flex: none;
  border: 0;
  border-radius: 10px;
  background: #f2f4f8;
  color: var(--muted);
  cursor: pointer;
  transition: background .16s, color .16s;
}

.sb-35__close:hover {
  background: #e7eaf1;
  color: var(--ink);
}

.sb-35__close svg {
  inline-size: 15px;
  block-size: 15px;
}

.sb-35__h {
  margin: 1rem 1.25rem .5rem;
  color: var(--muted);
  font: 600 .68rem/1 inherit;
  letter-spacing: .09em;
  text-transform: uppercase;
}

.sb-35__grid {
  list-style: none;
  margin: 0;
  padding: 0 1rem 1.1rem;
  display: grid;
  gap: .6rem;
  grid-template-columns: repeat(auto-fit,minmax(15rem,1fr));
  overflow: auto;
  overscroll-behavior: contain;
}

.sb-35__card {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  padding: .85rem .9rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #fbfcfe;
  cursor: pointer;
  font: 600 .92rem/1.3 inherit;
  text-wrap: pretty;
  transition: border-color .16s, translate .16s, background .16s;
}

.sb-35__card:hover {
  border-color: var(--acc);
  background: var(--card);
  translate: 0 -1px;
}

.sb-35__tag {
  align-self: start;
  padding: .16rem .4rem;
  border-radius: 5px;
  background: var(--wash);
  color: var(--acc);
  font: 600 .66rem/1 inherit;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.sb-35__meta {
  color: var(--muted);
  font: 400 .78rem/1 inherit;
}

.sb-35 :focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.sb-35__input:focus-visible {
  outline: none;
}

.sb-35[data-theme="dark"] {
  --bg: #0a0c12;
  --card: #141821;
  --ink: #e9ecf4;
  --muted: #878e9e;
  --line: #232936;
  --acc: #7c9cff;
  --wash: rgba(124,156,255,.14);
  --ring: #7c9cff;
  --shadow: rgba(0,0,0,.8);
}

.sb-35[data-theme="dark"] .sb-35__trigger,
.sb-35[data-theme="dark"] .sb-35__card {
  background: #101520;
}

.sb-35[data-theme="dark"] .sb-35__sk {
  background: #1b2230;
}

.sb-35[data-theme="dark"] .sb-35__close {
  background: #1b2230;
}

.sb-35[data-theme="dark"] .sb-35__modal {
  box-shadow: 0 40px 80px -24px #000, inset 0 1px 0 rgba(255,255,255,.05);
}

@media (prefers-color-scheme: dark) {
  .sb-35:not([data-theme="light"]) {
    --bg: #0a0c12;
    --card: #141821;
    --ink: #e9ecf4;
    --muted: #878e9e;
    --line: #232936;
    --acc: #7c9cff;
    --wash: rgba(124,156,255,.14);
    --ring: #7c9cff;
    --shadow: rgba(0,0,0,.8);
  }

  .sb-35:not([data-theme="light"]) .sb-35__trigger,
    .sb-35:not([data-theme="light"]) .sb-35__card {
    background: #101520;
  }

  .sb-35:not([data-theme="light"]) .sb-35__sk {
    background: #1b2230;
  }

  .sb-35:not([data-theme="light"]) .sb-35__close {
    background: #1b2230;
  }

  .sb-35:not([data-theme="light"]) .sb-35__modal {
    box-shadow: 0 40px 80px -24px #000, inset 0 1px 0 rgba(255,255,255,.05);
  }
}

@media (prefers-reduced-motion: reduce) {
  .sb-35 *,
    .sb-35 *::before,
    .sb-35 *::after {
    transition: none !important;
    animation: none !important;
  }
}

@media (forced-colors: active) {
  .sb-35__modal,
    .sb-35__page,
    .sb-35__trigger,
    .sb-35__card {
    border: 1px solid CanvasText;
  }
}

.sb-35__theme {
  position: absolute;
  inset-block-start: clamp(.75rem,2vw,1.25rem);
  inset-inline-end: clamp(.75rem,2vw,1.25rem);
  z-index: 50;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  display: grid;
  place-items: center;
  cursor: pointer;
  padding: 0;
  border-radius: 999px;
  border: 1px solid rgba(0,0,0,.12);
  color: currentColor;
  background: rgba(255,255,255,.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  transition: background .25s ease, transform .25s cubic-bezier(.16,1,.3,1), border-color .25s ease;
}

.sb-35[data-theme="dark"] .sb-35__theme {
  background: rgba(20,20,28,.72);
  border-color: rgba(255,255,255,.15);
  color: #fff;
}

@media (prefers-color-scheme: dark) {
  .sb-35:not([data-theme="light"]) .sb-35__theme {
    background: rgba(20,20,28,.72);
    border-color: rgba(255,255,255,.15);
    color: #fff;
  }
}

.sb-35__theme:hover {
  transform: translateY(-1px);
  border-color: rgba(0,0,0,.24);
}

.sb-35[data-theme="dark"] .sb-35__theme:hover,
.sb-35:not([data-theme="light"]) .sb-35__theme:hover {
  border-color: rgba(255,255,255,.3);
}

.sb-35__theme:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.sb-35__theme svg {
  grid-area: 1/1;
  inline-size: 1.1rem;
  block-size: 1.1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sb-35__sun {
  display: none;
}

.sb-35__theme[aria-pressed="true"] .sb-35__sun {
  display: block;
}

.sb-35__theme[aria-pressed="true"] .sb-35__moon {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .sb-35__theme {
    transition: none;
  }

  .sb-35__theme:hover {
    transform: none;
  }
}
```

## JavaScript
```js
(() => {
  const root = document.querySelector('.sb-35');
  if (!root) return;
  const dlg = root.querySelector('#sb-35-modal');
  const trigger = root.querySelector('#sb-35-open');
  const input = root.querySelector('#sb-35-input');

  const open = () => { dlg.showModal(); trigger.setAttribute('aria-expanded', 'true'); input.focus(); };
  trigger.addEventListener('click', open);
  root.querySelector('#sb-35-close').addEventListener('click', () => dlg.close());
  dlg.addEventListener('click', (e) => { if (e.target === dlg) dlg.close(); });   /* backdrop click */
  dlg.addEventListener('close', () => { trigger.setAttribute('aria-expanded', 'false'); trigger.focus(); });
  document.addEventListener('keydown', (e) => {
    if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); dlg.open ? dlg.close() : open(); }
  });
})();
(()=>{const r=document.querySelector('.sb-35');if(!r)return;const t=r.querySelector('.sb-35__theme');if(!t)return;const dark=()=>(r.dataset.theme||(matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'))==='dark';const sync=()=>{t.setAttribute('aria-pressed',String(dark()));t.setAttribute('aria-label',dark()?'Switch to light theme':'Switch to dark theme');};t.addEventListener('click',()=>{r.dataset.theme=dark()?'light':'dark';sync();});matchMedia('(prefers-color-scheme: dark)').addEventListener('change',()=>{if(!r.dataset.theme)sync();});sync();})();
```

How this works

The overlay is a dialog, not a div. Everything that makes an overlay hard — focus trapping, Escape, background inertness, stacking above every other element — is free with showModal():

trigger.addEventListener('click', () => { dlg.showModal(); input.focus(); });
dlg.addEventListener('close', () => trigger.focus());              /* return focus */
dlg.addEventListener('click', (e) => { if (e.target === dlg) dlg.close(); });  /* backdrop */

That last line is the whole "click outside to dismiss" behaviour: a click on the dialog element itself (rather than its children) means the user hit the backdrop area.

Dimming with depth. The backdrop uses both a dark wash and a blur so the page reads as out of focus rather than merely darkened:

.sb-35__modal::backdrop{background:rgba(10,12,20,.55); backdrop-filter:blur(6px);}

The card floats on a four-layer shadow and a 1px inner highlight — the same elevation language as demo #25, so the two can coexist in one product.

Make it yours

  • Change the card width with a single inline-size:min(42rem,92vw); the result grid re-flows via auto-fit.
  • Swap result cards for a list by changing the grid to a single column — the card styles are unchanged.
  • Open on / or ⌘K as well by adding a document keydown listener (see demos #01 and #16).
  • For a full-bleed mobile treatment, add @media (max-width:32rem){.sb-35__modal{inline-size:100vw; block-size:100dvh; border-radius:0}}.

Gotchas — read before shipping

  • Never put display on the dialog itself: an author display:flex outranks the UA dialog:not([open]){display:none} rule, so the closed dialog stays laid out as an invisible full-size overlay that swallows every click on the page beneath it. Set the layout on [open] instead — .sb-35__modal[open]{display:flex} — which keeps the allow-discrete exit transition working.
  • Do not animate a dialog with visibility; use @starting-style with allow-discrete, or it will pop in with no transition.
  • Always return focus to the trigger on close — otherwise keyboard users land back at the top of the document.
  • A blurred backdrop over a busy page is expensive; keep the blur radius modest (6-10px) and never animate it.
  • <dialog> without showModal() (i.e. the open attribute) is non-modal: no backdrop, no focus trap. Use the method, not the attribute.

Browser support

ChromeSafariFirefoxEdge
117+17.4+129+117+

<dialog>/showModal() is Chrome 37 / Safari 15.4 / Firefox 98. @starting-style + allow-discrete (Chrome 117 / Safari 17.4 / Firefox 129) affect only the enter animation. backdrop-filter needs the -webkit- prefix on older Safari; both are declared.

Techniques used in this demo

Search CodeFronts

Loading…