Template 1: Simple Sky Background ```html
.sky {
position: relative;
width: 100%;
height: 100vh;
background: linear-gradient(180deg, #87CEEB 0%, #E0F6FF 100%);
overflow: hidden;
}
.cloud {
position: absolute;
background: white;
border-radius: 50%;
filter: url(#cloudFilter);
animation: float linear infinite;
}
.cloud-1 { width: 300px; height: 150px; top: 10%; animation-duration: 80s; }
.cloud-2 { width: 400px; height: 180px; top: 30%; animation-duration: 100s; animation-delay: -30s; }
.cloud-3 { width: 250px; height: 120px; top: 50%; animation-duration: 70s; animation-delay: -50s; }
@keyframes float {
from { transform: translateX(-120%); }
to { transform: translateX(120vw); }
}
```
Template 2: Layered Parallax Clouds ```html
.parallax-sky {
position: relative;
height: 100vh;
background: linear-gradient(to bottom,
#1e3c72 0%,
#2a5298 30%,
#f5af19 90%,
#f12711 100%
);
overflow: hidden;
}
.cloud-layer {
position: absolute;
width: 200%;
height: 100%;
background-repeat: repeat-x;
}
.layer-back {
opacity: 0.3;
filter: url(#cloudBack) blur(2px);
animation: scroll 120s linear infinite;
}
.layer-mid {
opacity: 0.5;
filter: url(#cloudMid);
animation: scroll 80s linear infinite;
}
.layer-front {
opacity: 0.8;
filter: url(#cloudFront);
animation: scroll 45s linear infinite;
}
@keyframes scroll {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
```
Template 3: React Component ```tsx
import React, { useMemo } from 'react';
interface CloudProps {
type?: 'cumulus' | 'cirrus' | 'stratus' | 'storm';
seed?: number;
className?: string;
}
const CLOUD_CONFIGS = {
cumulus: { baseFrequency: '0.008', numOctaves: 4, scale: 60, blur: 4 },
cirrus: { baseFrequency: '0.02 0.005', numOctaves: 3, scale: 25, blur: 2 },
stratus: { baseFrequency: '0.015 0.003', numOctaves: 3, scale: 30, blur: 6 },
storm: { baseFrequency: '0.006', numOctaves: 5, scale: 150, blur: 3 },
};
export const Cloud: React.FC = ({
type = 'cumulus',
seed = Math.floor(Math.random() * 1000),
className
}) => {
const filterId = useMemo(() => cloud-${type}-${seed}, [type, seed]);
const config = CLOUD_CONFIGS[type];
return (
<>
type="fractalNoise"
baseFrequency={config.baseFrequency}
numOctaves={config.numOctaves}
seed={seed}
result="noise"
/>
className={className}
style={{ filter: url(#${filterId}) }}
/>
>
);
};
// Usage:
//
```
Template 4: CSS-Only Box-Shadow Clouds For simpler, more performant clouds without SVG filters:
```css
.cloud-simple {
width: 200px;
height: 60px;
background: white;
border-radius: 100px;
position: relative;
box-shadow:
/ Main body shadows for volume /
inset -10px -10px 30px rgba(0,0,0,0.05),
inset 10px 10px 30px rgba(255,255,255,0.8),
/ Outer glow /
0 10px 40px rgba(0,0,0,0.1);
}
.cloud-simple::before,
.cloud-simple::after {
content: '';
position: absolute;
background: white;
border-radius: 50%;
}
.cloud-simple::before {
width: 100px;
height: 100px;
top: -50px;
left: 30px;
}
.cloud-simple::after {
width: 70px;
height: 70px;
top: -30px;
left: 100px;
}
```
Performance Optimization Critical Rules numOctaves <= 5 - Above 5 provides diminishing visual returns with exponential CPU costBlur BEFORE displacement - 40% more efficient than blur afterAvoid animating filter properties - Use CSS transforms insteadUse seed for variation - Free performance vs. changing baseFrequencywill-change: transform - Only on animated elements, remove when staticBatch filter definitions - One block, reference by IDPerformance Tiers | Tier | Technique | FPS Target | Use Case |
|------|-----------|------------|----------|
| Ultra | CSS box-shadow only | 60fps | Mobile, low-end |
| High | SVG filter, no animation | 60fps | Static backgrounds |
| Medium | SVG filter + CSS transform animation | 45-60fps | Subtle movement |
| Low | SVG filter + | 30fps | Hero sections only |
Mobile Considerations ```css
@media (prefers-reduced-motion: reduce) {
.cloud {
animation: none;
}
}
@media (max-width: 768px) {
.cloud-layer {
/ Reduce to 2 layers on mobile /
}
.cloud {
filter: url(#cloudSimple); / Fewer octaves /
}
}
```
Performance Detection ```javascript
// Detect if device can handle filter animations
const canHandleFilters = () => {
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl');
if (!gl) return false;
const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
const renderer = debugInfo
? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)
: '';
// Reduce effects on integrated graphics
return !renderer.includes('Intel');
};
```
Framework Integration Next.js / React ```tsx
// components/CloudBackground.tsx
'use client';
import { useEffect, useState } from 'react';
export function CloudBackground() {
const [reducedMotion, setReducedMotion] = useState(false);
useEffect(() => {
const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
setReducedMotion(mq.matches);
mq.addEventListener('change', (e) => setReducedMotion(e.matches));
}, []);
return (
{/ SVG defs in portal to document head /}
{/ Cloud layers /}
);
}
```
Vue 3 ```vue
v-for="cloud in clouds"
:key="cloud.id"
class="cloud"
:style="cloud.style"
/>
import { computed } from 'vue';
import CloudFilter from './CloudFilter.vue';
const clouds = computed(() =>
Array.from({ length: 5 }, (_, i) => ({
id: i,
style: {
animationDuration: ${60 + i * 20}s,
animationDelay: ${-i * 15}s,
top: ${10 + i * 15}%,
}
}))
);
```
Tailwind CSS ```javascript
// tailwind.config.js
module.exports = {
theme: {
extend: {
animation: {
'cloud-drift': 'drift 80s linear infinite',
'cloud-morph': 'morph 15s ease-in-out infinite',
},
keyframes: {
drift: {
from: { transform: 'translateX(-100%)' },
to: { transform: 'translateX(100vw)' },
},
morph: {
'0%, 100%': { borderRadius: '60% 40% 30% 70% / 60% 30% 70% 40%' },
'50%': { borderRadius: '30% 60% 70% 40% / 50% 60% 30% 60%' },
},
},
},
},
};
```
Debugging Tips Visualize Filter Steps ```xml
```
Common Issues | Problem | Cause | Solution |
|---------|-------|----------|
| Clouds cut off | Filter region too small | Add x="-50%" y="-50%" width="200%" height="200%" |
| Jagged edges | Missing blur | Add feGaussianBlur before displacement |
| No variation | Same seed | Use different seed values |
| Performance issues | Too many octaves | Reduce numOctaves to 3-4 |
| Animation stuttering | Animating filter attrs | Use CSS transform animations instead |
Reference Sources CSS-Tricks: "Drawing Realistic Clouds with SVG and CSS" LogRocket: "Animated Cloud Generator with SVG CSS" Codrops: "SVG Filter Effects with feTurbulence" Click to Release: "CSS 3D Clouds" (billboard technique) Nephele Cloud Generator tool MDN: SVG Filter Primitives documentation ---
Clouds are nature's way of reminding us that even the sky has texture.