EmpireUI
Get Pro
← Blog8 min read#glassmorphism#ui-components#tailwind-css

Glassmorphism Complete Component Kit: Every UI Element

Every glassmorphism UI component you actually need — cards, modals, navbars, forms — built with Tailwind v4 and real CSS values. No fluff, just the kit.

Frosted glass UI panels layered over a gradient background showing glassmorphism card components

Why Glassmorphism Still Works in 2026

Honestly, glassmorphism never really went away — it just got used badly. Blurry cards slapped over flat backgrounds with no depth logic. That's not the style's fault. When it's done right, frosted glass creates genuine visual hierarchy without shouting.

The trick is that backdrop-filter: blur() pulls context from whatever's behind the element. That makes your UI feel grounded in its environment instead of floating disconnected. It's why glassmorphism works so well over gradients, photos, or a particles background.

This kit covers every component type you'll actually ship: cards, modals, navigation bars, form inputs, badges, tooltips, buttons, and sidebar panels. All values are production-tested. No placeholder examples that fall apart when real content hits them.

The Core CSS Foundation: Blur, Alpha, and Border

Every glassmorphism component shares three properties. Get these wrong and the whole thing falls apart. You need backdrop-filter: blur(), a semi-transparent background using rgba() or oklch() with an alpha channel, and a subtle border that catches light.

For the blur radius, 12px to 20px is your working range. Below 8px it looks like a mistake. Above 24px and text becomes hard to read against complex backgrounds. The sweet spot for most cards is backdrop-filter: blur(16px) saturate(180%). The saturate boost is easy to overlook but it makes colours in the blurred content pop instead of going muddy.

/* Base glassmorphism token set */
:root {
  --glass-bg: rgba(255, 255, 255, 0.12);
  --glass-bg-hover: rgba(255, 255, 255, 0.18);
  --glass-border: rgba(255, 255, 255, 0.25);
  --glass-blur: blur(16px) saturate(180%);
  --glass-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
  --glass-radius: 16px;
}

.glass-surface {
  background: var(--glass-bg);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--glass-radius);
  box-shadow: var(--glass-shadow);
}

Dark mode requires a different alpha value. rgba(255,255,255,0.12) is correct for light-over-dark scenarios. For dark glass over lighter backgrounds, flip to rgba(0,0,0,0.25). If you're building a theme toggle in React, you'll want both token sets defined and swap them via a data attribute on <html>.

Glassmorphism Card Component

The card is the most-used element in any kit. It also has the most failure modes. Content overflow, missing fallbacks for browsers that don't support backdrop-filter, and forgetting that the blur only works if there's actually something behind the card.

Here's a production-ready card in TSX using Tailwind v4.0.2. Notice the explicit will-change: transform — that hint pushes the blur compositing to the GPU and kills the jank you'd otherwise see on scroll.

interface GlassCardProps {
  children: React.ReactNode;
  className?: string;
  hover?: boolean;
}

export function GlassCard({ children, className = '', hover = false }: GlassCardProps) {
  return (
    <div
      className={[
        'rounded-2xl border border-white/25 bg-white/10',
        'backdrop-blur-[16px] [backdrop-filter:blur(16px)_saturate(180%)]',
        'shadow-[0_8px_32px_rgba(0,0,0,0.18)]',
        'p-6 will-change-transform',
        hover && 'transition-colors duration-200 hover:bg-white/18 hover:border-white/35',
        className,
      ]
        .filter(Boolean)
        .join(' ')}
    >
      {children}
    </div>
  );
}

The filter(Boolean) pattern keeps conditional classes clean. You'll use this pattern across every component in the kit — don't fight it with string interpolation.

Navigation Bar with Glass Effect

A sticky glass navbar is one of the trickier pieces to get right. The blur needs to work against constantly-changing page content as you scroll. Too much transparency and the nav becomes unreadable. Too little and it kills the glass effect entirely.

The right approach is to dynamically increase the background alpha on scroll using a scroll listener or an Intersection Observer. At rest: rgba(255,255,255,0.08). Once the user scrolls past 80px: rgba(255,255,255,0.18). That 10-point alpha jump is enough to improve readability without a jarring transition.

