Skip to content
Technical

Using SVGs in React and Next.js: Complete Integration Guide

Master SVG integration in React and Next.js applications. Learn import methods, component patterns, optimization, and best practices for modern web development.

Robin MonteiroJanuary 25, 2026Updated: October 10, 202613 min read
Use this article with an AI assistant:
.md
Using SVGs in React and Next.js: Complete Integration Guide
R
Robin Monteiro

Founder of VectoSolve

Self-taught developer, founder and sole developer of VectoSolve since 2024. He builds the conversion engine and the cutting, embroidery and 3D printing exports.

How this article was made: drafted with AI assistance, then edited and fact-checked before publication. About the author

Image vectorizationCutting machine filesEmbroidery filesSVG
Free previewNo signupFull-quality output

Try it on your own file

Free preview, no signup. Drop an image and see the vector before deciding anything.

Key Takeaways

  • React offers four main SVG import methods: image import, inline SVG, SVGR components, and dynamic imports
  • SVGR with Next.js webpack config gives you the best balance of developer experience and runtime control
  • Reusable icon components with TypeScript props (size, color, className) keep your codebase DRY
  • Framer Motion integrates natively with SVG elements for spring-based path and shape animations
  • Always add aria-label or aria-hidden to SVG icons for screen reader accessibility

SVG in Modern React Development

SVGs are essential for modern React applications, offering crisp graphics at any scale. This guide covers every method of using SVGs in React and Next.js projects.


Import Methods

1. Standard Image Import

Simplest approach:

jsx
import logo from './logo.svg';

function Header() {
  return <img src={logo} alt="Logo" className="logo" />;
}

Pros: Simple, familiar
Cons: No styling/manipulation access

2. Inline SVG Components

Full control:

jsx
function Icon() {
  return (
    <svg viewBox="0 0 24 24" className="icon">
      <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5"/>
    </svg>
  );
}

Pros: Full CSS/JS access
Cons: Verbose, can't easily change source

3. SVGR (React Component)

Import as component:

jsx
import { ReactComponent as Logo } from './logo.svg';

function Header() {
  return <Logo className="logo" fill="currentColor" />;
}

Pros: Best of both worlds
Cons: Requires configuration

4. Dynamic Import

For code splitting:

jsx
import dynamic from 'next/dynamic';

const DynamicIcon = dynamic(() => import('./icons/chart.svg'));

function Dashboard() {
  return <DynamicIcon />;
}

Pro Tip: For most React projects, SVGR is the recommended approach. It lets you import SVGs as React components with full prop support while keeping SVG files separate for easy editing in design tools.


SVGR Configuration

Next.js Setup

javascript
// next.config.js
module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });
    return config;
  },
};

With URL Fallback

javascript
// next.config.js
module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      issuer: /\.[jt]sx?$/,
      use: [
        {
          loader: '@svgr/webpack',
          options: {
            svgoConfig: {
              plugins: [{
                name: 'removeViewBox',
                active: false
              }]
            }
          }
        },
        'url-loader'
      ],
    });
    return config;
  },
};

A Full Year of Conversions for $49

Starter Annual: 25 conversions every month, $49 for the whole year. That is about $4.08 a month · Cancel anytime

Get the Annual Deal

Component Patterns

Reusable Icon Component

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

export function Icon({ name, size = 24, color = 'currentColor', className }: IconProps) {
  return (
    <svg
      width={size}
      height={size}
      fill={color}
      className={className}
    >
      <use href={`/sprites.svg#${name}`} />
    </svg>
  );
}

// Usage
<Icon name="search" size={20} color="#333" />

Icon Library Component

jsx
// icons/index.tsx
import { FC, SVGProps } from 'react';

interface IconComponentProps extends SVGProps<SVGSVGElement> {
  size?: number;
}

const createIcon = (path: string): FC<IconComponentProps> => {
  return function IconComponent({ size = 24, ...props }) {
    return (
      <svg
        viewBox="0 0 24 24"
        width={size}
        height={size}
        fill="currentColor"
        {...props}
      >
        <path d={path} />
      </svg>
    );
  };
};

export const SearchIcon = createIcon('M15.5 14h-.79l-.28-.27...');
export const HomeIcon = createIcon('M10 20v-6h4v6h5v-8h3L12...');

Styling SVGs in React

CSS Styling

css
/* styles.css */
.icon {
  width: 24px;
  height: 24px;
  fill: currentColor;
  transition: fill 0.2s;
}

