Usage
Common patterns for integrating Meteocons into your project. All examples use the fill style — swap fill for flat, line, or monochrome to use a different style.
SVG in HTML
The simplest approach — load animated SVGs as images. Animations play automatically without any JavaScript.
<img
src="https://cdn.meteocons.com/latest/svg/fill/rain.svg"
alt="Rain"
width="64"
height="64"
/>
You can also use SVGs as CSS backgrounds, though animations won’t play in background images:
.weather-icon {
width: 64px;
height: 64px;
background: url('https://cdn.meteocons.com/latest/svg/fill/rain.svg') center / contain no-repeat;
}
Inline SVG
Fetch and inline the SVG for full CSS control over individual elements. This is useful when you want to apply custom styling, filters, or CSS animations.
async function loadIcon(container, slug, style = 'fill') {
const response = await fetch(`https://cdn.meteocons.com/latest/svg/${style}/${slug}.svg`);
const svg = await response.text();
container.innerHTML = svg;
}
// Usage
const el = document.getElementById('icon');
await loadIcon(el, 'rain');
Once inlined, you can style every part of the SVG with CSS:
#icon svg {
width: 64px;
height: 64px;
}
/* Pause animations on hover */
#icon svg:hover * {
animation-play-state: paused;
}
Responsive sizing
Icons are designed on a 128×128 canvas and scale cleanly. Use CSS to make them responsive:
/* Fixed size */
.icon-sm { width: 32px; height: 32px; }
.icon-md { width: 64px; height: 64px; }
.icon-lg { width: 128px; height: 128px; }
/* Fluid — scales with parent */
.icon-fluid {
width: 100%;
height: auto;
max-width: 128px;
}
Lottie on the web
Lottie gives you full playback control — speed, direction, play/pause, and segment playback. Install lottie-web:
bun add lottie-webnpm install lottie-webyarn add lottie-webpnpm add lottie-web import lottie from 'lottie-web';
import rainAnimation from '@meteocons/lottie/fill/rain.json';
const animation = lottie.loadAnimation({
container: document.getElementById('weather-icon'),
renderer: 'canvas', // 'canvas' for performance, 'svg' for quality
loop: true,
autoplay: true,
animationData: rainAnimation
});
// Playback control
animation.setSpeed(0.5); // half speed
animation.setDirection(-1); // play in reverse
animation.goToAndStop(30, true); // jump to frame 30
animation.pause();
animation.play();
// Clean up when removing the element
animation.destroy();
Renderer comparison
| Renderer | Pros | Cons |
|---|---|---|
canvas | Better performance, lower memory | No CSS styling of internals |
svg | CSS accessible, crisp at any zoom | Slower with many icons |
Use canvas when displaying multiple icons on one page. Use svg when you need to style animation elements with CSS.
Lazy loading
When displaying many icons (e.g. a dashboard or icon grid), load them on demand with IntersectionObserver to avoid blocking the initial page load.
Lazy SVG images
<img
data-src="https://cdn.meteocons.com/latest/svg/fill/rain.svg"
alt="Rain"
width="64"
height="64"
loading="lazy"
/>
Native loading="lazy" works for <img> tags. For Lottie, use a manual observer:
Lazy Lottie animations
import lottie from 'lottie-web';
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (!entry.isIntersecting) {
continue;
}
lottie.loadAnimation({
container: entry.target,
renderer: 'canvas',
loop: true,
autoplay: true,
path: entry.target.dataset.src
});
observer.unobserve(entry.target);
}
}, { rootMargin: '200px' });
document.querySelectorAll('.lottie-icon').forEach(el => observer.observe(el));
<div class="lottie-icon" data-src="https://cdn.meteocons.com/latest/lottie/fill/rain.json" style="width: 64px; height: 64px"></div>
<div class="lottie-icon" data-src="https://cdn.meteocons.com/latest/lottie/fill/snow.json" style="width: 64px; height: 64px"></div>
<div class="lottie-icon" data-src="https://cdn.meteocons.com/latest/lottie/fill/wind.json" style="width: 64px; height: 64px"></div>
Accessibility
Weather icons convey information — make sure they’re accessible to everyone.
Images with alt text
Always provide meaningful alt text that describes the weather condition, not the icon name:
<!-- Good: describes the weather -->
<img src="https://cdn.meteocons.com/latest/svg/fill/rain.svg" alt="Rain expected" width="64" height="64" />
<!-- Bad: describes the icon -->
<img src="https://cdn.meteocons.com/latest/svg/fill/rain.svg" alt="rain icon" width="64" height="64" />
Decorative icons
If the icon is purely decorative (the weather is also described in text), hide it from screen readers:
<div class="forecast">
<img src="https://cdn.meteocons.com/latest/svg/fill/rain.svg" alt="" aria-hidden="true" width="48" height="48" />
<span>Rain — 18°C</span>
</div>
Reduced motion
Some users prefer reduced motion. Respect their preference by pausing SVG animations:
For Lottie, check the preference in JavaScript and show the first frame instead of looping:
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const animation = lottie.loadAnimation({
container: el,
path: 'https://cdn.meteocons.com/latest/lottie/fill/rain.json',
loop: !prefersReducedMotion,
autoplay: !prefersReducedMotion
});
if (prefersReducedMotion) {
animation.goToAndStop(0, true);
}
Dark mode with monochrome
The monochrome style uses currentColor for all fills and strokes, so the icons automatically match your text color. This is ideal for dark mode, theming, or branded interfaces.
Inline SVG (recommended)
Fetch the SVG and inject it as inline HTML. The icon inherits the CSS color property:
<div class="weather-widget">
<span class="icon"></span>
<span>Rain — 18°C</span>
</div>
const response = await fetch('https://cdn.meteocons.com/latest/svg/monochrome/rain.svg');
document.querySelector('.icon').innerHTML = await response.text();
.weather-widget {
color: #1e293b;
}
@media (prefers-color-scheme: dark) {
.weather-widget {
color: #f1f5f9;
}
}
CSS mask-image
Use the SVG as a mask and control the color via background-color. Works with external files, but does not support animations:
.weather-icon {
display: inline-block;
width: 64px;
height: 64px;
background-color: currentColor;
mask-image: url('https://cdn.meteocons.com/latest/svg/monochrome/rain.svg');
mask-size: contain;
mask-repeat: no-repeat;
}
Image tag
When using an <img> tag, currentColor does not work because the SVG is rendered in an isolated context. The icon will always appear black. Use the <img> tag only when you don’t need color customization:
<img src="https://cdn.meteocons.com/latest/svg/monochrome/rain.svg" alt="Rain" width="64" height="64" />
Lottie color customization
Lottie files encode colors as static RGBA values — there is no currentColor equivalent. To change colors at runtime, you have two options.
DOM manipulation (SVG renderer)
When using lottie-web with the svg renderer, you can modify the rendered SVG elements:
const animation = lottie.loadAnimation({
container: el,
path: 'https://cdn.meteocons.com/latest/lottie/monochrome/rain.json',
renderer: 'svg',
loop: true,
autoplay: true
});
animation.addEventListener('DOMLoaded', () => {
el.querySelectorAll('[fill="rgb(0,0,0)"]').forEach(node => {
node.setAttribute('fill', '#e2e8f0');
});
el.querySelectorAll('[stroke="rgb(0,0,0)"]').forEach(node => {
node.setAttribute('stroke', '#e2e8f0');
});
});
JSON pre-processing
Replace color values in the Lottie JSON before loading:
const response = await fetch('https://cdn.meteocons.com/latest/lottie/monochrome/rain.json');
const data = await response.json();
// Replace black [0,0,0,1] with a custom color
const json = JSON.stringify(data);
const colored = json.replaceAll(
'"c":{"a":0,"k":[0,0,0,1]}',
'"c":{"a":0,"k":[0.886,0.910,0.941,1]}' // #e2e8f0
);
lottie.loadAnimation({
container: el,
animationData: JSON.parse(colored),
renderer: 'svg',
loop: true,
autoplay: true
});
Lottie on mobile
iOS (Swift)
Using the lottie-ios library:
import Lottie
let animationView = LottieAnimationView(name: "rain")
animationView.frame = CGRect(x: 0, y: 0, width: 64, height: 64)
animationView.loopMode = .loop
animationView.play()
view.addSubview(animationView)
Android (Kotlin)
Using the lottie-android library:
<!-- layout.xml -->
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/weatherIcon"
android:layout_width="64dp"
android:layout_height="64dp"
app:lottie_rawRes="@raw/rain"
app:lottie_loop="true"
app:lottie_autoPlay="true" />
// Or programmatically
val animationView = findViewById<LottieAnimationView>(R.id.weatherIcon)
animationView.setAnimation("rain.json")
animationView.repeatCount = LottieDrawable.INFINITE
animationView.playAnimation()
React Native
bun add lottie-react-nativenpm install lottie-react-nativeyarn add lottie-react-nativepnpm add lottie-react-native import LottieView from 'lottie-react-native';
function WeatherIcon() {
return (
<LottieView
source={require('@meteocons/lottie/fill/rain.json')}
autoPlay
loop
style={{ width: 64, height: 64 }}
/>
);
}
Dynamic loading
Map weather API conditions to icon slugs for real-time weather displays:
const CONDITION_MAP: Record<string, string> = {
sunny: 'clear-day',
clear: 'clear-day',
'clear-night': 'clear-night',
cloudy: 'overcast',
'partly-cloudy': 'partly-cloudy-day',
rainy: 'rain',
'heavy-rain': 'extreme-rain',
snowy: 'snow',
stormy: 'thunderstorms-day-rain',
windy: 'wind',
foggy: 'fog-day',
hail: 'hail',
};
function getIconUrl(condition: string, style = 'fill', format: 'svg' | 'json' = 'svg'): string {
const slug = CONDITION_MAP[condition] ?? 'not-available';
const type = format === 'json' ? 'lottie' : 'svg';
return `https://cdn.meteocons.com/latest/${type}/${style}/${slug}.${format}`;
}
// Example: render weather for a city
function renderWeather(condition: string, temp: number) {
const iconUrl = getIconUrl(condition);
return `
<div class="weather">
<img src="${iconUrl}" alt="${condition}" width="64" height="64" />
<span>${temp}°C</span>
</div>
`;
}
Using the manifest
The manifest file contains metadata about all icons — their slugs, categories, and whether they’re animated. This is useful for building icon pickers, search features, or documentation.
import manifest from '@meteocons/svg/manifest.json';
// Get all icons in a flat list
const allIcons = manifest.categories.flatMap(category => category.icons);
console.log(`Total icons: ${allIcons.length}`);
// Find all rain-related icons
const rainIcons = allIcons.filter(icon => icon.slug.includes('rain'));
// Get only animated icons
const animatedIcons = allIcons.filter(icon => icon.animated);
// Group by category
for (const category of manifest.categories) {
console.log(`${category.name}: ${category.icons.length} icons`);
}
// Search by partial slug
function searchIcons(query: string) {
return allIcons.filter(icon =>
icon.slug.includes(query.toLowerCase())
);
}