Archived. This repo has been folded into the svgin monorepo as
packages/react, alongside a newsvgin-elementpackage and theapps/tryitdemo. Development, issues, and releases (still published to npm assvgin-react) now happen there. This repo is kept read-only for history.
svgin-react fetches an SVG from a URL, or takes raw SVG markup you already have, and renders it as a real, styleable React <svg> element instead of an <img>. Sanitized by default with DOMPurify, so it is safe with SVGs you did not create yourself. Works in the browser and in React Server Components.
import { SvgIn } from 'svgin-react';
<SvgIn src="/icons/alert.svg" width={24} fill="#f00" />Try it live: paste your own SVG markup and see exactly what the sanitizer strips, or click through the RSC, Suspense, Shadow DOM, provider-defaults, and lazy-loading demos.
An <img src="icon.svg"> cannot be styled with CSS: no color changes, no path animation, no targeting inner elements. Inlining the SVG markup fixes that, but inlining raw markup from a URL you do not fully control is a real security risk (an SVG can carry <script> tags, onload handlers, and other ways to run JavaScript). svgin-react fetches the SVG, sanitizes it, and inlines it as a normal React element.
For a static icon set that ships with your app, SVGR is the better fit; it works at build time with zero runtime cost. Reach for svgin-react when the SVG's content is not known until runtime: fetched from a URL, returned by an API, or stored in a database.
npm install svgin-reactThe default sanitizer needs DOMPurify, and on the server it also needs jsdom:
# client component only
npm install dompurify
# server component only
npm install dompurify jsdomIf you always pass your own sanitizeFn, or always use disableSanitization, you do not need either. They are optional peer dependencies, loaded lazily only when the default sanitizer actually runs.
import { SvgIn } from 'svgin-react';
export default function AlertIcon() {
return <SvgIn src="/icons/alert.svg" width={24} fill="#f00" />;
}This one import works in both a client component and a server component. In a Next.js App Router file, add 'use client' at the top if you specifically want the client version.
To force one or the other:
import { SvgIn as SvgInClient } from 'svgin-react/client'; // client component
import { SvgIn as SvgInServer } from 'svgin-react/server'; // server componentWorks with any React 19+ setup: Next.js (Pages Router and App Router), Remix, Vite + React, Create React App, Astro (React islands), and plain Node SSR.
More examples: raw markup, authenticated fetch, accessibility, custom sanitizer, callbacks, lazy loading
Raw markup you already have (from a CMS or API response), no fetch needed:
const { icon } = await cms.getContent(); // icon is a raw SVG string
<SvgIn svg={icon} width={24} />Fetching from an authenticated endpoint:
<SvgIn src="/api/user-uploaded-icon" fetchOptions={{ headers: { Authorization: `Bearer ${token}` } }} />Accessible name and description:
<SvgIn src="/icons/alert.svg" title="Alert" description="Indicates a warning that needs attention" />Custom sanitizer, or skip sanitization for SVGs you trust completely:
<SvgIn src="/icons/alert.svg" sanitizeFn={async (svg) => svg} />
<SvgIn src="/icons/alert.svg" disableSanitization />Error and mount callbacks:
<SvgIn
src="/icons/alert.svg"
onError={(error) => reportToTelemetry(error)}
onMount={(svg) => svg.classList.add('ready')}
/>Deferring the fetch until the icon scrolls near the viewport, for icon-heavy lists:
<SvgIn src="/icons/alert.svg" loading="lazy" />Sharing defaults (className, fallback, onError, etc.) across many icons with <SvgInProvider>, and every other prop, are covered in docs/api.md.
Suspense: <SvgInSuspense /> suspends via React 19's use() instead of managing its own loading/error state
import { SvgInSuspense } from 'svgin-react/suspense';
<Suspense fallback={<IconSkeleton />}>
<SvgInSuspense src="/icons/alert.svg" />
</Suspense>Pair it with a <Suspense> boundary and an error boundary instead of fallback/loadingFallback. It does not automatically retry a failed src, see docs/advanced.md for why and how to force one. Full props in docs/api.md.
Shadow DOM: <SvgInShadow /> encapsulates the SVG's style in a shadow root, in both directions
import { SvgInShadow } from 'svgin-react/shadow';
<SvgInShadow src="/icons/alert.svg" styles="path { fill: red; }" />Page CSS cannot reach in to affect the SVG, and the styles prop's CSS can never leak out onto the page. Use it when a source SVG's inline <style> block needs to stay scoped to that one instance, see docs/advanced.md for the limitation this solves. Full props in docs/api.md.
Preloading and cache utilities: warm the cache ahead of render, invalidate it on demand
import { clearSvgCache, hasCachedSvg, preloadSvg } from 'svgin-react/core';
await preloadSvg('/icons/alert.svg'); // fetches and caches ahead of render
hasCachedSvg('/icons/alert.svg'); // true, no fetch
clearSvgCache('/icons/alert.svg'); // forget one entry (or clearSvgCache() for all)A later <SvgIn src={url} /> for the same URL resolves from the cache instead of fetching again. See docs/api.md for both, and docs/advanced.md for exactly which calls share the cache.
| Entry point | Use for |
|---|---|
svgin-react |
Auto-resolves to the server or client component depending on where it is imported. |
svgin-react/client |
<SvgIn /> and <SvgInProvider>, forced client. |
svgin-react/server |
<SvgIn />, forced server. |
svgin-react/core |
preloadSvg, clearSvgCache, hasCachedSvg, no React component. |
svgin-react/suspense |
<SvgInSuspense />. |
svgin-react/shadow |
<SvgInShadow />. |
svgin-react/all |
Every client + core export behind one import. |
<SvgInSuspense /> and <SvgInShadow /> each have their own entry point so they cost nothing to consumers who do not use them. Full reasoning in docs/api.md.
SVGs are sanitized with DOMPurify by default. Use your own sanitizeFn, or set disableSanitization, only for SVGs you fully trust. Published bundles carry npm provenance attestations. See SECURITY.md to report a vulnerability, and docs/advanced.md for the full threat model.
- docs/api.md: complete props and exports for every component and entry point.
- docs/advanced.md: identity/caching semantics, reference-counted cancellation, Suspense retry behavior, the inline
<style>scoping limitation, and a detailed comparison againstreact-svg,react-inlinesvg, and SVGR.
See CONTRIBUTING.md for the local setup, required checks, and pull request conventions, and docs/maintainers.md for the release process.
Bug reports, feature requests, and pull requests are welcome. See CONTRIBUTING.md to get started, and CODE_OF_CONDUCT.md for how we expect people to treat each other in this project.
Using an AI coding tool (Claude Code, Cursor, Copilot, Gemini, etc.) in this repo? See AGENTS.md for shared agent instructions. See llms.txt for a machine-readable summary of this package.
MIT, see LICENSE.