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-web
npm install lottie-web
yarn add lottie-web
pnpm 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

RendererProsCons
canvasBetter performance, lower memoryNo CSS styling of internals
svgCSS accessible, crisp at any zoomSlower 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.

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-native
npm install lottie-react-native
yarn add lottie-react-native
pnpm 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())
    );
}