'use client';
import { useEffect, useState } from 'react';

export function GlassNavbar({ children }: { children: React.ReactNode }) {
  const [scrolled, setScrolled] = useState(false);

  useEffect(() => {
    const handler = () => setScrolled(window.scrollY > 80);
    window.addEventListener('scroll', handler, { passive: true });
    return () => window.removeEventListener('scroll', handler);
  }, []);

  return (
    <nav
      className={[
        'fixed inset-x-0 top-0 z-50 h-16 px-6',
        'flex items-center justify-between gap-8',
        'border-b border-white/20',
        'backdrop-blur-[20px] [backdrop-filter:blur(20px)_saturate(160%)]',
        'transition-[background-color] duration-300',
        scrolled ? 'bg-white/18' : 'bg-white/8',
      ].join(' ')}
    >
      {children}
    </nav>
  );
}

Set padding-top: 4rem on your page wrapper to avoid content hiding under the fixed bar. 64px matches the h-16 class exactly. That's 16 * 4 = 64px in the default Tailwind scale.

Modal Dialog, Form Inputs, and Overlay Stack

Modals are where glassmorphism earns its keep. A glass panel over a blurred page overlay looks genuinely premium. The key detail most people miss: the page overlay behind the modal should use backdrop-filter: blur(4px) at a very low value — just enough to push the modal forward visually without making the page content disappear.

Form inputs inside a glass modal need their own treatment. The default white input background destroys the effect. Use rgba(255,255,255,0.08) for input backgrounds, a 1px solid rgba(255,255,255,0.2) border, and bump the border to rgba(255,255,255,0.4) on focus. Add outline: none and handle the focus ring yourself — browser defaults look wrong against glass surfaces.

export function GlassInput({ label, ...props }: InputProps) {
  return (
    <div className="flex flex-col gap-1.5">
      <label className="text-sm font-medium text-white/80">{label}</label>
      <input
        {...props}
        className={[
          'rounded-xl px-4 py-3',
          'bg-white/8 border border-white/20',
          'text-white placeholder:text-white/40',
          'focus:outline-none focus:border-white/40 focus:bg-white/12',
          'transition-colors duration-150',
        ].join(' ')}
      />
    </div>
  );
}

Stack depth matters here. The page overlay sits at z-40, the modal container at z-50, and any tooltips or dropdowns inside the modal at z-60. Don't use arbitrary z-index values — stick to the 10-unit increments and document them in your design tokens.

Buttons, Badges, and Small Surface Components

Small components are easy to rush. Don't. A glass button that's 40px tall with 16px horizontal padding follows the same blur rules as the card — but you'll want backdrop-filter: blur(8px) rather than 16px, because buttons are small and heavy blur on a tiny surface just looks foggy.

For badges, skip the blur entirely in most cases. A 1px white/25 border with a rgba(255,255,255,0.12) fill reads as glass without the performance cost of blur compositing on dozens of small elements. Reserve backdrop-filter for surfaces larger than roughly 200×100px.

Buttons want a hover state that feels responsive. Transition background-color at 150ms and box-shadow at 200ms separately — the colour change should feel instant while the shadow elevation eases in. transition-[background-color,box-shadow] duration-[150ms,200ms] in Tailwind v4 syntax handles this cleanly. If you're curious how glassmorphism sits against other modern styles, glassmorphism vs neumorphism breaks down the tradeoffs in depth.

Performance, Fallbacks, and When to Skip the Blur

Here's the thing: backdrop-filter is not free. On mobile, compositing blurred layers chews through GPU budget fast. If you have more than 3-4 glass surfaces visible at once on a complex background, you'll start seeing paint drops on mid-range Android devices.

The fix isn't to abandon the style — it's to be strategic. Primary surfaces (the hero card, the modal) get the full blur(16px). Secondary surfaces (sidebar items, badges in a list) get reduced to blur(8px) or no blur at all with just the alpha background. Test on a real Pixel 7a, not just Chrome DevTools mobile simulation.

