| name | web-weather-creator |
| description | Master of stylized atmospheric effects using SVG filters and CSS animations. Creates clouds, waves, lightning, rain, fog, aurora borealis, god rays, lens flares, twilight skies, and ocean spray—all with a premium aesthetic that's stylized but never cheap-looking. |
| metadata | {"category":"Design","tags":["svg","animations","weather-effects","atmospheric","css-animations"],"pairs-with":[{"skill":"web-cloud-designer","reason":"Cloud effects are a specific weather element sharing SVG filter and animation techniques"},{"skill":"web-wave-designer","reason":"Wave effects share the same SVG feTurbulence and CSS animation infrastructure"},{"skill":"dark-mode-design-expert","reason":"Atmospheric weather effects must adapt visual parameters for dark and light modes"}]} |
Web Weather Creator
Master of stylized atmospheric effects using SVG filters and CSS animations. Creates clouds, waves, lightning, rain, fog, aurora borealis, god rays, lens flares, twilight skies, and ocean spray—all with a premium aesthetic that's stylized but never cheap-looking.
Activation Triggers
Activate on: "clouds", "waves", "weather effects", "atmospheric", "lightning", "rain", "fog", "mist", "aurora", "northern lights", "god rays", "crepuscular", "lens flare", "twilight", "sunset gradient", "golden hour", "ocean spray", "beach wash", "foam", "smoke", "parallax sky", "water ripples", "animated background"
NOT for:
- Photorealistic renders (use WebGL/Three.js)
- Static weather icons (use icon libraries)
- Weather data APIs (use backend services)
- 3D volumetric effects (use Babylon.js/Three.js)
Philosophy: Stylized, Not Cheap
The goal is premium stylization—effects that feel intentional and artistic, not like stock footage or placeholder art.
The Three Principles
- Layering Creates Depth - Multiple semi-transparent layers with parallax motion
- Organic Motion - Varied speeds, easing, and subtle randomization
- Restraint - One hero effect, subtle supporting elements
Quality Spectrum
CHEAP ──────────────────────── STYLIZED ──────────────────────── REALISTIC
CSS gradient blob SVG filter + layered opacity WebGL particles
Single div animation 3-5 layers with parallax Fluid simulation
Linear easing Cubic-bezier + varied timing Physics engine
Target Zone: The middle—stylized enough to feel crafted, performant enough for production.
Clouds Floating Through Content (Z-Index Strategy)
The most common question: "How do I make clouds float through my content, not just behind it?"
The Split-Layer Solution
<div class="atmosphere-container">
<div class="clouds clouds--back"></div>
<main class="content">
<div class="card">Your content here</div>
</main>
<div class="clouds clouds--front"></div>
</div>
.atmosphere-container {
position: relative;
isolation: isolate;
}
.clouds {
position: absolute;
inset: 0;
pointer-events: none;
filter: url(#cloud-cumulus);
}
.clouds--back {
z-index: -1;
opacity: 0.3;
transform: scale(1.5);
animation: drift 120s linear infinite;
}
.content {
position: relative;
z-index: 1;
}
.clouds--front {
z-index: 2;
opacity: 0.12;
transform: scale(0.8);
animation: drift 50s linear infinite reverse;
mask-image: linear-gradient(
to bottom,
black 0%,
transparent 30%,
transparent 70%,
black 100%
);
}
Key Principles
- Split clouds into 2-3 layers (back, mid, front)
- Front clouds use LOW opacity (10-15%) so content remains visible
- Always use
pointer-events: none on cloud layers
- Use masks to clear space around important content
- Vary animation speeds for parallax depth (back = slow, front = fast)
Blend Modes for Natural Integration
.clouds--front {
mix-blend-mode: soft-light;
opacity: 0.25;
}
.clouds--front {
mix-blend-mode: screen;
opacity: 0.15;
}
Content Readability
.card {
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(4px);
}
→ See references/layering-strategies.md for complete patterns including parallax, content-aware masking, and React components.
Core Technique: SVG Filter Chain
All atmospheric effects build on this filter architecture:
<svg width="0" height="0">
<defs>
<filter id="atmosphere" x="-50%" y="-50%" width="200%" height="200%">
<feTurbulence
type="fractalNoise" <!-- or "turbulence" for water -->
baseFrequency="0.01"
numOctaves="4"
seed="1"
result="noise"
/>
<feDisplacementMap
in="SourceGraphic"
in2="noise"
scale="30" <!-- Distortion intensity -->
xChannelSelector="R"
yChannelSelector="G"
result="displaced"
/>
<feGaussianBlur
in="displaced"
stdDeviation=
=
/>
Key Parameter Reference
| Parameter | Effect | Range | Notes |
|---|
type="fractalNoise" | Soft, cloudy | - | Clouds, smoke, fog |
type="turbulence" | Wavy, liquid | - | Water, waves, ripples |
baseFrequency | Shape size | 0.001-0.1 | Lower = larger shapes |
numOctaves | Detail level | 1-8 | 3-5 optimal, >5 diminishing returns |
scale (displacement) | Distortion | 0-100 | Start at 20-30 |
stdDeviation (blur) | Softness | 0-20 | 2-5 for clouds, 0-2 for water |
SECTION A: CLOUD EFFECTS
Cloud Type Recipes
| Cloud Type | baseFrequency | numOctaves | Blur | Character |
|---|
| Cumulus (fluffy) | 0.008 | 4 | 3-5 | Puffy, cotton-like |
| Cirrus (wispy) | 0.003 | 5 | 1-2 | Thin, streaky |
| Stratus (flat) | 0.015 | 2 | 5-8 | Low, uniform |
| Storm (dramatic) | 0.006 | 5 | 2-3 | Dense, textured |
| Cartoon | 0.02 | 2 | 8-12 | Soft, simple |
Multi-Layer Cloud System
.cloud-layer {
position: absolute;
inset: 0;
background: radial-gradient(
ellipse 200% 100% at 50% 100%,
rgba(255, 255, 255, 0.9) 0%,
transparent 70%
);
filter: url(#cloud-filter);
}
.cloud-back {
opacity: 0.3;
transform: scale(1.5);
animation: drift 120s linear infinite;
}
.cloud-mid {
opacity: 0.5;
transform: scale(1.2);
animation: drift 80s linear infinite;
}
.cloud-front {
opacity: 0.7;
transform: scale(1);
animation: drift 50s linear infinite;
}
@keyframes drift {
from { transform: translateX(-10%); }
to { transform: (); }
}
Cloud Color Palettes
:root {
--cloud-white: rgba(255, 255, 255, 0.9);
--cloud-highlight: rgba(255, 250, 240, 1);
--cloud-shadow: rgba(180, 190, 210, 0.6);
--cloud-gold: rgba(255, 200, 100, 0.8);
--cloud-pink: rgba(255, 150, 180, 0.7);
--cloud-purple: rgba(180, 100, 200, 0.5);
--storm-dark: rgba(60, 70, 90, 0.9);
--storm-purple: rgba(80, 60, 100, 0.7);
--storm-highlight: rgba(200, 210, 230, );
}
SECTION B: WAVE & WATER EFFECTS
Critical Difference: Waves Use turbulence
<feTurbulence
type="turbulence"
baseFrequency="0.01 0.03" <!-- X << Y for horizontal waves -->
numOctaves="3"
result="waves"
/>
Wave Type Recipes
| Wave Type | baseFrequency | numOctaves | Scale | Character |
|---|
| Ocean swell | 0.005 0.015 | 3 | 40 | Broad, rolling |
| Lake ripples | 0.02 0.04 | 2 | 15 | Small, regular |
| Beach shore | 0.008 0.02 | 4 | 30 | Approaching, foam |
| Pool reflection | 0.03 0.03 | 2 | 10 | Subtle, uniform |
Animated Wave SVG
<svg viewBox="0 0 1440 320" preserveAspectRatio="none">
<defs>
<filter id="wave-distort">
<feTurbulence
type="turbulence"
baseFrequency="0.01 0.02"
numOctaves="3"
result="turbulence"
>
<animate
attributeName="baseFrequency"
dur="20s"
values="0.01 0.02; 0.015 0.025; 0.01 0.02"
repeatCount="indefinite"
/>
</feTurbulence>
<feDisplacementMap
in="SourceGraphic"
in2="turbulence"
scale="20"
xChannelSelector="R"
yChannelSelector="G"
/>
</filter>
</defs>
<path
fill="var(--ocean-color)"
filter="url(#wave-distort)"
d=
>
Ocean Color Palettes
:root {
--ocean-deep: #0c4a6e;
--ocean-mid: #0369a1;
--ocean-surface: #38bdf8;
--ocean-foam: rgba(255, 255, 255, 0.8);
--tropical-deep: #047857;
--tropical-mid: #10b981;
--tropical-surface: #6ee7b7;
--stormy-deep: #1e3a5f;
--stormy-mid: #334155;
--stormy-surface: #64748b;
--sunset-water: linear-gradient(
180deg,
rgba(251, 146, 60, 0.4) 0%,
rgba(14, 165, 233, 0.6) 50%,
#0c4a6e 100%
);
}
SECTION C: LIGHTNING EFFECTS
SVG Stroke-Dashoffset Lightning
The most effective technique for lightning uses animated stroke-dashoffset on SVG paths:
<svg viewBox="0 0 100 200" class="lightning">
<defs>
<filter id="lightning-glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<path
class="bolt"
d="M50,0 L45,40 L55,45 L40,90 L60,95 L35,150 L70,100 L50,95 L65,50 L45,45 L60,10 Z"
fill="none"
stroke="white"
stroke-width="2"
filter="url(#lightning-glow)"
/>
</svg>
.lightning {
position: absolute;
pointer-events: none;
opacity: 0;
}
.bolt {
stroke-dasharray: 500;
stroke-dashoffset: 500;
}
.lightning.flash {
animation: lightning-flash 0.5s ease-out forwards;
}
.lightning.flash .bolt {
animation: bolt-draw 0.15s ease-out forwards;
}
@keyframes lightning-flash {
0% { opacity: 0; }
10% { opacity: 1; }
20% { opacity: 0.5; }
30% { opacity: 1; }
100% { opacity: 0; }
}
@keyframes bolt-draw {
to { stroke-dashoffset: 0; }
}
Lightning Flash Overlay
.lightning-flash-overlay {
position: fixed;
inset: 0;
background: rgba(255, 255, 255, 0);
pointer-events: none;
z-index: 1000;
}
.lightning-flash-overlay.active {
animation: screen-flash 0.3s ease-out;
}
@keyframes screen-flash {
0% { background: rgba(255, 255, 255, 0); }
10% { background: rgba(200, 220, 255, 0.4); }
20% { background: rgba(255, 255, 255, 0); }
30% { background: rgba(200, 220, 255, 0.2); }
100% { background: rgba(255, 255, 255, 0); }
}
Branching Lightning Pattern
function generateLightningPath(startX, startY, endY, segments = 8) {
let path = `M${startX},${startY}`;
let x = startX;
let y = startY;
const segmentHeight = (endY - startY) / segments;
for (let i = 0; i < segments; i++) {
const jitter = (Math.random() - 0.5) * 30;
x += jitter;
y += segmentHeight;
path += ` L${x},${y}`;
if (Math.random() < 0.2) {
const branchX = x + (Math.random() - 0.5) * 40;
const branchY = y + segmentHeight * 0.5;
path += ` M${x},${y} L${branchX},${branchY} M${x},${y}`;
}
}
return path;
}
SECTION D: RAIN EFFECTS
CSS-Only Rain with Custom Properties
.rain-container {
position: absolute;
inset: 0;
overflow: hidden;
pointer-events: none;
}
.raindrop {
position: absolute;
width: 2px;
background: linear-gradient(
180deg,
transparent 0%,
rgba(174, 194, 224, 0.5) 50%,
rgba(174, 194, 224, 0.8) 100%
);
border-radius: 0 0 2px 2px;
animation: rain-fall var(--fall-duration) linear infinite;
animation-delay: var(--delay);
left: var(--x);
height: var(--length);
opacity: var(--opacity);
}
@keyframes rain-fall {
0% {
transform: translateY(-100vh);
}
100% {
transform: translateY(100vh);
}
}
Rain Generator (JavaScript)
function createRain(container, dropCount = 100) {
for (let i = 0; i < dropCount; i++) {
const drop = document.createElement('div');
drop.className = 'raindrop';
drop.style.setProperty('--x', `${Math.random() * 100}%`);
drop.style.setProperty('--delay', `${Math.random() * 2}s`);
drop.style.setProperty('--fall-duration', `${0.5 + Math.random() * 0.5}s`);
drop.style.setProperty('--length', `${15 + Math.random() * 20}px`);
drop.style.setProperty('--opacity', `${0.3 + Math.random() * 0.5}`);
container.appendChild(drop);
}
}
Rain Intensity Presets
.rain-light {
--drop-count: 50;
--fall-duration-base: 1.2s;
--drop-opacity: 0.3;
}
.rain-moderate {
--drop-count: 150;
--fall-duration-base: 0.8s;
--drop-opacity: 0.5;
}
.rain-heavy {
--drop-count: 300;
--fall-duration-base: 0.5s;
--drop-opacity: 0.7;
}
Rain + Wind Angle
.raindrop.windy {
animation: rain-fall-diagonal var(--fall-duration) linear infinite;
}
@keyframes rain-fall-diagonal {
0% {
transform: translate(-50vw, -100vh) rotate(15deg);
}
100% {
transform: translate(50vw, 100vh) rotate(15deg);
}
}
SECTION E: FOG & MIST EFFECTS
Multi-Layer Fog System
.fog-container {
position: absolute;
inset: 0;
overflow: hidden;
pointer-events: none;
}
.fog-layer {
position: absolute;
width: 200%;
height: 100%;
background: url("data:image/svg+xml,...") repeat-x;
opacity: 0.3;
filter: url(#fog-filter);
}
.fog-back {
animation: fog-drift 60s linear infinite;
opacity: 0.2;
transform: scale(1.5);
}
.fog-mid {
animation: fog-drift 40s linear infinite reverse;
opacity: 0.3;
transform: scale(1.2);
}
.fog-front {
animation: fog-drift 25s linear infinite;
opacity: 0.4;
}
@keyframes fog-drift {
from { transform: translateX(-50%); }
to { transform: translateX(0%); }
}
SVG Fog Filter
<filter id="fog-filter" x="-50%" y="-50%" width="200%" height="200%">
<feTurbulence
type="fractalNoise"
baseFrequency="0.003"
numOctaves="4"
seed="5"
result="noise"
/>
<feGaussianBlur in="noise" stdDeviation="20" result="blur" />
<feColorMatrix
type="matrix"
values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 0.5 0"
result="faded"
/>
</filter>
Fog Density Variations
:root {
--fog-light: rgba(255, 255, 255, 0.2);
--fog-blur-light: 10px;
--fog-mist: rgba(200, 210, 230, 0.4);
--fog-blur-mist: 20px;
--fog-dense: rgba(180, 190, 210, 0.6);
--fog-blur-dense: 40px;
--fog-eerie: rgba(100, 120, 140, 0.5);
--fog-blur-eerie: 30px;
}
Ground-Hugging Mist
.ground-mist {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 30%;
background: linear-gradient(
to top,
rgba(255, 255, 255, 0.6) 0%,
rgba(255, 255, 255, 0.3) 40%,
transparent 100%
);
filter: url(#fog-filter);
animation: mist-breathe 8s ease-in-out infinite;
}
@keyframes mist-breathe {
0%, 100% {
opacity: 0.5;
transform: scaleY(1);
}
50% {
opacity: 0.7;
transform: scaleY(1.1);
}
}
SECTION F: TWILIGHT & SKY GRADIENTS
Sky Time Progression
:root {
--sky-predawn: linear-gradient(
to top,
#1a1a2e 0%,
#16213e 30%,
#0f3460 60%,
#1a1a2e 100%
);
--sky-dawn: linear-gradient(
to top,
#ff6b6b 0%,
#feca57 20%,
#ff9ff3 40%,
#54a0ff 70%,
#1a1a2e 100%
);
--sky-golden: linear-gradient(
to top,
#ff9a56 0%,
#ffbe76 30%,
#ffeaa7 50%,
#74b9ff 80%,
#0984e3 100%
);
--sky-midday: linear-gradient(
to top,
#74b9ff 0%,
#0984e3 50%,
#0652dd 100%
);
--sky-sunset: linear-gradient(
to top,
#e17055 0%,
,
,
,
);
: (
to top,
,
,
,
,
,
);
: (
to top,
,
,
);
}
Animated Sky Transition
.sky-canvas {
background: var(--sky-midday);
transition: background 3s ease-in-out;
}
.sky-canvas[data-time="dawn"] { background: var(--sky-dawn); }
.sky-canvas[data-time="golden"] { background: var(--sky-golden); }
.sky-canvas[data-time="midday"] { background: var(--sky-midday); }
.sky-canvas[data-time="sunset"] { background: var(--sky-sunset); }
.sky-canvas[data-time="dusk"] { background: var(--sky-dusk); }
.sky-canvas[data-time="night"] { background: var(--sky-night); }
Sun/Moon Position System
.celestial-body {
position: absolute;
width: 60px;
height: 60px;
border-radius: 50%;
transition: all 2s cubic-bezier(0.4, 0, 0.2, 1);
}
.sun {
background: radial-gradient(
circle,
#fff7e6 0%,
#ffd93d 40%,
#ff8c00 100%
);
box-shadow:
0 0 40px 10px rgba(255, 200, 50, 0.6),
0 0 80px 30px rgba(255, 150, 0, 0.3);
}
.moon {
background: radial-gradient(
circle at 30% 30%,
#f5f5f5 0%,
#e0e0e0 50%,
#bdbdbd 100%
);
box-shadow:
0 (, , , ),
inset - - (, , , );
}
SECTION G: AURORA BOREALIS
Stacked Gradient Aurora
.aurora-container {
position: absolute;
inset: 0;
overflow: hidden;
background: linear-gradient(to top, #0a0a1a 0%, #1a1a3a 100%);
}
.aurora-band {
position: absolute;
top: 10%;
left: -50%;
width: 200%;
height: 40%;
opacity: 0.6;
mix-blend-mode: screen;
filter: blur(30px);
}
.aurora-green {
background: linear-gradient(
90deg,
transparent 0%,
rgba(0, 255, 128, 0.4) 20%,
rgba(0, 255, 200, 0.6) 50%,
rgba(0, 255, 128, 0.4) 80%,
transparent 100%
);
animation: aurora-wave 15s ease-in-out infinite;
}
.aurora-purple {
: (
,
transparent ,
(, , , ) ,
(, , , ) ,
(, , , ) ,
transparent
);
: aurora-wave ease-in-out infinite reverse;
: -;
}
{
: (
,
transparent ,
(, , , ) ,
(, , , ) ,
(, , , ) ,
transparent
);
: aurora-wave ease-in-out infinite;
: -;
}
aurora-wave {
, {
: (-) () (-);
: ;
}
{
: (-) () ();
: ;
}
{
: () () (-);
: ;
}
{
: () () ();
: ;
}
}
Aurora Curtain Effect
.aurora-curtain {
position: absolute;
top: 0;
width: 100%;
height: 60%;
background: repeating-linear-gradient(
90deg,
transparent 0px,
rgba(0, 255, 150, 0.1) 2px,
transparent 4px
);
filter: blur(2px);
animation: curtain-shimmer 3s ease-in-out infinite;
}
@keyframes curtain-shimmer {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.6; }
}
Aurora Color Palettes
:root {
--aurora-green-1: rgba(0, 255, 128, 0.6);
--aurora-green-2: rgba(50, 255, 180, 0.4);
--aurora-purple-1: rgba(138, 43, 226, 0.5);
--aurora-purple-2: rgba(186, 85, 211, 0.4);
--aurora-blue-1: rgba(0, 191, 255, 0.4);
--aurora-blue-2: rgba(65, 105, 225, 0.3);
--aurora-red-1: rgba(255, 69, 0, 0.3);
--aurora-red-2: rgba(255, 99, 71, 0.2);
}
SECTION H: GOD RAYS (CREPUSCULAR RAYS)
Conic Gradient God Rays
.god-rays-container {
position: absolute;
inset: 0;
overflow: hidden;
pointer-events: none;
}
.god-rays {
position: absolute;
top: -50%;
left: 50%;
transform: translateX(-50%);
width: 200%;
height: 200%;
background: conic-gradient(
from 180deg at 50% 0%,
transparent 0deg,
rgba(255, 248, 220, 0.2) 5deg,
transparent 10deg,
transparent 20deg,
rgba(255, 248, 220, 0.15) 25deg,
transparent 30deg,
transparent 45deg,
rgba(255, 248, 220, 0.2) 50deg,
transparent 55deg,
transparent 70deg,
rgba(255, 248, 220, 0.1) ,
transparent ,
transparent ,
(, , , ) ,
transparent ,
transparent ,
(, , , ) ,
transparent ,
transparent ,
(, , , ) ,
transparent ,
transparent
);
: (
ellipse at ,
black ,
transparent
);
: rays-pulse ease-in-out infinite;
}
rays-pulse {
, { : ; }
{ : ; }
}
Through-Window God Rays
.window-rays {
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(
135deg,
transparent 0%,
transparent 30%,
rgba(255, 248, 220, 0.3) 30%,
rgba(255, 248, 220, 0.1) 35%,
transparent 35%,
transparent 45%,
rgba(255, 248, 220, 0.25) 45%,
rgba(255, 248, 220, 0.05) 52%,
transparent 52%,
transparent 60%,
rgba(255, 248, 220, 0.2) 60%,
rgba(255, 248, 220, 0.05) 68%,
transparent 68%
);
filter: blur(20px);
mix-blend-mode: overlay;
}
Animated Ray Rotation
.rotating-rays {
animation: rays-rotate 120s linear infinite;
}
@keyframes rays-rotate {
from { transform: translateX(-50%) rotate(0deg); }
to { transform: translateX(-50%) rotate(360deg); }
}
SECTION I: LENS FLARE & CAMERA EFFECTS
Radial Gradient Lens Flare
.lens-flare-container {
position: absolute;
inset: 0;
pointer-events: none;
overflow: hidden;
}
.flare-source {
position: absolute;
width: 80px;
height: 80px;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(255, 255, 255, 1) 0%,
rgba(255, 240, 200, 0.8) 20%,
rgba(255, 200, 100, 0.4) 40%,
transparent 70%
);
box-shadow:
0 0 60px 30px rgba(255, 200, 100, 0.5),
0 0 120px 60px rgba(255, 150, 50, 0.3);
}
.flare-artifact {
: absolute;
: ;
: ;
}
{
: ;
: ;
: (
circle,
(, , , ) ,
(, , , ) ,
transparent
);
: (
, , , , ,
);
}
{
: ;
: ;
: (
,
transparent ,
(, , , ) ,
(, , , ) ,
(, , , ) ,
transparent
);
: center;
}
{
: ;
: ;
: solid (, , , );
: transparent;
}
Anamorphic Flare (Cinematic)
.anamorphic-flare {
position: absolute;
width: 100%;
height: 4px;
top: 50%;
transform: translateY(-50%);
background: linear-gradient(
90deg,
transparent 0%,
rgba(100, 180, 255, 0.3) 20%,
rgba(255, 255, 255, 0.6) 50%,
rgba(100, 180, 255, 0.3) 80%,
transparent 100%
);
filter: blur(2px);
animation: anamorphic-pulse 4s ease-in-out infinite;
}
@keyframes anamorphic-pulse {
0%, 100% {
opacity: 0.4;
transform: translateY(-50%) scaleX(0.8);
}
50% {
opacity: 0.7;
transform: translateY(-) ();
}
}
Dynamic Flare Following Mouse
function createDynamicFlare(container, sourcePosition) {
const center = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
const direction = {
x: center.x - sourcePosition.x,
y: center.y - sourcePosition.y
};
const artifactCount = 5;
for (let i = 0; i < artifactCount; i++) {
const t = (i + 1) / (artifactCount + 1);
const artifact = document.createElement('div');
artifact.className = 'flare-artifact hexagon';
artifact.style.left = `${sourcePosition.x + direction.x * t * 1.5}px`;
artifact.style.top = `${sourcePosition.y + direction.y * t * 1.5}px`;
artifact.style.opacity = 0.3 - (i * 0.05);
artifact.style.transform = ;
container.(artifact);
}
}
SECTION J: OCEAN SPRAY & SPLASH
Particle-Based Spray
.spray-container {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 40%;
overflow: hidden;
pointer-events: none;
}
.spray-particle {
position: absolute;
width: var(--size, 4px);
height: var(--size, 4px);
border-radius: 50%;
background: radial-gradient(
circle,
rgba(255, 255, 255, 0.9) 0%,
rgba(200, 230, 255, 0.6) 50%,
transparent 100%
);
animation: spray-rise var(--duration, 1s) ease-out forwards;
animation-delay: var(--delay, 0s);
}
@keyframes spray-rise {
0% {
transform: translateY(0) scale(1);
opacity: 0.8;
}
50% {
: ;
}
{
: (-) ((--drift, )) ();
: ;
}
}
Spray Generator
function createSpray(container, intensity = 'medium') {
const config = {
light: { count: 20, maxSize: 6, maxDuration: 1.2 },
medium: { count: 50, maxSize: 10, maxDuration: 1.5 },
heavy: { count: 100, maxSize: 15, maxDuration: 2 }
}[intensity];
for (let i = 0; i < config.count; i++) {
const particle = document.createElement('div');
particle.className = 'spray-particle';
particle.style.setProperty('--size', `${2 + Math.random() * config.maxSize}px`);
particle.style.setProperty('--duration', `${0.5 + Math.random() * config.maxDuration}s`);
particle.style.setProperty('--delay', );
particle..(, );
particle.. = ;
particle.. = ;
container.(particle);
( particle.(), ( + config.) * + );
}
}
Impact Splash Ring
.splash-ring {
position: absolute;
border-radius: 50%;
border: 3px solid rgba(255, 255, 255, 0.6);
background: transparent;
animation: splash-expand 0.8s ease-out forwards;
}
@keyframes splash-expand {
0% {
width: 10px;
height: 10px;
opacity: 1;
transform: translate(-50%, -50%) rotateX(70deg);
}
100% {
width: 150px;
height: 150px;
opacity: 0;
transform: translate(-50%, -50%) rotateX(70deg);
}
}
SECTION K: BEACH WASH & FOAM
Shore Wash Animation
<svg class="beach-wave" viewBox="0 0 1440 200" preserveAspectRatio="none">
<defs>
<linearGradient id="foam-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="rgba(255,255,255,0.9)" />
<stop offset="30%" stop-color="rgba(200,230,255,0.6)" />
<stop offset="100%" stop-color="rgba(56,189,248,0.4)" />
</linearGradient>
<filter id="foam-texture">
<feTurbulence type="turbulence" baseFrequency="0.02 0.05" numOctaves="3" />
<feDisplacementMap in="SourceGraphic" scale="5" />
.beach-container {
position: relative;
height: 300px;
overflow: hidden;
}
.wet-sand {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 100px;
background: linear-gradient(
to top,
#c2b280 0%,
#d4c896 50%,
#e6dbb0 100%
);
}
.wet-sand::before {
content: '';
position: absolute;
inset: 0;
background: rgba(56, 189, 248, 0.2);
animation: wet-recede 4s ease-in-out infinite;
}
@keyframes wet-recede {
0%, 100% {
clip-path: polygon(0 0, 100% 0, 100% 80%, 0 60%);
}
50% {
clip-path: polygon( , , , );
}
}
Foam Bubble Details
.foam-bubbles {
position: absolute;
width: 100%;
height: 30px;
bottom: 60px;
}
.foam-bubble {
position: absolute;
width: var(--size, 8px);
height: var(--size, 8px);
border-radius: 50%;
background: radial-gradient(
circle at 30% 30%,
rgba(255, 255, 255, 0.9) 0%,
rgba(200, 230, 255, 0.5) 50%,
transparent 100%
);
animation: bubble-pop var(--duration, 2s) ease-out infinite;
animation-delay: var(--delay, 0s);
}
@keyframes bubble-pop {
0% {
transform: scale(1);
opacity: 0.8;
}
80% {
transform: scale(1.1);
opacity: ;
}
{
: ();
: ;
}
}
Receding Wave Trail
.wave-trail {
position: absolute;
bottom: 60px;
left: 0;
right: 0;
height: 5px;
background: linear-gradient(
90deg,
transparent 0%,
rgba(255, 255, 255, 0.6) 10%,
rgba(255, 255, 255, 0.8) 50%,
rgba(255, 255, 255, 0.6) 90%,
transparent 100%
);
animation: trail-recede 4s ease-in-out infinite;
}
@keyframes trail-recede {
0% {
transform: translateY(0) scaleX(1);
opacity: 0.8;
}
50% {
transform: translateY(-30px) scaleX(0.95);
opacity: 0.4;
}
100% {
transform: translateY() ();
: ;
}
}
SECTION L: PERFORMANCE OPTIMIZATION
Performance Tiers
@media (prefers-reduced-motion: reduce) {
.weather-effect {
animation: none !important;
filter: none !important;
}
}
.weather-effect--performance {
filter: url(#static-filter);
animation-play-state: paused;
}
.weather-effect--full {
filter: url(#animated-filter);
animation-play-state: running;
}
GPU Acceleration
.weather-layer {
will-change: transform, opacity;
transform: translateZ(0);
backface-visibility: hidden;
contain: layout paint;
}
.weather-layer {
animation: transform-change 10s;
}
Intersection Observer for Off-Screen
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const effect = entry.target;
if (entry.isIntersecting) {
effect.classList.add('weather-effect--active');
} else {
effect.classList.remove('weather-effect--active');
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.weather-effect').forEach(el => observer.observe(el));
Mobile Optimization
@media (max-width: 768px) {
.cloud-back,
.fog-back {
display: none;
}
.weather-filter {
filter: blur(var(--blur)) opacity(0.5);
}
.rain-container {
--drop-count: 50;
}
}
SECTION M: REACT INTEGRATION
Weather Effect Provider
import React, { createContext, useContext, useState, useEffect } from 'react';
type WeatherType =
| 'clear'
| 'cloudy'
| 'rainy'
| 'stormy'
| 'foggy'
| 'snowy'
| 'aurora';
type TimeOfDay = 'dawn' | 'morning' | 'noon' | 'afternoon' | 'dusk' | 'night';
interface WeatherContextType {
weather: WeatherType;
timeOfDay: TimeOfDay;
intensity: number;
setWeather: (w: WeatherType) => void;
setTimeOfDay: (t: TimeOfDay) => void;
setIntensity: (i: number) => void;
}
const WeatherContext = createContext<WeatherContextType | null>(null);
export () {
[weather, setWeather] = useState<>();
[timeOfDay, setTimeOfDay] = useState<>();
[intensity, setIntensity] = ();
( {
hour = ().();
(hour >= && hour < ) ();
(hour >= && hour < ) ();
(hour >= && hour < ) ();
(hour >= && hour < ) ();
(hour >= && hour < ) ();
();
}, []);
(
);
}
= () => {
context = ();
(!context) ();
context;
};
Atmospheric Canvas Component
import React from 'react';
import { useWeather } from './WeatherProvider';
import { CloudLayer } from './CloudLayer';
import { RainEffect } from './RainEffect';
import { LightningEffect } from './LightningEffect';
import { FogLayer } from './FogLayer';
import { AuroraEffect } from './AuroraEffect';
import { SkyGradient } from './SkyGradient';
export function AtmosphericCanvas() {
const { weather, timeOfDay, intensity } = useWeather();
return (
<div className="atmospheric-canvas">
{/* SVG Filters */}
<svg width="0" height="0" aria-hidden="true">
<defs>
<filter =>...
...
...
{/* Sky base */}
{/* Weather layers */}
{(weather === 'cloudy' || weather === 'rainy' || weather === 'stormy') && (
)}
{weather === 'foggy' && }
{weather === 'aurora' && }
{(weather === 'rainy' || weather === 'stormy') && (
)}
{weather === 'stormy' && }
);
}
Individual Effect Components
interface CloudLayerProps {
variant: 'cumulus' | 'cirrus' | 'stratus' | 'storm';
opacity?: number;
}
export function CloudLayer({ variant, opacity = 0.7 }: CloudLayerProps) {
const configs = {
cumulus: { baseFrequency: 0.008, blur: 4, layers: 3 },
cirrus: { baseFrequency: 0.003, blur: 2, layers: 2 },
stratus: { baseFrequency: 0.015, blur: 6, layers: 2 },
storm: { baseFrequency: 0.006, blur: 3, layers: 4 }
};
const config = configs[variant];
return (
<div className="cloud-system" style={{ '--opacity': opacity } }>
{Array.from({ length: config.layers }, (_, i) => (
))}
);
}
SECTION N: TAILWIND INTEGRATION
Custom Tailwind Utilities
module.exports = {
theme: {
extend: {
animation: {
'drift': 'drift 60s linear infinite',
'drift-slow': 'drift 120s linear infinite',
'drift-fast': 'drift 30s linear infinite',
'wave': 'wave 10s ease-in-out infinite',
'rain-fall': 'rain-fall 0.8s linear infinite',
'lightning': 'lightning-flash 0.5s ease-out',
'aurora': 'aurora-wave 15s ease-in-out infinite',
'fog-breathe': 'fog-breathe 8s ease-in-out infinite',
},
keyframes: {
drift: {
'0%': { transform: 'translateX(-10%)' },
'100%': { transform: 'translateX(10%)' },
},
wave: {
'0%, 100%': { transform: 'translateY(0)' },
'50%': { transform: 'translateY(-10px)' },
},
'rain-fall': {
'0%': { transform: 'translateY(-100vh)' },
'100%': { transform: 'translateY(100vh)' },
},
'lightning-flash': {
'0%': { : },
: { : },
: { : },
: { : },
: { : },
},
: {
: { : , : },
: { : , : },
},
: {
: { : , : },
: { : , : },
},
},
: {
: ,
: ,
},
},
},
: [
() {
({
: {
: ,
},
: {
: ,
},
: {
: ,
},
: {
: ,
},
: {
: ,
},
});
},
],
};
Tailwind Component Classes
<div class="absolute inset-0 opacity-50 filter-cloud animate-drift-slow"></div>
<div class="absolute inset-0 overflow-hidden pointer-events-none">
<div class="w-0.5 h-5 bg-gradient-to-b from-transparent via-sky-200/50 to-sky-300/80 rounded-b animate-rain-fall"></div>
</div>
<div class="absolute inset-0 bg-white/30 backdrop-blur-fog filter-fog animate-fog-breathe"></div>
<div class="absolute top-1/4 -left-1/2 w-[200%] h-2/5 opacity-60 mix-screen blur-3xl animate-aurora bg-gradient-to-r from-transparent via-emerald-400/40 to-transparent"></div>
Quick Reference Card
Effect Selection Matrix
| Effect | Best For | Complexity | Performance |
|---|
| Clouds | Hero sections, headers | Medium | High |
| Waves | Footers, section dividers | Medium | High |
| Lightning | Dramatic moments, gaming | Low | Very High |
| Rain | Mood, atmosphere | Medium | Medium |
| Fog | Mystery, depth | Low | High |
| Aurora | Night scenes, magical | High | Medium |
| God rays | Divine, cinematic | Low | High |
| Lens flare | Realistic, photography | Medium | High |
| Ocean spray | Beach, action | High | Low |
| Beach wash | Coastal, calm | Medium | Medium |
| Twilight sky | Time indication | Low | Very High |
Common Combinations
| Scene | Effects | Notes |
|---|
| Dramatic storm | Storm clouds + Rain + Lightning | Stagger lightning timing |
| Peaceful beach | Light clouds + Beach wash + God rays | Slow animations |
| Foggy morning | Fog + Ground mist + Soft clouds | Reduce saturation |
| Northern night | Aurora + Stars + Light fog | Dark background essential |
| Cinematic moment | God rays + Lens flare + Light haze | Don't overdo flares |
Performance Budget
| Device | Max Layers | Max Particles | Filter Complexity |
|---|
| Desktop | 5-7 | 200 | Full |
| Tablet | 3-5 | 100 | Simplified |
| Mobile | 2-3 | 50 | Minimal |
Resources & References
Tutorials Referenced
Tools
Code Collections
Version History
- v1.0.0 (2026-01-25): Merged from web-cloud-designer + web-wave-designer, added lightning, rain, fog, twilight, aurora, god rays, lens flare, ocean spray, beach wash effects
Remember: Stylized weather effects are about restraint and layering. One well-crafted effect beats five mediocre ones. When in doubt, reduce intensity and increase subtlety.