1. Inline SVG components
Converting each icon into a component (the approach this site automates) gives you full control: icons inherit color through currentColor, accept props such as size and className, and can be animated with CSS or a motion library. Bundlers tree-shake unused components, so you only ship the icons you import.
The trade-off is that the markup becomes part of your JavaScript bundle. For a few dozen small icons that is negligible; for hundreds of complex illustrations it is not.
2. Image tags and CSS backgrounds
<img src="/logo.svg" alt="Company"> is the simplest option and the browser can cache the file. However, the SVG is isolated from your CSS, so you cannot change its color on hover or in dark mode. Use it for logos and illustrations that never change.
3. SVGR and build-time loaders
SVGR (via @svgr/webpack or vite-plugin-svgr) converts .svg imports into components at build time. It is convenient for large icon folders but adds build configuration and can behave differently across bundlers and Turbopack. Converting once with this tool produces the same kind of component as committed source code.
4. SVG sprites and 5. icon libraries
A sprite sheet places many <symbol> elements in one file and references them with <use href="#icon">. It keeps HTML small but complicates server-side rendering. Icon libraries such as Lucide, Heroicons or Phosphor ship pre-built components and are ideal when their style matches your design.
Whichever method you choose, follow these accessibility rules:
- Decorative icons next to text get aria-hidden="true".
- Standalone icons, such as an icon-only button, need an accessible name via aria-label on the button or a <title> inside the SVG.
- Keep a viewBox and size icons in em or rem so they scale with the user's font size.
- Ensure a contrast ratio of at least 3:1 for meaningful icons (WCAG 1.4.11).