EmpireUI
Get Pro
← Blog7 min read#glassmorphism#kanban-board#react

Glassmorphism Kanban Board: Project Management UI

Build a glassmorphism kanban board with React and Tailwind. Frosted-glass cards, drag-and-drop columns, and real CSS backdrop-filter code you can ship today.

Frosted glass kanban board with translucent columns on a gradient background

Why Glassmorphism Works for Kanban UIs

Honestly, frosted glass is one of the few visual trends that actually makes functional sense in a kanban layout. Most design trends look great in Dribbble mockups and fall apart the moment you add real content. Glassmorphism doesn't — and kanban is exactly the context where it earns its keep.

The trick is layering. A kanban board already has inherent depth: a background, column containers, card items, and modal overlays. Glassmorphism maps directly to that hierarchy. Each layer gets progressively less transparent, so your eye naturally reads the depth without explicit shadows doing all the heavy lifting.

If you haven't already read what is glassmorphism, it's worth a quick stop. The short version: backdrop-filter: blur() plus a semi-transparent background plus a subtle border. That's the whole trick. The kanban context just gives you a natural reason to stack three or four of those layers on top of each other.

Contrast is the real challenge here. Cards need to be readable. Blur without enough contrast kills legibility on lower-end monitors. We'll address that directly in the implementation sections below.

Structuring the Kanban Board with React Components

Keep the component tree flat where you can. A <Board> component that renders a row of <Column> components, each containing a list of <Card> components. Three levels. Don't over-engineer it before you have drag-and-drop working.

For state, a simple object keyed by column id — { todo: Card[], inProgress: Card[], done: Card[] } — is enough to get started. You can always migrate to a reducer or Zustand later. Premature architecture is the enemy of shipping.

Each <Column> receives its cards array, a title, and an onDrop handler. Each <Card> gets an onDragStart. That's the entire prop surface you need for a functional MVP. Everything else — labels, avatars, due dates — comes after the layout is right.

One thing worth noting: don't mix drag-and-drop state into your visual glassmorphism styling logic. Keep a separate isDragOver boolean per column and apply a conditional class. It's cleaner and easier to debug when the drop zones light up wrong.

The Core Glassmorphism CSS for Columns and Cards

Here's the actual CSS that drives the effect. You need a vivid background behind everything — a gradient, an image, or even an animated particles background — otherwise the blur has nothing to refract and the cards just look grey.

For the column containers, rgba(255,255,255,0.12) background with backdrop-filter: blur(16px) gives you a strong frosted effect without making the content unreadable. Cards inside the column use rgba(255,255,255,0.20) — slightly more opaque — so they visually pop off the column surface.

/* Column container */
.glass-column {
  background: rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 16px;
  padding: 16px;
  gap: 8px;
  display: flex;
  flex-direction: column;
}

/* Individual card */
.glass-card {
  background: rgba(255, 255, 255, 0.20);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.30);
  border-radius: 10px;
  padding: 14px 16px;
  cursor: grab;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.glass-card:active {
  cursor: grabbing;
  transform: scale(1.02) rotate(1deg);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
}

The -webkit-backdrop-filter prefix is still necessary for Safari as of mid-2026. Don't skip it. Chrome handles it without the prefix, but Safari usage in SaaS products is often 25-35% of your traffic. That's not a number you can ignore.

Tailwind v4 Implementation for the Board Layout

With Tailwind v4.0.2 you can express most of the glassmorphism utilities inline without a single custom CSS class. The backdrop-blur-* scale goes up to backdrop-blur-3xl (64px), but for kanban columns backdrop-blur-xl (24px) is about as far as you want to push it before text contrast suffers.

// Board.tsx
export function KanbanBoard() {
  return (
    <div
      className="min-h-screen bg-gradient-to-br from-violet-700 via-purple-600 to-indigo-800 p-8"
    >
      <div className="flex gap-6 overflow-x-auto pb-4">
        {columns.map((col) => (
          <KanbanColumn key={col.id} column={col} />
        ))}
      </div>
    </div>
  );
}

// KanbanColumn.tsx
export function KanbanColumn({ column }: { column: Column }) {
  return (
    <div
      className="
        flex-shrink-0 w-72
        bg-white/10 backdrop-blur-xl
        border border-white/20
        rounded-2xl p-4
        flex flex-col gap-2
      "
    >
      <h3 className="text-white font-semibold text-sm uppercase tracking-wider mb-2">
        {column.title}
      </h3>
      {column.cards.map((card) => (
        <KanbanCard key={card.id} card={card} />
      ))}
    </div>
  );
}

// KanbanCard.tsx
export function KanbanCard({ card }: { card: Card }) {
  return (
    <div
      draggable
      className="
        bg-white/20 backdrop-blur-sm
        border border-white/30
        rounded-xl p-3
        text-white text-sm
        cursor-grab active:cursor-grabbing
        hover:bg-white/25
        transition-colors duration-150
      "
    >
      <p className="font-medium">{card.title}</p>
      {card.label && (
        <span className="mt-2 inline-block text-xs bg-white/20 rounded-full px-2 py-0.5">
          {card.label}
        </span>
      )}
    </div>
  );
}

Notice the gap-2 on the column flex container — that's an 8px gap between cards. It's a small number but it's intentional. Tighter spacing makes the column feel like a cohesive unit rather than a loose stack of items.

If you're deciding between Tailwind and plain CSS modules for a project like this, the Tailwind vs CSS Modules breakdown is genuinely useful. For a component with this much repetitive utility work, Tailwind wins on speed.

Drag and Drop Without a Heavy Library

The HTML5 drag-and-drop API is underrated. For a kanban board with a few columns and a few dozen cards, you don't need react-beautiful-dnd or dnd-kit. Those are great libraries, but they add weight and complexity. The native API works fine until you need touch support or animated reordering.

The pattern is simple. Store draggingCardId and draggingFromColumn in state. On dragStart set both. On dragOver call preventDefault() so the browser registers a valid drop target — this is the step most tutorials miss. On drop, remove the card from its source column and append it to the target.

Where does glassmorphism come in? Use the isDragOver state on each column to increase the background opacity from bg-white/10 to bg-white/20 and add a ring-2 ring-white/40. That's your visual drop zone feedback. It feels polished and it's five characters of Tailwind.

What about mobile? Honestly, the native HTML5 API doesn't fire on touch devices. If your users need mobile kanban interaction — and they might, for a SaaS product — you'll want to reach for dnd-kit or a pointer events-based approach. Don't fake it with touchmove listeners unless you enjoy pain.

Dark Background Gradients That Actually Pop

The glassmorphism effect only reads clearly against a colorful, high-saturation background. A flat white or light grey background makes backdrop-filter: blur() invisible. You need something the blur can actually diffuse.

For project management tools, deep purples and indigos work well — they feel professional without looking like a gaming peripheral. Try from-slate-900 via-purple-900 to-indigo-900 in Tailwind for a dark SaaS aesthetic. Or go bolder: from-rose-500 via-fuchsia-600 to-violet-700 for a product aimed at creatives.

One pattern that works well is a slow-animated gradient as the board background. A 10-second CSS @keyframes animation that subtly shifts hue gives the frosted glass something dynamic to react to. It's not essential, but it elevates the experience from "okay glass effect" to "wait, this looks incredible." The glassmorphism vs neumorphism breakdown has more on why background choice matters so much for each style.

Also consider the time-of-day use case. Project management tools get used all day. A theme toggle that shifts between a light-background glass effect and a dark-background one is worth the 30 minutes of implementation time.

Accessibility and Contrast in Glass Card UIs

Here's where a lot of glassmorphism implementations fall apart. The semi-transparent backgrounds and blurred content behind card text can tank your contrast ratio below WCAG AA standards. That's 4.5:1 for normal text. You can't hand-wave this away.

The fix isn't complicated. Add a text-shadow to headings: text-shadow: 0 1px 3px rgba(0,0,0,0.4). Use font-semibold or font-bold for card titles — heavier weight reads better through a blurred background. And always test your contrast against the darkest portion of your background gradient, not the average.

