Design
Using SVG in Next.js/React: Inline vs img vs SVGR Components
Using SVG in Next.js/React: Inline vs <img> vs Components
SVG in Next.js is easy—until you need to change the color, animate paths, or avoid bundling 500 icons into your JS.
There are 3 practical methods that cover 99% of real projects:
Inline SVG (paste SVG markup in JSX)
<img>/ public folder (treat SVG as an asset URL)SVG as React components (SVGR approach)
Let’s break down when to use each, and how to do it without breaking accessibility.
Method 1: Inline SVG (best for theming + animation)
What it looks like
Pros
Best control over fill/stroke
Easy to animate with CSS/Framer Motion
No asset loading requests (it’s in the HTML/JS)
Cons
Can clutter components if overused
Repeating the same SVG in many places can bloat your code
Use inline SVG when: it’s a UI icon you want to theme (currentColor), animate, or tweak per state.
Method 2: Public folder + <img> (best for “just show this SVG”)
Put your SVG in:/public/icons/logo.svg
Then:
Pros
Simple and fast to implement
SVG stays out of your JS bundle
Great for logos/illustrations you don’t need to theme
Cons
You can’t easily change internal SVG colors with CSS (unless you use filters, which is messy)
Limited control for animation of internal paths
Use <img> when: the SVG is basically an image (logo, decorative illustration, badge).
Method 3: next/image for SVG (use carefully)
Next.js Image component extends <img> and can render SVGs too. Next.js+1
Important note: vector images often don’t benefit from Next’s optimization the same way photos do. Next’s legacy Image docs even call out that unoptimized can be useful for SVG. Next.js
Rule:
If you’re using SVG like a normal asset, public +
<img>is usually cleaner.If you already use
Imageeverywhere and want consistency, it can work—just don’t expect big “optimization wins.”
SVGR approach: import SVG as a React component (best for icon systems)
SVGR lets you do:
SVGR has official guidance for configuring Next.js with @svgr/webpack. react-svgr.com
Pros
Perfect for design systems (icons as components)
You can enforce
currentColor, add props, and standardize sizeWorks great with Tailwind/React patterns
Cons
Adds build configuration
Easy to accidentally bundle too many icons into JS if not organized
Theming: fill/stroke the right way
If you want CSS control, use:
fill="currentColor"stroke="currentColor"
Then:
Avoid: hardcoded fills like fill="#000" inside icon SVGs if you want themable icons.
Accessibility: don’t ship “silent icons”
Best practices:
If the SVG is meaningful → ensure it has a label:
Inline:
role="img"+aria-label="..."(or<title>)<img>: always addalt="..."
If the SVG is purely decorative → hide it:
Inline:
aria-hidden="true"<img>:alt=""
Pros/cons summary (fast)
Inline SVG: best control, best theming, best animation
Public +
<img>: best simplicity, best for logos/illustrationsSVGR component: best for icon libraries and scalable UI systems
(Community discussions often land on this exact split: inline/SVGR for icons, public assets for “image-like” SVGs.) Reddit+1
Best practice checklist
✅ Icons you want to color via CSS → Inline or SVGR
✅ Logos and illustrations → Public +
<img>✅ Keep icon SVGs clean:
currentColor, remove inline styles✅ Add accessibility labels
✅ Optimize SVGs before shipping (minify, remove junk)
Internal reading:
