How to Use SVG Icons: A Practical Guide for Modern Web Apps
Learn the most reliable ways to use SVG icons in Astro, React, and plain HTML. Includes accessibility, performance, and production-ready examples.
SVG icons are the default choice for modern interfaces because they stay sharp at any size, are easy to style, and can be optimized aggressively.
Why teams standardize on SVG icons
- Crisp on every display — no blur on high-DPI screens
- Easy to theme — use
currentColorand inherit from text color - Fast to ship — tiny files once optimized
- Flexible — inline, component-based, or CDN-hosted
Pick one icon style per product surface. Mixing many packs on one screen makes interfaces feel inconsistent.
1) Inline SVG (best control)
Inline SVG gives full control over paths, fill, stroke, and animation.
<button class="icon-button" aria-label="Open menu">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="20"
height="20"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<line x1="3" y1="6" x2="21" y2="6" />
<line x1="3" y1="12" x2="21" y2="12" />
<line x1="3" y1="18" x2="21" y2="18" />
</svg>
</button>
.icon-button {
color: #334155;
}
.icon-button:hover {
color: #2563eb;
}
2) Referencing SVG with img (simple and cacheable)
Use this when you only need display and don’t need CSS control of paths.
<img src="/icons/logo.svg" alt="Company logo" width="24" height="24" />
If you use img, you cannot change stroke/fill colors via normal CSS selectors inside the SVG.
3) React component icons (best developer experience)
For React and Astro islands, component icons are usually the fastest workflow.
import { Home, Search } from 'lucide-react';
export function Toolbar() {
return (
<nav className="flex items-center gap-3">
<button aria-label="Home">
<Home className="h-5 w-5" />
</button>
<button aria-label="Search">
<Search className="h-5 w-5" />
</button>
</nav>
);
}
4) CDN-hosted icon URLs (quick prototyping)
For broad icon catalogs, fetch SVG directly from your icon API:
<img
src="https://api.iconify.design/lucide/home.svg"
alt="Home icon"
width="24"
height="24"
/>
This is great for prototypes and content pages, but for critical UI controls use local bundles or pre-resolved components where possible.
Accessibility checklist
- Decorative icon: add
aria-hidden="true" - Interactive icon button: add a meaningful
aria-label - Avoid relying on icon-only meaning when critical; pair with text
<button aria-label="Delete file" className="inline-flex items-center gap-2">
<Trash2 className="h-4 w-4" aria-hidden="true" />
<span>Delete</span>
</button>
Performance checklist
- Run SVGs through SVGO before shipping
- Reuse the same icon set per surface
- Prefer CSS
transformandopacityfor icon animations - Avoid very complex path-heavy icons in dense lists
Choose icon size fast
Use this helper to pick practical icon size tokens for web and mobile UI.
Icon Size Advisor
Pick your UI context and get a practical icon size recommendation.
Popular icon styles
Recommended approach for this project
For All SVG Icons content and examples:
- Use fenced code blocks in MDX for built-in syntax highlighting
- Use
IconGridfor visual icon previews in blogs - Keep
IconPreviewoptional for single-icon demos only
That combination keeps blog content fast, readable, and easier to maintain over time.