Skip to main content

Managing SVG Icons in React & Next.js: The Complete Guide

Managing SVG Icons in React & Next.js: The Complete Guide
react#react#nextjs#svg#icons+4 more

Managing SVG Icons in React & Next.js: The Complete Guide

Icons from different sources? Legacy SVGs as images? Learn how to properly manage, organize, and use SVG icons in modern React and Next.js projects.

Mohammad Alhabil

Author

December 15, 2024
6 min read
~1200 words

Managing SVG Icons in React & Next.js: The Complete Guide

How many times have you received a design with icons from a million sources?

You opened the design and found Remix, Feather, Material, and random SVGs all mixed in the same design!

Let's go through the most common problems and how to solve them as developers...

1️⃣ Legacy Project with SVGs Used as Images

Found this everywhere?

<img src="/icons/star.svg" alt="star" />

Want to change the icon color or stroke? Impossible... because you've treated it as an image, losing all SVG advantages.

The Problem

You might think: "I'll copy the SVG code and replace <img> everywhere."

But wait... if the same icon is repeated in 20 places? Copy the code 20 times?!

❌ Code becomes a mess ❌ Hard to maintain ❌ Bundle size increases

The Solution: SVGInject

A lightweight and smart tool that converts any <img src="icon.svg"> inside the DOM to a real <svg>:

<img class="inject-me" src="/icon.svg" />

<script src="https://unpkg.com/@iconfu/svg-inject"></script>
<script>
  SVGInject(document.querySelectorAll('.inject-me'));
</script>

Now you can modify it with CSS!

.inject-me path {
  fill: #3b82f6;
  stroke: #1e40af;
}

⚠️ Note: For large numbers of icons, dynamic DOM manipulation can affect performance. Use it wisely for medium or quick projects.

2️⃣ New Project with Icons from Different Sources

The designer sent you 50 icons from Remix, Material, Feather, and others?

The Smart Solution: IcoMoon

  1. Collect all icons and upload them to icomoon.io
  2. Unify styles and sizes
  3. Rename icons for consistency
  4. Remove unwanted icons
  5. Export as Font or SVG Folder

Benefits

FeatureDescription
🎨 Unified StyleAll icons look consistent
📁 Single SourceOne library for everything
🔧 CustomizableEdit before export
📦 OptimizedOnly include what you need

3️⃣ React/Next.js: SVGs as Components

As React developers, we love everything to be:

  • ✅ JSX
  • ✅ Customizable
  • ✅ Reusable

Using icomoon-react

  1. Export from IcoMoon → Select "Generate SVG"
  2. Find selection.json in the folder
  3. Use with icomoon-react:
npm install icomoon-react
import IcoMoon from 'icomoon-react';
import iconSet from './selection.json';

interface IconProps {
  icon: string;
  size?: number;
  color?: string;
}

export function Icon({ icon, size = 24, color = 'currentColor' }: IconProps) {
  return (
    <IcoMoon
      iconSet={iconSet}
      icon={icon}
      size={size}
      color={color}
    />
  );
}

// Usage
<Icon icon="star" size={24} color="#f59e0b" />
<Icon icon="heart" size={32} color="#ef4444" />

Why This is Better

<img> ApproachComponent Approach
Can't change colorsFull color control
No SSR benefitsSSR compatible
Extra HTTP requestsBundled with JS
Hard to maintainEasy to reuse

4️⃣ Best Icon Libraries in 2025

Starting from scratch? Here are the best options:

Lucide Icons

npm install lucide-react
import { Star, Heart, User } from 'lucide-react';

<Star size={24} color="#f59e0b" />

✅ Very lightweight, excellent React support

Heroicons

npm install @heroicons/react
import { StarIcon } from '@heroicons/react/24/solid';

<StarIcon className="h-6 w-6 text-yellow-500" />

✅ Perfect with Tailwind CSS

Tabler Icons

npm install @tabler/icons-react

✅ Ideal for dashboards

Phosphor Icons

npm install @phosphor-icons/react

✅ Huge library with multiple styles (thin, light, regular, bold, fill, duotone)

Comparison Table

LibraryIconsStylesSizeBest For
Lucide1400+1~1KB eachGeneral use
Heroicons300+2~1KB eachTailwind projects
Tabler4000+1~1KB eachDashboards
Phosphor7000+6~2KB eachVariety needed
Iconoir1300+1~1KB eachModern designs

Tips from Experience

1. Create a Unified Icon Component

// components/Icon.tsx
import * as LucideIcons from 'lucide-react';

type IconName = keyof typeof LucideIcons;

interface IconProps {
  name: IconName;
  size?: number;
  className?: string;
}

export function Icon({ name, size = 24, className }: IconProps) {
  const LucideIcon = LucideIcons[name] as React.ComponentType<any>;
  
  if (!LucideIcon) {
    console.warn(`Icon "${name}" not found`);
    return null;
  }
  
  return <LucideIcon size={size} className={className} />;
}

// Usage
<Icon name="Star" size={24} className="text-yellow-500" />

2. Optimize SVGs Before Using

Use SVGOMG to:

  • Remove unnecessary metadata
  • Optimize paths
  • Reduce file size by 50-80%

3. Consistent Sizing

If icons have inconsistent sizes, organize them in IcoMoon before export:

  • Align
  • Center
  • Resize to consistent viewBox

Quick Decision Guide

SituationSolution
🏚️ Legacy project with <img> SVGsSVGInject
🆕 New project, mixed icon sourcesIcoMoon
⚛️ React/Next.js projecticomoon-react or Lucide
🎨 Starting from scratchPick from recommended libraries

Resources


Interfaces you love, code you understand. 💡

Topics covered

#react#nextjs#svg#icons#icomoon#lucide#frontend#design-system

Found this article helpful?

Share it with your network and help others learn too!

Mohammad Alhabil

Written by Mohammad Alhabil

Frontend Developer & Software Engineer passionate about building beautiful and functional web experiences. I write about React, Next.js, and modern web development.