Skip to main content

Scalable Vector Graphics (SVG)

SVGs scale without pixelation. They also bloat your bundle if you inline them carelessly.

The strategy depends on how many SVGs you have and whether they need runtime manipulation.

SVG Strategies

StrategyHowBundle ImpactRuntime ControlBest For
Inline SVGPaste SVG markup in JSXAdds to component sizeFull (props, CSS, animation)Icons needing color/state changes
SVGR componentBuild-time transform to React componentTree-shakeableFullIcon libraries, design systems
SVG spriteSingle file, reference by useOne HTTP requestLimited (CSS only)Large icon sets, static icons
img tag<img src="icon.svg" />Separate HTTP requestNoneDecorative, non-interactive
CSS backgroundbackground-image: url(...)Cached by browserNonePatterns, decorative backgrounds

Decision Rule

QuestionIf YesIf No
Need to change color/state?SVGR or inlineimg tag or sprite
More than 20 icons?Sprite or SVGR with tree-shakingInline is fine
Is it decorative only?img tag or CSS backgroundNeeds inline or SVGR
Part of a design system?SVGRCase by case

Key Patterns

PatternWhy
Remove hardcoded fill/strokeLet CSS or props control color
Set viewBox, remove width/heightScale responsively
Use currentColor for fillsInherits text color automatically
Optimize with SVGOStrip editor metadata, reduce file size

Context

  • Components — SVGs are components when interactive
  • Tailwind — Tailwind classes control SVG styling
  • Performance — SVG strategy directly affects bundle size
  • Design — Icon systems and visual consistency

Questions

When does an SVG sprite outperform individual SVGR components?

  • What is the bundle cost of inlining vs. importing 50 SVG icons?
  • How do you maintain SVG accessibility (role, title, desc) across a design system?
  • When should you use a font icon set instead of SVGs?