Screen readers don't care about your backdrop filter at all, which is actually good news — your semantic HTML just needs to be correct. Columns should be <section> or <ul> elements with proper aria-label attributes. Cards are <li> items. Add role="button" and tabIndex={0} to draggable cards so keyboard users can interact.

Don't forget focus styles. The default browser focus ring disappears against a glass surface. Add an explicit focus-visible:ring-2 focus-visible:ring-white to every interactive card. It's one line and it keeps you out of accessibility trouble.

Shipping It: Performance Considerations for backdrop-filter

backdrop-filter triggers compositing on the GPU. That's generally fine, but if you have 50+ cards all with backdrop-blur-xl applied simultaneously, you might notice frame rate issues on integrated graphics — especially during drag animations when transform and backdrop-filter are both active.

The practical fix: only apply backdrop-filter to the column containers, not individual cards. Cards can use a slightly opaque solid-ish color that mimics glass without the compositing cost. On a 72-card board this can make the difference between 60fps and 45fps during drag.

Also worth knowing: backdrop-filter doesn't work if the element has overflow: hidden set on any ancestor in some browser versions. If your columns clip overflow for scrolling, you may need to restructure slightly. Test in Chrome, Firefox, and Safari before you ship. Browser support is good in 2026 but there are still edge cases in older Safari versions on iOS.

For Empire UI's best free glassmorphism components, performance was a real constraint during development. The solution was progressive enhancement — basic styling without blur for low-end devices detected via window.matchMedia('(prefers-reduced-motion: reduce)') combined with a quick GPU tier check. Not perfect, but it keeps the experience usable for everyone.

FAQ

Does backdrop-filter blur work in all browsers for a kanban board?

Yes, with caveats. Chrome, Edge, and Firefox support it without a prefix. Safari requires -webkit-backdrop-filter. Internet Explorer doesn't support it at all, but that's 2026 — if your analytics show IE traffic, you have bigger problems. Always include both the prefixed and unprefixed declarations.

What blur radius should I use for kanban columns vs cards?

A good starting point: 16px blur on column containers and 8px on individual cards. This creates a depth hierarchy where columns feel like physical surfaces and cards sit above them. Going higher than 24px on cards usually hurts text legibility more than it helps the aesthetic.

Can I combine glassmorphism with dark mode on a kanban board?

Absolutely. In dark mode, swap your background gradient to something like from-slate-900 to-indigo-950, and adjust card backgrounds to rgba(255,255,255,0.08) instead of 0.20. The border should stay around rgba(255,255,255,0.15). Text goes white or near-white. The effect reads just as well on dark backgrounds — sometimes better.

Should I use dnd-kit or the native HTML5 drag API for a glass kanban?

Native HTML5 API is fine for desktop-only boards with modest card counts. If you need touch support, animated reorder previews, or accessibility beyond basic keyboard nav, dnd-kit is worth the dependency. It's about 12KB gzipped. react-beautiful-dnd is no longer actively maintained as of late 2025, so avoid it for new projects.

How do I prevent glass card text from being unreadable over the blurred background?

Three things: use font-semibold or font-bold for card titles, add a subtle text-shadow (0 1px 3px rgba(0,0,0,0.3) works well), and increase card background opacity until contrast passes WCAG AA. Run your colors through a contrast checker with the actual background value, not a theoretical one.

Why does my backdrop-filter look grey and flat instead of frosted glass?

Your background isn't colorful enough. backdrop-filter: blur() diffuses whatever is behind the element. If that's a light grey or white surface, you just get a slightly lighter grey. You need a vibrant gradient or image behind the board for the frosted effect to read properly. Switch to a saturated purple, blue, or gradient and the effect appears immediately.

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

Read next

Glassmorphism Onboarding Screens: Welcome Flow with BlurGlassmorphism Analytics Chart: Data Viz with Blur BackgroundsGlassmorphism vs Solid Design: Which Converts Better in 2027Drag-and-Drop Sortable Lists in React: No Library Required