npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

frosted-canvas

v2.0.0

Published

Interactive shader gradients for any div element

Readme

Frosted Canvas

Beautiful, interactive shader gradients for any div element. Built with Three.js and WebGL shaders.

npm version License: MIT

📖 Full Documentation | 🎨 Live Demo | 🛠️ Color Customizer

Table of Contents

Features

  • 44 beautiful preset gradients with smooth animations
  • NEW v2.0: Advanced gradient controls with domain warping and turbulence
  • Custom color API for creating unique gradients
  • Simple, declarative API
  • Framework agnostic (React, Vue, Svelte, vanilla JS)
  • Automatic container resizing
  • Lightweight (~98KB) with Three.js as peer dependency
  • CDN support for no-build workflows
  • Fine-grained control over animation, effects, and gradient flow

Installation

npm install frosted-canvas three

Note: Three.js is a peer dependency to keep the package lightweight (~98KB instead of ~698KB) and prevent duplicate installations.

Quick Start

Basic Usage with Preset

import FrostedCanvas from 'frosted-canvas';

// Initialize with a preset gradient
const frost = new FrostedCanvas('#container', { preset: 0 });
<div id="container" style="width: 100%; height: 400px;"></div>

Static Background

import FrostedCanvas from 'frosted-canvas';

// Generate a static (non-animated) background
const frost = new FrostedCanvas('#container', { 
  preset: 0,
  static: true 
});

Custom Colors

import FrostedCanvas from 'frosted-canvas';

const frost = new FrostedCanvas('#container');

// Create your own gradient
frost.setColors({
  paletteA: [0.9, 0.2, 0.5], // Pink
  paletteB: [0.5, 0.5, 0.5], // Gray
  paletteC: [1.0, 0.8, 0.3], // Yellow
  paletteD: [0.1, 0.3, 0.6], // Blue
});

Using Hex Colors

function hexToRgb(hex) {
  const r = parseInt(hex.slice(1, 3), 16) / 255;
  const g = parseInt(hex.slice(3, 5), 16) / 255;
  const b = parseInt(hex.slice(5, 7), 16) / 255;
  return [r, g, b];
}

frost.setColors({
  paletteA: hexToRgb('#FF6B6B'),
  paletteC: hexToRgb('#4ECDC4'),
});

Understanding the Color Palette

The shader uses a cosine-based formula to generate beautiful procedural gradients. Each gradient is controlled by 4 color palettes (A, B, C, D):

The Formula:

color(t) = a + b · cos[2π(c·t+d)]

The Palettes:

  • Palette A (Offset): Base color offset - shifts the entire color range
  • Palette B (Amplitude): Color intensity - controls how vibrant colors are
  • Palette C (Frequency): Color variation - controls how colors transition
  • Palette D (Phase): Color shift - offsets the color wave

Each palette takes RGB values from 0 to 1:

  • [1.0, 0.0, 0.0] = Red
  • [0.0, 1.0, 0.0] = Green
  • [0.0, 0.0, 1.0] = Blue
  • [0.5, 0.5, 0.5] = Mid Gray

Learn more: YouTube explanation | Full theory

Advanced Gradient Controls (v2.0+)

Version 2.0 introduces powerful new controls for creating more organic and dynamic gradients:

Domain Warping

domainWarpStrength (0-0.5): Warps the coordinate space using layered noise for organic, flowing distortions. Higher values create more dramatic warping effects.

frost.setConfig({ domainWarpStrength: 0.25 }); // Moderate organic flow

Turbulence

turbulence (0-1.0): Adds fractal Brownian motion (FBM) with 5 octaves of noise for additional complexity and detail. Creates layered, turbulent effects.

frost.setConfig({ turbulence: 0.5 }); // Add fractal detail

Gradient Rotation

gradientAngle (0-6.28): Rotates the gradient direction in radians (0° to 360°). Allows dynamic gradient rotation.

frost.setConfig({ gradientAngle: Math.PI / 4 }); // 45 degree rotation

Color Distribution

colorSpread (0.1-3.0): Controls how spread out colors are across the gradient. Lower values create tighter color bands, higher values stretch and repeat colors.

frost.setConfig({ colorSpread: 1.5 }); // Wider color distribution

Flow Animation

flowSpeed (0-1.0): Independent animation speed for the domain warping flow, separate from the main animation speed for more control.

frost.setConfig({ flowSpeed: 0.6 }); // Faster flowing motion

Example: Maximum Organic Effect

frost.setConfig({
  domainWarpStrength: 0.4,
  turbulence: 0.8,
  flowSpeed: 0.5,
  colorSpread: 2.0,
  gradientAngle: Math.PI / 6,
});

API Reference

Constructor

new FrostedCanvas(container, options);

Parameters:

  • container (string | HTMLElement) - CSS selector or DOM element
  • options (object) - Configuration options

Options: | Option | Type | Default | Description | |--------|------|---------|-------------| | preset | number | 0 | Starting preset (0-43) | | showGUI | boolean | false | Show debug controls | | autoResize | boolean | true | Auto-resize on container changes | | static | boolean | false | Generate static (non-animated) background |

