Skip to content

Writing

2 min read

Frostpane: A Modern CSS Library for Frosted Glass Effects

Frostpane is my SCSS library for liquid-glass UI: backdrop-filter blur, custom-property theming, and effects that stay fast across browsers.

Frosted glass is everywhere in interface design right now: translucent panels, blurred backgrounds, and thin borders that give a layout some depth. Frostpane is my SCSS library for building those effects without fighting performance or browser support every time.

The Anatomy of Frosted Glass Effects

The effect comes from a handful of CSS properties stacked together:

.frost-panel {
  background: rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

Each property contributes to the effect: the semi-transparent background provides the base layer, backdrop-filter creates the blur on content behind the element, the subtle border adds definition, and the shadow creates depth.

SCSS Architecture for Flexibility

Frostpane combines CSS custom properties with SCSS mixins so the look stays adjustable:

:root {
  --frost-blur: 10px;
  --frost-saturation: 180%;
  --frost-opacity: 0.15;
  --frost-border-opacity: 0.2;
  --frost-radius: 16px;
}

@mixin frost-base($blur: var(--frost-blur)) {
  backdrop-filter: blur($blur) saturate(var(--frost-saturation));
  -webkit-backdrop-filter: blur($blur) saturate(var(--frost-saturation));
  background: rgba(255, 255, 255, var(--frost-opacity));
  border: 1px solid rgba(255, 255, 255, var(--frost-border-opacity));
  border-radius: var(--frost-radius);
}

The custom properties give you runtime theming with sensible defaults. You can override individual values in the browser without recompiling the stylesheet.

A side-by-side comparison showing how liquid glass effects adapt to light and dark color schemes.

Light and Dark Mode Variants

Liquid glass requires different treatments for light and dark backgrounds:

@mixin frost-light {
  @include frost-base;
  background: rgba(255, 255, 255, 0.25);
  border-color: rgba(255, 255, 255, 0.3);
}

@mixin frost-dark {
  @include frost-base;
  background: rgba(0, 0, 0, 0.25);
  border-color: rgba(255, 255, 255, 0.1);
}

@media (prefers-color-scheme: dark) {
  .frost-panel {
    @include frost-dark;
  }
}

The prefers-color-scheme query swaps variants automatically, so the panels match whichever theme the user is running.

Performance Considerations

Backdrop filters can impact rendering performance, particularly on lower-powered devices. Frostpane includes performance-conscious defaults:

@mixin frost-performant {
  @include frost-base;
  
  @media (prefers-reduced-motion: reduce) {
    backdrop-filter: none;
    background: rgba(255, 255, 255, 0.85);
  }
  
  // Fallback for unsupported browsers
  @supports not (backdrop-filter: blur(1px)) {
    background: rgba(255, 255, 255, 0.9);
  }
}

Browsers without backdrop-filter get a solid background, and anyone who has asked for reduced motion drops the blur entirely.

Animation Integration

A little animation sells the effect:

@mixin frost-animated {
  @include frost-base;
  transition: 
    backdrop-filter 0.3s ease,
    background 0.3s ease,
    transform 0.3s ease;
  
  &:hover {
    --frost-blur: 15px;
    --frost-opacity: 0.2;
    transform: translateY(-2px);
  }
}

On hover the blur and opacity ramp up and the panel lifts a couple of pixels, all transitioned rather than snapped.

Highlight Effects

Adding highlights creates the impression of light catching the glass surface:

@mixin frost-highlight {
  @include frost-base;
  position: relative;
  
  &::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(
      90deg,
      transparent,
      rgba(255, 255, 255, 0.4),
      transparent
    );
  }
}

This subtle gradient along the top edge suggests a light source above the element, adding to the three-dimensional illusion.

Browser Compatibility

backdrop-filter has broad support now, but it’s still worth handling the browsers that lack it:

.frost-panel {
  // Solid fallback for older browsers
  background: rgba(255, 255, 255, 0.9);
  
  @supports (backdrop-filter: blur(1px)) {
    background: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(10px);
  }
}

The feature query means older browsers get a solid panel instead of a transparent, unreadable one.

A practical application shot showing how the different components (nav, modal, card) look when composed together in a full UI.

Component Variations

Frostpane includes pre-built component styles for common use cases:

.frost-card {
  @include frost-base;
  padding: 1.5rem;
}

.frost-nav {
  @include frost-base;
  position: fixed;
  top: 0;
  width: 100%;
  z-index: 100;
}

.frost-modal {
  @include frost-base;
  max-width: 500px;
  margin: auto;
}

Treat them as starting points and adjust from there to fit whatever you’re building.

Integration Patterns

Dropping it into an existing project is straightforward:

// Import the library
@use 'frostpane' as frost;

// Apply to custom components
.my-sidebar {
  @include frost.frost-base;
  @include frost.frost-highlight;
  width: 280px;
  padding: 1rem;
}

The namespaced @use keeps Frostpane’s mixins from colliding with anything else in your styles.


See Frostpane in action at cameronrye.github.io/frostpane or explore the source code on GitHub.

Subscribe

Was this helpful?

Discuss

Ask can help explain concepts, provide context, or point you to related content.