.icon:hover {
  fill: #0066cc;
}

Styled Components

jsx
import styled from 'styled-components';

const StyledSvg = styled.svg`
  width: ${props => props.size || 24}px;
  height: ${props => props.size || 24}px;
  fill: ${props => props.color || 'currentColor'};
  transition: fill 0.2s;

  &:hover {
    fill: ${props => props.hoverColor || props.color};
  }
`;

Tailwind CSS

jsx
<svg
  className="w-6 h-6 fill-current text-gray-600 hover:text-blue-500 transition-colors"
  viewBox="0 0 24 24"
>
  <path d="..."/>
</svg>

Animation in React

CSS Animation

jsx
function LoadingSpinner() {
  return (
    <svg className="animate-spin" viewBox="0 0 24 24">
      <circle
        className="opacity-25"
        cx="12" cy="12" r="10"
        stroke="currentColor" strokeWidth="4"
      />
      <path
        className="opacity-75"
        fill="currentColor"
        d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
      />
    </svg>
  );
}

Framer Motion

jsx
import { motion } from 'framer-motion';

function AnimatedIcon() {
  return (
    <motion.svg
      viewBox="0 0 24 24"
      initial={{ scale: 0 }}
      animate={{ scale: 1 }}
      transition={{ type: 'spring' }}
    >
      <motion.path
        d="M12 2L2 22h20L12 2z"
        initial={{ pathLength: 0 }}
        animate={{ pathLength: 1 }}
      />
    </motion.svg>
  );
}

Free SVG Tools for Crafters

Design Checker · Color Separator · Mat Preview · Offset Generator · Text to SVG

Check Your SVG Free

Optimization Strategies

Build-Time Optimization

javascript
// svgo.config.js
module.exports = {
  plugins: [
    'preset-default',
    'removeDimensions',
    { name: 'removeViewBox', active: false },
    { name: 'prefixIds', params: { prefix: 'svg-' } }
  ]
};

Code Splitting

jsx
// Lazy load heavy icons
const ChartIcon = lazy(() => import('./icons/Chart'));

function Dashboard() {
  return (
    <Suspense fallback={<div className="icon-placeholder" />}>
      <ChartIcon />
    </Suspense>
  );
}

Never remove viewBox during SVGO optimization. Without viewBox, SVGs lose their ability to scale responsively. Always set removeViewBox: false in your SVGO config.


Accessibility in React

Accessible Icon Pattern

jsx
interface AccessibleIconProps {
  label: string;
  children: React.ReactNode;
}

function AccessibleIcon({ label, children }: AccessibleIconProps) {
  return (
    <span role="img" aria-label={label}>
      {children}
    </span>
  );
}

// Usage
<AccessibleIcon label="Search">
  <SearchIcon />
</AccessibleIcon>

Icon Button

jsx
function IconButton({ icon: Icon, label, onClick }) {
  return (
    <button
      onClick={onClick}
      aria-label={label}
      className="icon-button"
    >
      <Icon aria-hidden="true" />
    </button>
  );
}

Vectosolve Integration

Workflow

Using Vectosolve with React:

  1. Convert images to SVG
  2. Download clean output
  3. Import into React project
  4. Use preferred method above

Clean Output Benefits

Vectosolve SVGs are:

  • Optimized for web use
  • Ready for SVGR import
  • Clean path data
  • Easy to style

A Full Year of Conversions for $49

Starter Annual: 25 conversions every month, $49 for the whole year. That is about $4.08 a month · Cancel anytime

Get the Annual Deal

Conclusion

React offers multiple ways to work with SVGs, each with trade-offs. Choose the approach that fits your needs: simple image imports for basic use, SVGR for full control, or component patterns for icon systems. Start with clean, optimized SVGs from Vectosolve for the best results.

Get React-Ready SVGs


SVG Import MethodRuntime ControlBundle ImpactBest For
<img src> importNoneSeparate HTTP requestStatic decorative images
Inline JSX SVGFull (props, events, CSS)Increases component sizeInteractive icons, animations
SVGR componentFull (typed props, tree-shaking)Per-component chunkIcon libraries, design systems
Dynamic importFull (after load)Code-split, lazy loadedBelow-fold or conditional SVGs
Tags:
React
Next.js
SVG
Components
Web Development
Share:

Try Vectosolve Now

Convert your images to high-quality SVG vectors with AI

AI-Powered Vectorization

Ready to vectorize your images?

Convert your PNG, JPG, and other images to high-quality, scalable SVG vectors in seconds.