Always include a @supports fallback. Browsers that don't support backdrop-filter will render your rgba() background without the blur, which is usually acceptable — just make sure the alpha value is high enough to stay readable. rgba(255,255,255,0.65) is a safe floor for fallback readability. Also worth reading: if you're deciding between Tailwind vs CSS Modules for managing all these glass tokens, that article lays out the real-world tradeoffs.

What about Safari? It's fine. -webkit-backdrop-filter has been stable since Safari 15.4. Just always include both the prefixed and unprefixed declarations. The Empire UI kit handles this with a Tailwind plugin that auto-generates both — check the best free glassmorphism components roundup to see how our components compare to standalone libraries.

Putting the Full Kit Together in a Real Layout

A complete glassmorphism layout needs a background layer that actually gives the blur something to work with. A CSS gradient mesh is the simplest option. Two or three large radial gradients in position over a dark base colour — no image dependency, loads instantly, and gives your glass surfaces real depth.

Structure your component tree so glass surfaces are never nested inside other glass surfaces. Nested backdrop-filter elements create a compounding blur effect that's almost impossible to control. If you need a dropdown inside a glass card, render the dropdown in a portal at the root level and position it absolutely. It's a bit more wiring but the visual result is consistent.

With all seven component types from this kit — card, navbar, modal, input, button, badge, sidebar — you can build a complete SaaS dashboard UI without ever reaching for a third-party component library. The whole set adds about 2.8KB to your bundle in raw CSS (pre-gzip) since it's almost entirely composable utility classes with a handful of CSS custom properties. That's the kind of number worth knowing before you commit to a visual direction. If you want to understand the foundations before building out the full kit, what is glassmorphism covers the design theory behind why these values work.

FAQ

Does backdrop-filter work in all modern browsers?

Yes, for anything released in the last 3-4 years. Chrome 76+, Firefox 103+, Safari 15.4+ all support it. Always include both backdrop-filter and -webkit-backdrop-filter in your CSS, and add a @supports (backdrop-filter: blur(1px)) guard with a higher-opacity fallback background for older environments.

What blur radius should I use for glassmorphism components?

12px to 20px covers most use cases. Cards and modals work well at blur(16px). Navbars can go up to blur(20px). Small elements like buttons should be blur(8px) or no blur at all — heavy blur on tiny surfaces just looks foggy rather than glassy.

How do I make glassmorphism work in dark mode?

Swap your CSS custom properties at the html[data-theme='dark'] level. Light mode glass typically uses rgba(255,255,255,0.12) for the background. Dark mode glass uses rgba(15,15,25,0.45) — a dark tinted alpha rather than white. The border flips from rgba(255,255,255,0.25) to rgba(255,255,255,0.10) to stay subtle without disappearing.

Why does my glass card look flat with no blur effect?

The blur composites against what's behind the element in the DOM. If your glass card sits over a flat solid colour or another opaque element, there's nothing to blur — it'll just render as a semi-transparent rectangle. You need a textured, gradient, or image background behind glass surfaces for the effect to be visible.

Can I use glassmorphism with Tailwind CSS without custom plugins?

Partially. Tailwind v4 includes backdrop-blur-* utilities. You can write backdrop-blur-[16px] for arbitrary values. The saturate part of the filter requires [backdrop-filter:blur(16px)_saturate(180%)] as an arbitrary property since Tailwind doesn't compose multi-value backdrop-filters natively yet. It works, it's just verbose.

Does glassmorphism hurt performance on mobile?

It can. Each element with backdrop-filter creates a new compositor layer. Multiple blurred surfaces on a complex background hit GPU memory hard, especially on mid-range Android. Limit full-blur surfaces to 3-4 per viewport on mobile, and reduce blur radius to blur(8px) on smaller screens via a Tailwind responsive prefix like sm:backdrop-blur-[16px].

Free components in 40 styles
React & Tailwind, copy-paste ready.
Browse →

Read next

Glassmorphism Carousel: Slider Component with Frosted CardsGlassmorphism Bottom Sheet: Mobile-First Frosted PanelTailwind Avatar Component: Image, Initials, Group, StatusDrag-and-Drop Sortable Lists in React: No Library Required