# Dark Glass UI

> Build a dark-themed glassmorphism UI with Tailwind CSS v4 design tokens, frosted glass cards, unified button interactions, ambient animations, and accessibility baselines. Use when the user wants a dark theme, glass-effect UI, frosted panels, neon accents, or cinematic web design.

- Skill: `ph13917403910/dark-glass-ui` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ph13917403910/dark-glass-ui`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ph13917403910/dark-glass-ui/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: PH13917403910 (https://skillmd.com/u/ph13917403910)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/ph13917403910/dark-glass-ui

---


# Dark Glassmorphism UI System

## Design tokens (@theme)

Define all colors, fonts, and spacing in `globals.css` using Tailwind v4 `@theme`:

```css
@import "tailwindcss";

@theme {
  /* Navy scale — darkest to lightest */
  --color-navy-950: #060d1b;
  --color-navy-900: #0a1628;
  --color-navy-800: #0f1d32;
  --color-navy-700: #162744;
  --color-navy-600: #1e3358;

  /* Accent (warm orange) */
  --color-accent: #f97316;
  --color-accent-light: #fb923c;

  /* Cyber (cool teal) */
  --color-cyber: #06b6d4;
  --color-cyber-light: #22d3ee;

  /* Typography */
  --font-sans: var(--font-inter, "Inter"), ui-sans-serif, system-ui, sans-serif;
  --font-display: var(--font-space-grotesk, "Space Grotesk"), ui-sans-serif, system-ui, sans-serif;
}
```

Body background: `bg-navy-950`. Primary text: `text-white` or `text-gray-200`. Secondary text: `text-gray-400`.

## Card glass

The signature component — frosted translucent panels:

```css
.card-glass {
  background: rgba(15, 29, 50, 0.55);
  backdrop-filter: blur(20px) saturate(1.3);
  -webkit-backdrop-filter: blur(20px) saturate(1.3);
  border: 1px solid rgba(255, 255, 255, 0.06);
  box-shadow:
    inset 0 1px 0 0 rgba(255, 255, 255, 0.04),
    0 4px 24px rgba(0, 0, 0, 0.25),
    0 1px 2px rgba(0, 0, 0, 0.15);
  position: relative;
}

.card-glass::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: url("data:image/svg+xml,...") repeat; /* subtle noise texture */
  opacity: 0.03;
  pointer-events: none;
}

.card-glass:hover {
  border-color: rgba(249, 115, 22, 0.15);
  box-shadow:
    inset 0 1px 0 0 rgba(255, 255, 255, 0.06),
    0 4px 32px rgba(0, 0, 0, 0.3),
    0 0 0 1px rgba(249, 115, 22, 0.08);
}
```

Usage: `<div className="card-glass rounded-2xl p-6">...</div>`

## Button system

### Global baseline (in globals.css)

```css
@layer base {
  button, [role="button"] {
    transition-property: transform, opacity, filter, box-shadow,
                         background-color, border-color, color;
    transition-duration: 0.15s;
    transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
    cursor: pointer;
  }
  button:disabled, [role="button"][aria-disabled="true"] {
    cursor: not-allowed;
  }
}

button:active:not(:disabled),
[role="button"]:active:not(:disabled) {
  transform: scale(0.975);
}

button:focus-visible,
[role="button"]:focus-visible {
  outline: 2px solid rgba(249, 115, 22, 0.5);
  outline-offset: 2px;
}
```

This eliminates the need for per-button `transition`, `active:scale-*`, and `focus:outline-*` classes.

### Primary CTA button

```html
<button className="btn-shimmer rounded-xl bg-gradient-to-r from-accent to-amber-500
  px-8 py-3 font-bold text-white shadow-xl shadow-accent/20
  hover:shadow-accent/40 hover:scale-[1.02] disabled:opacity-35">
  Action
</button>
```

### Shimmer effect

```css
.btn-shimmer {
  position: relative;
  overflow: hidden;
}
.btn-shimmer::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    105deg,
    transparent 40%,
    rgba(255, 255, 255, 0.15) 45%,
    rgba(255, 255, 255, 0.15) 55%,
    transparent 60%
  );
  animation: shimmer 2.5s ease-in-out infinite;
}
@keyframes shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}
```

### Secondary / Ghost button

```html
<button className="rounded-xl border border-white/10 bg-white/5 px-6 py-2.5
  text-sm text-gray-300 hover:bg-white/10 hover:text-white
  disabled:opacity-35">
  Secondary
</button>
```

## Ambient background

Two-layer approach for cinematic depth without harming readability:

1. **Canvas starfield** — static stars with subtle twinkling and mouse parallax
2. **CSS orbs** — soft radial-gradient blobs with slow CSS animation

```tsx
// Starfield: <canvas> with requestAnimationFrame
// Orbs: absolute-positioned divs with radial-gradient + CSS animation
// Both layers sit behind content with pointer-events: none
```

Keep orb colors dim (opacity 0.08–0.15) and blur heavy (`blur(80px)+`) to avoid UI interference.

## Noise overlay

Adds film grain texture across the entire page:

```css
.noise {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  opacity: 0.015;
  background: url("data:image/svg+xml,...") repeat;
  background-size: 200px;
}
```

## Accessibility baseline

### Reduced motion

```css
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
```

### Required ARIA patterns

- Progress indicators: `role="progressbar"` + `aria-valuenow/min/max`
- Interactive non-button elements: `role="button"` + `tabindex="0"` + keyboard handler
- Modals: `role="dialog"` + `aria-modal="true"` + focus trap

### Color contrast

- Body text on navy-950: use `text-gray-200` minimum (ratio > 7:1)
- Secondary text: `text-gray-400` (ratio > 4.5:1)
- Never rely solely on color to convey information

## Checklist

- [ ] `@theme` tokens defined — never use raw hex in components
- [ ] `.card-glass` with backdrop-filter, noise pseudo-element, hover state
- [ ] Global button baseline in `@layer base` (transition, active, focus-visible)
- [ ] `.btn-shimmer` for primary CTAs
- [ ] Noise overlay at `opacity: 0.015`, `pointer-events: none`
- [ ] `prefers-reduced-motion` media query in globals.css
- [ ] All interactive elements keyboard-accessible with visible focus

