17 / 20
All 20 in 20 Tailwind CSS Kbd Keys
- 01Tailwind CSS Kbd Tag Styling for Inline Keyboard Keys
- 02Tailwind 3D Keycap Button with Press-Down Effect
- 03Tailwind Keyboard Shortcut Combo with Plus Separators
- 04Flat Minimalist Tailwind Kbd Key for Body Text
- 05Responsive Tailwind Kbd Sizing with Em Units
- 06Tailwind Mac Cmd vs Windows Ctrl Shortcut Toggle
- 07Tailwind Arrow Keys and Navigation Key Layout
- 08Auto-Detect OS Keyboard Shortcuts (Cmd or Ctrl) in Tailwind
- 09Tailwind Keyboard Layout with Function Keys and Space Bar
- 10Tailwind Icon Keycaps with Inline SVG
- 11Tailwind Search Input with Cmd+K Shortcut Hint
- 12Tailwind Keyboard Shortcuts Cheat Sheet Grid
- 13Tailwind Tooltip with Keyboard Shortcut Hint
- 14Tailwind Keyboard Shortcut Settings Table
- 15Live Key Press Visualizer with Tailwind CSS
- 16Neumorphic Keycap Design in Tailwind CSS
- 17Glassmorphism Keyboard Keys in Tailwind CSS
- 18Retro Typewriter Round Keys in Tailwind CSS
- 19Terminal-Style Monospace Kbd Keys in Tailwind
- 20Dark Mode Kbd Keys with Tailwind CSS Variables
Glassmorphism Keyboard Keys in Tailwind CSS
A frosted media-player shortcut panel over a colour field: the panel and every key blur what sits behind them. A solid, readable fill is declared first; supports-[backdrop-filter:blur(1px)]: swaps in the translucent fill and backdrop-blur-2xl only where blur actually works — so text never lands on an unblurred, busy background.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="kbd-17 relative w-full min-h-svh scheme-light kbd17-dark:scheme-dark bg-kbd17-bg bg-[radial-gradient(38%_48%_at_18%_22%,var(--color-kbd17-b1),transparent_70%),radial-gradient(42%_52%_at_84%_28%,var(--color-kbd17-b2),transparent_70%),radial-gradient(55%_50%_at_50%_95%,var(--color-kbd17-b3),transparent_72%)] text-kbd17-ink font-kbd17-sans" aria-label="Glassmorphic translucent keycap demo">
<div class="grid min-h-svh place-items-center px-5 pt-20 pb-12">
<div class="w-full min-w-0 max-w-[26rem] rounded-3xl border border-kbd17-edge bg-kbd17-panel p-6 shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_30px_60px_-30px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-glass supports-[backdrop-filter:blur(1px)]:backdrop-blur-2xl supports-[backdrop-filter:blur(1px)]:backdrop-saturate-150 sm:p-7">
<p class="mb-2 text-[11px] font-semibold uppercase tracking-[0.22em] text-kbd17-mut">Now playing · shortcuts</p>
<div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Play or pause</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span class="px-5">Space</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Next track</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⌘</span><span class="sr-only">Command</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">→</span><span class="sr-only">Right arrow</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Volume up</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⌥</span><span class="sr-only">Option</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">↑</span><span class="sr-only">Up arrow</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Shuffle queue</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⇧</span><span class="sr-only">Shift</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md">S</kbd></kbd></div>
</div>
<p class="mt-3 text-[12px] text-kbd17-mut">Solid fill declared first · blur added behind <code class="font-mono">@supports</code></p>
</div>
</div>
<div class="absolute top-3.5 right-4 z-10">
<input id="kbd-17-theme" type="checkbox" class="peer sr-only">
<label for="kbd-17-theme" class="inline-flex min-h-11 cursor-pointer select-none items-center gap-2.5 rounded-full border border-current/55 px-4 font-sans text-[11px] font-bold uppercase leading-none tracking-[0.16em] text-kbd17-ink transition-colors hover:border-current peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-kbd17-acc">
<span aria-hidden="true" class="size-3 flex-none rounded-full bg-current transition-[background-color,box-shadow] duration-300 kbd17-dark:bg-transparent kbd17-dark:shadow-[inset_-4px_-2px_0_0_currentColor] motion-reduce:transition-none"></span>
<span class="kbd17-dark:hidden">Light</span><span class="hidden kbd17-dark:inline">Dark</span><span class="sr-only"> theme</span>
</label>
</div>
</section><section class="kbd-17 relative w-full min-h-svh scheme-light kbd17-dark:scheme-dark bg-kbd17-bg bg-[radial-gradient(38%_48%_at_18%_22%,var(--color-kbd17-b1),transparent_70%),radial-gradient(42%_52%_at_84%_28%,var(--color-kbd17-b2),transparent_70%),radial-gradient(55%_50%_at_50%_95%,var(--color-kbd17-b3),transparent_72%)] text-kbd17-ink font-kbd17-sans" aria-label="Glassmorphic translucent keycap demo">
<div class="grid min-h-svh place-items-center px-5 pt-20 pb-12">
<div class="w-full min-w-0 max-w-[26rem] rounded-3xl border border-kbd17-edge bg-kbd17-panel p-6 shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_30px_60px_-30px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-glass supports-[backdrop-filter:blur(1px)]:backdrop-blur-2xl supports-[backdrop-filter:blur(1px)]:backdrop-saturate-150 sm:p-7">
<p class="mb-2 text-[11px] font-semibold uppercase tracking-[0.22em] text-kbd17-mut">Now playing · shortcuts</p>
<div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Play or pause</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span class="px-5">Space</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Next track</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⌘</span><span class="sr-only">Command</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">→</span><span class="sr-only">Right arrow</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Volume up</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⌥</span><span class="sr-only">Option</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">↑</span><span class="sr-only">Up arrow</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Shuffle queue</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⇧</span><span class="sr-only">Shift</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md">S</kbd></kbd></div>
</div>
<p class="mt-3 text-[12px] text-kbd17-mut">Solid fill declared first · blur added behind <code class="font-mono">@supports</code></p>
</div>
</div>
<div class="absolute top-3.5 right-4 z-10">
<input id="kbd-17-theme" type="checkbox" class="peer sr-only">
<label for="kbd-17-theme" class="inline-flex min-h-11 cursor-pointer select-none items-center gap-2.5 rounded-full border border-current/55 px-4 font-sans text-[11px] font-bold uppercase leading-none tracking-[0.16em] text-kbd17-ink transition-colors hover:border-current peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-kbd17-acc">
<span aria-hidden="true" class="size-3 flex-none rounded-full bg-current transition-[background-color,box-shadow] duration-300 kbd17-dark:bg-transparent kbd17-dark:shadow-[inset_-4px_-2px_0_0_currentColor] motion-reduce:transition-none"></span>
<span class="kbd17-dark:hidden">Light</span><span class="hidden kbd17-dark:inline">Dark</span><span class="sr-only"> theme</span>
</label>
</div>
</section>@import "tailwindcss";
/* Theme state: follows the OS; the corner switch flips it for THIS demo only. */
@custom-variant kbd17-dark {
@media (prefers-color-scheme: dark) {
&:where(.kbd-17:not(:has(#kbd-17-theme:checked)), .kbd-17:not(:has(#kbd-17-theme:checked)) *) {
@slot;
}
}
@media (prefers-color-scheme: light) {
&:where(.kbd-17:has(#kbd-17-theme:checked), .kbd-17:has(#kbd-17-theme:checked) *) {
@slot;
}
}
}
/* Every colour is light-dark(day, night): the root's scheme-light / scheme-dark utility picks the side. */
@theme {
--color-kbd17-bg: light-dark(#f3eefb, #0b0a14);
--color-kbd17-bg: light-dark(oklch(0.957 0.018 303.4), oklch(0.152 0.021 288.2));
--color-kbd17-b1: light-dark(#ff8fb1, #7a1d4d);
--color-kbd17-b1: light-dark(oklch(0.779 0.139 1.4), oklch(0.399 0.135 353.5));
--color-kbd17-b2: light-dark(#7cc4ff, #11407a);
--color-kbd17-b2: light-dark(oklch(0.796 0.111 244.6), oklch(0.375 0.111 256.1));
--color-kbd17-b3: light-dark(#ffd27a, #5a3a0c);
--color-kbd17-b3: light-dark(oklch(0.885 0.118 82.9), oklch(0.378 0.074 70.8));
--color-kbd17-panel: light-dark(#fbf9ff, #1a1826);
--color-kbd17-panel: light-dark(oklch(0.985 0.008 301.4), oklch(0.218 0.027 290.5));
--color-kbd17-glass: light-dark(#ffffff8c, #1c1a2b8c);
--color-kbd17-glass: light-dark(oklch(1 0 0 / 0.55), oklch(0.229 0.033 288.9 / 0.55));
--color-kbd17-keyfill: light-dark(#ffffff, #2a2840);
--color-kbd17-keyfill: light-dark(oklch(1 0 0), oklch(0.291 0.043 287.2));
--color-kbd17-keyglass: light-dark(#ffffffb3, #ffffff1f);
--color-kbd17-keyglass: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.12));
--color-kbd17-edge: light-dark(#ffffffb3, #ffffff26);
--color-kbd17-edge: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.15));
--color-kbd17-shine: light-dark(#ffffffe6, #ffffff33);
--color-kbd17-shine: light-dark(oklch(1 0 0 / 0.9), oklch(1 0 0 / 0.2));
--color-kbd17-shade: light-dark(#3b1d5c40, #000000b3);
--color-kbd17-shade: light-dark(oklch(0.308 0.109 302.3 / 0.25), oklch(0 0 0 / 0.7));
--color-kbd17-rule: light-dark(#1a103014, #ffffff1a);
--color-kbd17-rule: light-dark(oklch(0.206 0.061 294.9 / 0.08), oklch(1 0 0 / 0.1));
--color-kbd17-ink: light-dark(#1d1530, #f3f0fb);
--color-kbd17-ink: light-dark(oklch(0.221 0.052 295.5), oklch(0.961 0.015 298.6));
--color-kbd17-mut: light-dark(#4e4565, #bdb6cf);
--color-kbd17-mut: light-dark(oklch(0.413 0.054 296.9), oklch(0.79 0.036 298.4));
--color-kbd17-acc: light-dark(#7c3aed, #c4a6ff);
--color-kbd17-acc: light-dark(oklch(0.541 0.247 293), oklch(0.784 0.127 298.9));
--font-kbd17-sans: 'Sora', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as utilities so the stage is sized before the browser build compiles. */
.kbd-17 {
width: 100%;
min-height: 100svh;
position: relative;
}@import "tailwindcss";
/* Theme state: follows the OS; the corner switch flips it for THIS demo only. */
@custom-variant kbd17-dark {
@media (prefers-color-scheme: dark) {
&:where(.kbd-17:not(:has(#kbd-17-theme:checked)), .kbd-17:not(:has(#kbd-17-theme:checked)) *) {
@slot;
}
}
@media (prefers-color-scheme: light) {
&:where(.kbd-17:has(#kbd-17-theme:checked), .kbd-17:has(#kbd-17-theme:checked) *) {
@slot;
}
}
}
/* Every colour is light-dark(day, night): the root's scheme-light / scheme-dark utility picks the side. */
@theme {
--color-kbd17-bg: light-dark(#f3eefb, #0b0a14);
--color-kbd17-bg: light-dark(oklch(0.957 0.018 303.4), oklch(0.152 0.021 288.2));
--color-kbd17-b1: light-dark(#ff8fb1, #7a1d4d);
--color-kbd17-b1: light-dark(oklch(0.779 0.139 1.4), oklch(0.399 0.135 353.5));
--color-kbd17-b2: light-dark(#7cc4ff, #11407a);
--color-kbd17-b2: light-dark(oklch(0.796 0.111 244.6), oklch(0.375 0.111 256.1));
--color-kbd17-b3: light-dark(#ffd27a, #5a3a0c);
--color-kbd17-b3: light-dark(oklch(0.885 0.118 82.9), oklch(0.378 0.074 70.8));
--color-kbd17-panel: light-dark(#fbf9ff, #1a1826);
--color-kbd17-panel: light-dark(oklch(0.985 0.008 301.4), oklch(0.218 0.027 290.5));
--color-kbd17-glass: light-dark(#ffffff8c, #1c1a2b8c);
--color-kbd17-glass: light-dark(oklch(1 0 0 / 0.55), oklch(0.229 0.033 288.9 / 0.55));
--color-kbd17-keyfill: light-dark(#ffffff, #2a2840);
--color-kbd17-keyfill: light-dark(oklch(1 0 0), oklch(0.291 0.043 287.2));
--color-kbd17-keyglass: light-dark(#ffffffb3, #ffffff1f);
--color-kbd17-keyglass: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.12));
--color-kbd17-edge: light-dark(#ffffffb3, #ffffff26);
--color-kbd17-edge: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.15));
--color-kbd17-shine: light-dark(#ffffffe6, #ffffff33);
--color-kbd17-shine: light-dark(oklch(1 0 0 / 0.9), oklch(1 0 0 / 0.2));
--color-kbd17-shade: light-dark(#3b1d5c40, #000000b3);
--color-kbd17-shade: light-dark(oklch(0.308 0.109 302.3 / 0.25), oklch(0 0 0 / 0.7));
--color-kbd17-rule: light-dark(#1a103014, #ffffff1a);
--color-kbd17-rule: light-dark(oklch(0.206 0.061 294.9 / 0.08), oklch(1 0 0 / 0.1));
--color-kbd17-ink: light-dark(#1d1530, #f3f0fb);
--color-kbd17-ink: light-dark(oklch(0.221 0.052 295.5), oklch(0.961 0.015 298.6));
--color-kbd17-mut: light-dark(#4e4565, #bdb6cf);
--color-kbd17-mut: light-dark(oklch(0.413 0.054 296.9), oklch(0.79 0.036 298.4));
--color-kbd17-acc: light-dark(#7c3aed, #c4a6ff);
--color-kbd17-acc: light-dark(oklch(0.541 0.247 293), oklch(0.784 0.127 298.9));
--font-kbd17-sans: 'Sora', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as utilities so the stage is sized before the browser build compiles. */
.kbd-17 {
width: 100%;
min-height: 100svh;
position: relative;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<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.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
/* Theme state: follows the OS; the corner switch flips it for THIS demo only. */
@custom-variant kbd17-dark {
@media (prefers-color-scheme: dark) {
&:where(.kbd-17:not(:has(#kbd-17-theme:checked)), .kbd-17:not(:has(#kbd-17-theme:checked)) *) {
@slot;
}
}
@media (prefers-color-scheme: light) {
&:where(.kbd-17:has(#kbd-17-theme:checked), .kbd-17:has(#kbd-17-theme:checked) *) {
@slot;
}
}
}
/* Every colour is light-dark(day, night): the root's scheme-light / scheme-dark utility picks the side. */
@theme {
--color-kbd17-bg: light-dark(#f3eefb, #0b0a14);
--color-kbd17-bg: light-dark(oklch(0.957 0.018 303.4), oklch(0.152 0.021 288.2));
--color-kbd17-b1: light-dark(#ff8fb1, #7a1d4d);
--color-kbd17-b1: light-dark(oklch(0.779 0.139 1.4), oklch(0.399 0.135 353.5));
--color-kbd17-b2: light-dark(#7cc4ff, #11407a);
--color-kbd17-b2: light-dark(oklch(0.796 0.111 244.6), oklch(0.375 0.111 256.1));
--color-kbd17-b3: light-dark(#ffd27a, #5a3a0c);
--color-kbd17-b3: light-dark(oklch(0.885 0.118 82.9), oklch(0.378 0.074 70.8));
--color-kbd17-panel: light-dark(#fbf9ff, #1a1826);
--color-kbd17-panel: light-dark(oklch(0.985 0.008 301.4), oklch(0.218 0.027 290.5));
--color-kbd17-glass: light-dark(#ffffff8c, #1c1a2b8c);
--color-kbd17-glass: light-dark(oklch(1 0 0 / 0.55), oklch(0.229 0.033 288.9 / 0.55));
--color-kbd17-keyfill: light-dark(#ffffff, #2a2840);
--color-kbd17-keyfill: light-dark(oklch(1 0 0), oklch(0.291 0.043 287.2));
--color-kbd17-keyglass: light-dark(#ffffffb3, #ffffff1f);
--color-kbd17-keyglass: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.12));
--color-kbd17-edge: light-dark(#ffffffb3, #ffffff26);
--color-kbd17-edge: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.15));
--color-kbd17-shine: light-dark(#ffffffe6, #ffffff33);
--color-kbd17-shine: light-dark(oklch(1 0 0 / 0.9), oklch(1 0 0 / 0.2));
--color-kbd17-shade: light-dark(#3b1d5c40, #000000b3);
--color-kbd17-shade: light-dark(oklch(0.308 0.109 302.3 / 0.25), oklch(0 0 0 / 0.7));
--color-kbd17-rule: light-dark(#1a103014, #ffffff1a);
--color-kbd17-rule: light-dark(oklch(0.206 0.061 294.9 / 0.08), oklch(1 0 0 / 0.1));
--color-kbd17-ink: light-dark(#1d1530, #f3f0fb);
--color-kbd17-ink: light-dark(oklch(0.221 0.052 295.5), oklch(0.961 0.015 298.6));
--color-kbd17-mut: light-dark(#4e4565, #bdb6cf);
--color-kbd17-mut: light-dark(oklch(0.413 0.054 296.9), oklch(0.79 0.036 298.4));
--color-kbd17-acc: light-dark(#7c3aed, #c4a6ff);
--color-kbd17-acc: light-dark(oklch(0.541 0.247 293), oklch(0.784 0.127 298.9));
--font-kbd17-sans: 'Sora', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as utilities so the stage is sized before the browser build compiles. */
.kbd-17 {
width: 100%;
min-height: 100svh;
position: relative;
}@import "tailwindcss";
/* Theme state: follows the OS; the corner switch flips it for THIS demo only. */
@custom-variant kbd17-dark {
@media (prefers-color-scheme: dark) {
&:where(.kbd-17:not(:has(#kbd-17-theme:checked)), .kbd-17:not(:has(#kbd-17-theme:checked)) *) {
@slot;
}
}
@media (prefers-color-scheme: light) {
&:where(.kbd-17:has(#kbd-17-theme:checked), .kbd-17:has(#kbd-17-theme:checked) *) {
@slot;
}
}
}
/* Every colour is light-dark(day, night): the root's scheme-light / scheme-dark utility picks the side. */
@theme {
--color-kbd17-bg: light-dark(#f3eefb, #0b0a14);
--color-kbd17-bg: light-dark(oklch(0.957 0.018 303.4), oklch(0.152 0.021 288.2));
--color-kbd17-b1: light-dark(#ff8fb1, #7a1d4d);
--color-kbd17-b1: light-dark(oklch(0.779 0.139 1.4), oklch(0.399 0.135 353.5));
--color-kbd17-b2: light-dark(#7cc4ff, #11407a);
--color-kbd17-b2: light-dark(oklch(0.796 0.111 244.6), oklch(0.375 0.111 256.1));
--color-kbd17-b3: light-dark(#ffd27a, #5a3a0c);
--color-kbd17-b3: light-dark(oklch(0.885 0.118 82.9), oklch(0.378 0.074 70.8));
--color-kbd17-panel: light-dark(#fbf9ff, #1a1826);
--color-kbd17-panel: light-dark(oklch(0.985 0.008 301.4), oklch(0.218 0.027 290.5));
--color-kbd17-glass: light-dark(#ffffff8c, #1c1a2b8c);
--color-kbd17-glass: light-dark(oklch(1 0 0 / 0.55), oklch(0.229 0.033 288.9 / 0.55));
--color-kbd17-keyfill: light-dark(#ffffff, #2a2840);
--color-kbd17-keyfill: light-dark(oklch(1 0 0), oklch(0.291 0.043 287.2));
--color-kbd17-keyglass: light-dark(#ffffffb3, #ffffff1f);
--color-kbd17-keyglass: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.12));
--color-kbd17-edge: light-dark(#ffffffb3, #ffffff26);
--color-kbd17-edge: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.15));
--color-kbd17-shine: light-dark(#ffffffe6, #ffffff33);
--color-kbd17-shine: light-dark(oklch(1 0 0 / 0.9), oklch(1 0 0 / 0.2));
--color-kbd17-shade: light-dark(#3b1d5c40, #000000b3);
--color-kbd17-shade: light-dark(oklch(0.308 0.109 302.3 / 0.25), oklch(0 0 0 / 0.7));
--color-kbd17-rule: light-dark(#1a103014, #ffffff1a);
--color-kbd17-rule: light-dark(oklch(0.206 0.061 294.9 / 0.08), oklch(1 0 0 / 0.1));
--color-kbd17-ink: light-dark(#1d1530, #f3f0fb);
--color-kbd17-ink: light-dark(oklch(0.221 0.052 295.5), oklch(0.961 0.015 298.6));
--color-kbd17-mut: light-dark(#4e4565, #bdb6cf);
--color-kbd17-mut: light-dark(oklch(0.413 0.054 296.9), oklch(0.79 0.036 298.4));
--color-kbd17-acc: light-dark(#7c3aed, #c4a6ff);
--color-kbd17-acc: light-dark(oklch(0.541 0.247 293), oklch(0.784 0.127 298.9));
--font-kbd17-sans: 'Sora', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as utilities so the stage is sized before the browser build compiles. */
.kbd-17 {
width: 100%;
min-height: 100svh;
position: relative;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@400..700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@400..700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The CSS original's
@supports (backdrop-filter: blur(1px)) { … }block becamesupports-[backdrop-filter:blur(1px)]:on each utility it gates — the fallback and the enhancement sit side by side in one class list. - Alpha colours are 8-digit hex / oklch-with-alpha tokens, so
bg-kbd17-glassneeds no opacity modifier. - UI upgrade: keys now blur too (glass on glass) with a specular top edge, so they read as raised panes instead of flat stickers.
- UI upgrade: arrow and modifier glyphs gained
sr-onlynames, and muted copy rose to 6.8:1 against the frosted panel.
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: Glassmorphism Keyboard Keys in Tailwind CSS
Source: https://codefronts.com/snippets/tailwind-css-kbd-keys/glassmorphism-keyboard-keys-tailwind-css/
A frosted media-player shortcut panel over a colour field: the panel and every key blur what sits behind them. A solid, readable fill is declared first; supports-[backdrop-filter:blur(1px)]: swaps in the translucent fill and backdrop-blur-2xl only where blur actually works — so text never lands on an unblurred, busy background.
## HTML
```html
<section class="kbd-17 relative w-full min-h-svh scheme-light kbd17-dark:scheme-dark bg-kbd17-bg bg-[radial-gradient(38%_48%_at_18%_22%,var(--color-kbd17-b1),transparent_70%),radial-gradient(42%_52%_at_84%_28%,var(--color-kbd17-b2),transparent_70%),radial-gradient(55%_50%_at_50%_95%,var(--color-kbd17-b3),transparent_72%)] text-kbd17-ink font-kbd17-sans" aria-label="Glassmorphic translucent keycap demo">
<div class="grid min-h-svh place-items-center px-5 pt-20 pb-12">
<div class="w-full min-w-0 max-w-[26rem] rounded-3xl border border-kbd17-edge bg-kbd17-panel p-6 shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_30px_60px_-30px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-glass supports-[backdrop-filter:blur(1px)]:backdrop-blur-2xl supports-[backdrop-filter:blur(1px)]:backdrop-saturate-150 sm:p-7">
<p class="mb-2 text-[11px] font-semibold uppercase tracking-[0.22em] text-kbd17-mut">Now playing · shortcuts</p>
<div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Play or pause</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span class="px-5">Space</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Next track</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⌘</span><span class="sr-only">Command</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">→</span><span class="sr-only">Right arrow</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Volume up</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⌥</span><span class="sr-only">Option</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">↑</span><span class="sr-only">Up arrow</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Shuffle queue</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⇧</span><span class="sr-only">Shift</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md">S</kbd></kbd></div>
</div>
<p class="mt-3 text-[12px] text-kbd17-mut">Solid fill declared first · blur added behind <code class="font-mono">@supports</code></p>
</div>
</div>
<div class="absolute top-3.5 right-4 z-10">
<input id="kbd-17-theme" type="checkbox" class="peer sr-only">
<label for="kbd-17-theme" class="inline-flex min-h-11 cursor-pointer select-none items-center gap-2.5 rounded-full border border-current/55 px-4 font-sans text-[11px] font-bold uppercase leading-none tracking-[0.16em] text-kbd17-ink transition-colors hover:border-current peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-kbd17-acc">
<span aria-hidden="true" class="size-3 flex-none rounded-full bg-current transition-[background-color,box-shadow] duration-300 kbd17-dark:bg-transparent kbd17-dark:shadow-[inset_-4px_-2px_0_0_currentColor] motion-reduce:transition-none"></span>
<span class="kbd17-dark:hidden">Light</span><span class="hidden kbd17-dark:inline">Dark</span><span class="sr-only"> theme</span>
</label>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
/* Theme state: follows the OS; the corner switch flips it for THIS demo only. */
@custom-variant kbd17-dark {
@media (prefers-color-scheme: dark) {
&:where(.kbd-17:not(:has(#kbd-17-theme:checked)), .kbd-17:not(:has(#kbd-17-theme:checked)) *) {
@slot;
}
}
@media (prefers-color-scheme: light) {
&:where(.kbd-17:has(#kbd-17-theme:checked), .kbd-17:has(#kbd-17-theme:checked) *) {
@slot;
}
}
}
/* Every colour is light-dark(day, night): the root's scheme-light / scheme-dark utility picks the side. */
@theme {
--color-kbd17-bg: light-dark(#f3eefb, #0b0a14);
--color-kbd17-bg: light-dark(oklch(0.957 0.018 303.4), oklch(0.152 0.021 288.2));
--color-kbd17-b1: light-dark(#ff8fb1, #7a1d4d);
--color-kbd17-b1: light-dark(oklch(0.779 0.139 1.4), oklch(0.399 0.135 353.5));
--color-kbd17-b2: light-dark(#7cc4ff, #11407a);
--color-kbd17-b2: light-dark(oklch(0.796 0.111 244.6), oklch(0.375 0.111 256.1));
--color-kbd17-b3: light-dark(#ffd27a, #5a3a0c);
--color-kbd17-b3: light-dark(oklch(0.885 0.118 82.9), oklch(0.378 0.074 70.8));
--color-kbd17-panel: light-dark(#fbf9ff, #1a1826);
--color-kbd17-panel: light-dark(oklch(0.985 0.008 301.4), oklch(0.218 0.027 290.5));
--color-kbd17-glass: light-dark(#ffffff8c, #1c1a2b8c);
--color-kbd17-glass: light-dark(oklch(1 0 0 / 0.55), oklch(0.229 0.033 288.9 / 0.55));
--color-kbd17-keyfill: light-dark(#ffffff, #2a2840);
--color-kbd17-keyfill: light-dark(oklch(1 0 0), oklch(0.291 0.043 287.2));
--color-kbd17-keyglass: light-dark(#ffffffb3, #ffffff1f);
--color-kbd17-keyglass: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.12));
--color-kbd17-edge: light-dark(#ffffffb3, #ffffff26);
--color-kbd17-edge: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.15));
--color-kbd17-shine: light-dark(#ffffffe6, #ffffff33);
--color-kbd17-shine: light-dark(oklch(1 0 0 / 0.9), oklch(1 0 0 / 0.2));
--color-kbd17-shade: light-dark(#3b1d5c40, #000000b3);
--color-kbd17-shade: light-dark(oklch(0.308 0.109 302.3 / 0.25), oklch(0 0 0 / 0.7));
--color-kbd17-rule: light-dark(#1a103014, #ffffff1a);
--color-kbd17-rule: light-dark(oklch(0.206 0.061 294.9 / 0.08), oklch(1 0 0 / 0.1));
--color-kbd17-ink: light-dark(#1d1530, #f3f0fb);
--color-kbd17-ink: light-dark(oklch(0.221 0.052 295.5), oklch(0.961 0.015 298.6));
--color-kbd17-mut: light-dark(#4e4565, #bdb6cf);
--color-kbd17-mut: light-dark(oklch(0.413 0.054 296.9), oklch(0.79 0.036 298.4));
--color-kbd17-acc: light-dark(#7c3aed, #c4a6ff);
--color-kbd17-acc: light-dark(oklch(0.541 0.247 293), oklch(0.784 0.127 298.9));
--font-kbd17-sans: 'Sora', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as utilities so the stage is sized before the browser build compiles. */
.kbd-17 {
width: 100%;
min-height: 100svh;
position: relative;
}
```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: Glassmorphism Keyboard Keys in Tailwind CSS
Source: https://codefronts.com/snippets/tailwind-css-kbd-keys/glassmorphism-keyboard-keys-tailwind-css/
A frosted media-player shortcut panel over a colour field: the panel and every key blur what sits behind them. A solid, readable fill is declared first; supports-[backdrop-filter:blur(1px)]: swaps in the translucent fill and backdrop-blur-2xl only where blur actually works — so text never lands on an unblurred, busy background.
## HTML
```html
<section class="kbd-17 relative w-full min-h-svh scheme-light kbd17-dark:scheme-dark bg-kbd17-bg bg-[radial-gradient(38%_48%_at_18%_22%,var(--color-kbd17-b1),transparent_70%),radial-gradient(42%_52%_at_84%_28%,var(--color-kbd17-b2),transparent_70%),radial-gradient(55%_50%_at_50%_95%,var(--color-kbd17-b3),transparent_72%)] text-kbd17-ink font-kbd17-sans" aria-label="Glassmorphic translucent keycap demo">
<div class="grid min-h-svh place-items-center px-5 pt-20 pb-12">
<div class="w-full min-w-0 max-w-[26rem] rounded-3xl border border-kbd17-edge bg-kbd17-panel p-6 shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_30px_60px_-30px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-glass supports-[backdrop-filter:blur(1px)]:backdrop-blur-2xl supports-[backdrop-filter:blur(1px)]:backdrop-saturate-150 sm:p-7">
<p class="mb-2 text-[11px] font-semibold uppercase tracking-[0.22em] text-kbd17-mut">Now playing · shortcuts</p>
<div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Play or pause</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span class="px-5">Space</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Next track</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⌘</span><span class="sr-only">Command</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">→</span><span class="sr-only">Right arrow</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Volume up</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⌥</span><span class="sr-only">Option</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">↑</span><span class="sr-only">Up arrow</span></kbd></kbd></div>
<div class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-b border-kbd17-rule py-3 last:border-0"><span class="min-w-0 text-[14.5px]">Shuffle queue</span><kbd class="inline-flex items-center gap-1.5"><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md"><span aria-hidden="true">⇧</span><span class="sr-only">Shift</span></kbd><span class="text-[11px] text-kbd17-mut" aria-hidden="true">+</span><kbd class="inline-flex h-8 min-w-8 items-center justify-center rounded-lg border border-kbd17-edge bg-kbd17-keyfill px-2 text-[13px] font-semibold leading-none text-kbd17-ink shadow-[inset_0_1px_0_var(--color-kbd17-shine),0_4px_12px_-4px_var(--color-kbd17-shade)] supports-[backdrop-filter:blur(1px)]:bg-kbd17-keyglass supports-[backdrop-filter:blur(1px)]:backdrop-blur-md">S</kbd></kbd></div>
</div>
<p class="mt-3 text-[12px] text-kbd17-mut">Solid fill declared first · blur added behind <code class="font-mono">@supports</code></p>
</div>
</div>
<div class="absolute top-3.5 right-4 z-10">
<input id="kbd-17-theme" type="checkbox" class="peer sr-only">
<label for="kbd-17-theme" class="inline-flex min-h-11 cursor-pointer select-none items-center gap-2.5 rounded-full border border-current/55 px-4 font-sans text-[11px] font-bold uppercase leading-none tracking-[0.16em] text-kbd17-ink transition-colors hover:border-current peer-focus-visible:outline-3 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-kbd17-acc">
<span aria-hidden="true" class="size-3 flex-none rounded-full bg-current transition-[background-color,box-shadow] duration-300 kbd17-dark:bg-transparent kbd17-dark:shadow-[inset_-4px_-2px_0_0_currentColor] motion-reduce:transition-none"></span>
<span class="kbd17-dark:hidden">Light</span><span class="hidden kbd17-dark:inline">Dark</span><span class="sr-only"> theme</span>
</label>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
/* Theme state: follows the OS; the corner switch flips it for THIS demo only. */
@custom-variant kbd17-dark {
@media (prefers-color-scheme: dark) {
&:where(.kbd-17:not(:has(#kbd-17-theme:checked)), .kbd-17:not(:has(#kbd-17-theme:checked)) *) {
@slot;
}
}
@media (prefers-color-scheme: light) {
&:where(.kbd-17:has(#kbd-17-theme:checked), .kbd-17:has(#kbd-17-theme:checked) *) {
@slot;
}
}
}
/* Every colour is light-dark(day, night): the root's scheme-light / scheme-dark utility picks the side. */
@theme {
--color-kbd17-bg: light-dark(#f3eefb, #0b0a14);
--color-kbd17-bg: light-dark(oklch(0.957 0.018 303.4), oklch(0.152 0.021 288.2));
--color-kbd17-b1: light-dark(#ff8fb1, #7a1d4d);
--color-kbd17-b1: light-dark(oklch(0.779 0.139 1.4), oklch(0.399 0.135 353.5));
--color-kbd17-b2: light-dark(#7cc4ff, #11407a);
--color-kbd17-b2: light-dark(oklch(0.796 0.111 244.6), oklch(0.375 0.111 256.1));
--color-kbd17-b3: light-dark(#ffd27a, #5a3a0c);
--color-kbd17-b3: light-dark(oklch(0.885 0.118 82.9), oklch(0.378 0.074 70.8));
--color-kbd17-panel: light-dark(#fbf9ff, #1a1826);
--color-kbd17-panel: light-dark(oklch(0.985 0.008 301.4), oklch(0.218 0.027 290.5));
--color-kbd17-glass: light-dark(#ffffff8c, #1c1a2b8c);
--color-kbd17-glass: light-dark(oklch(1 0 0 / 0.55), oklch(0.229 0.033 288.9 / 0.55));
--color-kbd17-keyfill: light-dark(#ffffff, #2a2840);
--color-kbd17-keyfill: light-dark(oklch(1 0 0), oklch(0.291 0.043 287.2));
--color-kbd17-keyglass: light-dark(#ffffffb3, #ffffff1f);
--color-kbd17-keyglass: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.12));
--color-kbd17-edge: light-dark(#ffffffb3, #ffffff26);
--color-kbd17-edge: light-dark(oklch(1 0 0 / 0.7), oklch(1 0 0 / 0.15));
--color-kbd17-shine: light-dark(#ffffffe6, #ffffff33);
--color-kbd17-shine: light-dark(oklch(1 0 0 / 0.9), oklch(1 0 0 / 0.2));
--color-kbd17-shade: light-dark(#3b1d5c40, #000000b3);
--color-kbd17-shade: light-dark(oklch(0.308 0.109 302.3 / 0.25), oklch(0 0 0 / 0.7));
--color-kbd17-rule: light-dark(#1a103014, #ffffff1a);
--color-kbd17-rule: light-dark(oklch(0.206 0.061 294.9 / 0.08), oklch(1 0 0 / 0.1));
--color-kbd17-ink: light-dark(#1d1530, #f3f0fb);
--color-kbd17-ink: light-dark(oklch(0.221 0.052 295.5), oklch(0.961 0.015 298.6));
--color-kbd17-mut: light-dark(#4e4565, #bdb6cf);
--color-kbd17-mut: light-dark(oklch(0.413 0.054 296.9), oklch(0.79 0.036 298.4));
--color-kbd17-acc: light-dark(#7c3aed, #c4a6ff);
--color-kbd17-acc: light-dark(oklch(0.541 0.247 293), oklch(0.784 0.127 298.9));
--font-kbd17-sans: 'Sora', system-ui, sans-serif;
}
/* Root rule: the full-bleed contract, stated in CSS as well as utilities so the stage is sized before the browser build compiles. */
.kbd-17 {
width: 100%;
min-height: 100svh;
position: relative;
}
```How this works
Solid first, glass second. Translucent fills without blur put text straight onto the gradient, which fails contrast. The fallback is the default; the glass is the enhancement:
bg-kbd17-panel
supports-[backdrop-filter:blur(1px)]:bg-kbd17-glass
supports-[backdrop-filter:blur(1px)]:backdrop-blur-2xlKeys are glass on glass. Each cap blurs again with backdrop-blur-md and a brighter fill, so it reads as a raised pane rather than a hole.
Make it yours
- Clearer glass:
backdrop-blur-lgand a lower-opacityglasstoken. - Different mood: change the three blob tokens
b1–b3. - Inline in an app: drop the colour field; glass needs something behind it to blur.
Gotchas — read before shipping
backdrop-filtercreates a stacking context and is GPU-costly — avoid on long scrolling lists.- Nested backdrop filters can render as plain blur-of-blur in Safari; keep key blur light.
- Measure contrast against the blurred background at its brightest point.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 123+ | 17.5+ | 128+ | 123+ |
backdrop-filter is supported in Chrome 76 / Safari 9 (prefixed) / Firefox 103; the supports-[…] fallback covers the rest. Tailwind v4 + light-dark() set the floor.