Methods

setPreset(index)

Change to a different preset gradient (0-43).

frost.setPreset(3);

setColors(colors)

Set custom RGB colors (values 0-1).

frost.setColors({
  paletteA: [0.9, 0.65, 1.0], // Offset
  paletteB: [0.5, 0.5, 0.5], // Amplitude
  paletteC: [1.0, 0.7, 0.4], // Frequency
  paletteD: [0.0, 0.15, 0.2], // Phase
});

setConfig(config)

Adjust animation, effects, and gradient controls.

frost.setConfig({
  // Animation & Noise
  noiseScale: 0.3, // 0.1-3.0: Size of noise patterns
  noiseStrength: 0.35, // 0-1.0: Intensity of distortion
  animationSpeed: 0.5, // 0-0.5: Speed of animation
  grainIntensity: 0.03, // 0-0.2: Film grain effect
  vignetteStrength: 3.0, // 0-3.0: Edge darkening

  // Advanced Gradient Controls (v2.0+)
  domainWarpStrength: 0.15, // 0-0.5: Organic coordinate warping
  turbulence: 0.2, // 0-1.0: Fractal noise complexity
  gradientAngle: 0.0, // 0-6.28: Rotation angle in radians
  colorSpread: 1.0, // 0.1-3.0: Color distribution
  flowSpeed: 0.3, // 0-1.0: Independent flow animation speed
});

getColors()

Get current color values.

const colors = frost.getColors();
// Returns: { paletteA: [...], paletteB: [...], paletteC: [...], paletteD: [...] }

getConfig()

Get current configuration.

const config = frost.getConfig();
// Returns: { noiseScale: 0.3, noiseStrength: 0.35, ... }

destroy()

Clean up resources and remove canvas.

frost.destroy();

Presets

44 preset gradients are available (indexed 0-43).

Featured Presets

| Index | Name | Description | | ----- | ------------ | ----------------------------------------- | | 0 | Molten Peach | Warm molten peach with lively motion | | 1 | Paper Koi | Gentle paper-like pastels with pond tones | | 2 | Sunset Bloom | Warm orange center with soft grain | | 3 | Aurora Glow | The northern lights | | 4 | Deep Ocean | Muted teals and deep blues, calm motion | | 5 | Slate Grain | High-grain monochrome, cinematic | | 10 | Coral Reef | Bright coral / teal interplay | | 13 | Forest Mist | Subtle greens and cool fog | | 14 | Solar Flare | Fiery amber with fast motion | | 15 | Arctic Dawn | Pale blues, crisp and calm | | 20 | Candy Cloud | Playful pinks and blues | | 30 | Cosmic Bloom | Galactic gradients with soft pulsation | | 43 | Mystic Flow | Ethereal flowing gradients with organic warping (v2.0 showcase) |

All 44 Presets

Molten Peach, Paper Koi, Sunset Bloom, Aurora Glow, Deep Ocean, Slate Grain, Peach Mirage, Crimson Dusk, Watermelon, Electric Indigo, Coral Reef, Lemon Zest, Midnight Velvet, Forest Mist, Solar Flare, Arctic Dawn, Vintage Sepia, Lavender Haze, Moss Grove, Copper Sunset, Candy Cloud, Meteor Storm, Tropical Night, Dusty Rose, Slate Storm, Glacial Drift, Amber Glow, Neon Canyon, Petrol Dream, Saffron Mist, Cosmic Bloom, Porcelain Dawn, Obsidian Fade, Rose Quartz, Velvet Plum, Horizon Teal, Dusty Denim, Brass Ember, Iris Bloom, Celadon Whisper, Starling Night, Polar Mint, Silent Harbor, Mystic Flow.

Framework Integration

React

import { useEffect, useRef } from 'react';
import FrostedCanvas from 'frosted-canvas';

function Hero() {
  const containerRef = useRef(null);
  const frostRef = useRef(null);

  useEffect(() => {
    frostRef.current = new FrostedCanvas(containerRef.current, {
      preset: 0,
    });
    return () => frostRef.current?.destroy();
  }, []);

  return (
    <div ref={containerRef} style={{ width: '100%', height: '100vh' }}>
      <h1>Your Content</h1>
    </div>
  );
}

Vue 3

<template>
  <div ref="container" class="background">
    <h1>Your Content</h1>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import FrostedCanvas from 'frosted-canvas';

const container = ref(null);
let frost = null;

onMounted(() => {
  frost = new FrostedCanvas(container.value, { preset: 0 });
});

onUnmounted(() => frost?.destroy());
</script>

<style scoped>
.background {
  width: 100%;
  height: 100vh;
}
</style>

Svelte

<script>
  import { onMount, onDestroy } from 'svelte';
  import FrostedCanvas from 'frosted-canvas';

  let container;
  let frost;

  onMount(() => {
    frost = new FrostedCanvas(container, { preset: 0 });
  });

  onDestroy(() => {
    if (frost) frost.destroy();
  });
</script>

<div bind:this={container} class="background">
  <h1>Your Content</h1>
</div>

<style>
  .background {
    width: 100%;
    height: 100vh;
  }
</style>

Next.js

'use client';

import { useEffect, useRef } from 'react';
import FrostedCanvas from 'frosted-canvas';

export default function Hero() {
  const containerRef = useRef(null);
  const frostRef = useRef(null);

  useEffect(() => {
    if (containerRef.current && !frostRef.current) {
      frostRef.current = new FrostedCanvas(containerRef.current, {
        preset: 0,
      });
    }

    return () => {
      if (frostRef.current) {
        frostRef.current.destroy();
        frostRef.current = null;
      }
    };
  }, []);

  return (
    <div ref={containerRef} style={{ width: '100%', height: '100vh' }}>
      <h1>Next.js + Frosted Canvas</h1>
    </div>
  );
}

Vanilla JavaScript

<div id="background" style="width: 100%; height: 100vh;"></div>

<script type="module">
  import FrostedCanvas from 'frosted-canvas';
  new FrostedCanvas('#background', { preset: 0 });
</script>

CDN Usage

For projects without a build step:

<!DOCTYPE html>
<html>
  <head>
    <style>
      #background {
        width: 100%;
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <div id="background"></div>

    <script type="importmap">
      {
        "imports": {
          "three": "https://unpkg.com/[email protected]/build/three.module.js",
          "three/": "https://unpkg.com/[email protected]/"
        }
      }
    </script>

    <script type="module">
      import FrostedCanvas from 'https://unpkg.com/frosted-canvas/dist/frosted-canvas.es.js';
      new FrostedCanvas('#background', { preset: 0 });
    </script>
  </body>
</html>

Usage Examples

Full-Screen Hero Background

<div class="hero" id="hero-bg">
  <div class="hero-content">
    <h1>Welcome</h1>
  </div>
</div>

<script type="module">
  import FrostedCanvas from 'frosted-canvas';
  new FrostedCanvas('#hero-bg', { preset: 0 });
</script>

Card Background

<div class="card" id="card-bg">
  <div class="card-content">
    <h2>Card Title</h2>
  </div>
</div>

<script type="module">
  import FrostedCanvas from 'frosted-canvas';
  new FrostedCanvas('#card-bg', { preset: 5 });
</script>

Interactive Preset Switcher

<div id="bg">
  <button onclick="frost.setPreset(0)">Sunset</button>
  <button onclick="frost.setPreset(3)">Aurora</button>
  <button onclick="frost.setPreset(14)">Solar Flare</button>
</div>

<script type="module">
  import FrostedCanvas from 'frosted-canvas';
  window.frost = new FrostedCanvas('#bg', { preset: 0 });
</script>

Custom Color Examples

Sunset Orange & Pink

frost.setColors({
  paletteA: [0.9, 0.65, 1.0],
  paletteB: [0.5, 0.5, 0.5],
  paletteC: [1.0, 0.7, 0.4],
  paletteD: [0.0, 0.15, 0.2],
});

Ocean Blue & Teal

frost.setColors({
  paletteA: [0.5, 0.8, 1.0],
  paletteB: [0.5, 0.5, 0.5],
  paletteC: [1.0, 1.0, 0.5],
  paletteD: [0.0, 0.1, 0.2],
});

Purple & Magenta

frost.setColors({
  paletteA: [0.8, 0.5, 1.0],
  paletteB: [0.5, 0.5, 0.5],
  paletteC: [1.0, 0.5, 0.8],
  paletteD: [0.3, 0.2, 0.5],
});

Tips & Best Practices

Creating Great Gradients

  1. Start with a preset: Use frost.setPreset(0) then tweak from there
  2. Keep Palette B moderate: Values around 0.5 work best for amplitude
  3. Experiment with Palette C: This creates the most dramatic changes
  4. Use complementary colors: Colors opposite on the color wheel create vibrant gradients
  5. Test different noise settings: Lower noiseScale = larger patterns
  6. Adjust animation speed: Slower speeds (0.1-0.3) are often more elegant

When to Use Static Backgrounds

Use static: true when:

  • You want better performance (no animation loop)
  • Creating print-ready or screenshot-friendly designs
  • Building static hero sections or cards
  • Reducing battery consumption on mobile devices
  • You need a beautiful gradient without motion

Performance

  • Container must have explicit width and height
  • Call destroy() when removing the component to clean up resources
  • Use autoResize: true for responsive containers
  • Multiple instances on the same page are supported

Saving and Loading Custom Presets

// Save current state
const myPreset = {
  colors: frost.getColors(),
  config: frost.getConfig(),
};
localStorage.setItem('myGradient', JSON.stringify(myPreset));

// Load later
const saved = JSON.parse(localStorage.getItem('myGradient'));
frost.setColors(saved.colors);
frost.setConfig(saved.config);

Resources

Development

# Install dependencies
npm install

# Start development server
npm run dev

# Build library for npm
npm run build

# Build demo site
npm run build:demo

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE for details.

Credits