How to svg sprite browser usage reference: the use element guide
- Step 1Reference a symbol from an inline sprite — After pasting the builder's
sprite.svgonce near the top of<body>, use<svg width="24" height="24" aria-hidden="true"><use href="#icon-cart"/></svg>. The fragment (#icon-cart) must exactly match a<symbol id>in the sprite — check capitalisation and the file-name stem. - Step 2Reference a symbol from an external sprite — Host the file and use the full URL plus fragment:
<use href="/sprite.svg#icon-cart"/>. Same-origin is simplest. Expect that your page CSS won't reach the symbol — design those icons to be self-coloured, or inline the sprite if you need CSS fills. - Step 3Use href, not xlink:href — Write
hrefalone.xlink:hrefis deprecated since SVG 2 and unnecessary in every current browser. Only add it as a fallback if you must support pre-2020 engines — and in 2026 that's effectively never. - Step 4Label meaningful icons — For decorative icons set
aria-hidden="true"on the outer<svg>. For meaningful icons setrole="img"andaria-label="…". The builder does not add<title>or ARIA to symbols, so this is always your responsibility at the use site. - Step 5Always size the outer svg — Set
width/height(or CSS dimensions) on the<svg>wrapping<use>. Without a size the icon renders at 0×0 and vanishes. The symbol'sviewBoxdefines its aspect ratio; the wrapper defines its rendered size. - Step 6Fix cross-origin external sprites with CORS — If the external sprite lives on a different origin (e.g. a CDN subdomain), serve it with
Access-Control-Allow-Originand load it over the same scheme (HTTPS page → HTTPS sprite). Otherwise some browsers refuse to render the referenced symbols.
Inline vs external <use> behaviour
The single biggest source of confusion. The builder outputs inline; the external column is when you self-host that file.
| Concern | Inline sprite (same document) | External sprite (separate URL) |
|---|---|---|
| Reference | <use href="#icon-cart"/> | <use href="/sprite.svg#icon-cart"/> |
| Network | None (already in DOM) | One fetch for the sprite file |
| CORS | N/A | Cross-origin needs Access-Control-Allow-Origin |
| Page CSS reaches symbol | Yes — currentColor + fills work | No — symbol is in a separate scope |
| Scheme/protocol | Inherits the page | Must match (HTTPS page → HTTPS sprite) |
Attribute and accessibility reference
What to write, and what the builder does and does not provide.
| Item | Correct usage | Builder provides it? |
|---|---|---|
href | Always — <use href="#id"/> | You write it (a usage comment is hinted in output) |
xlink:href | Avoid — deprecated; legacy fallback only | No |
| Decorative ARIA | aria-hidden="true" on outer <svg> | No — add it yourself |
| Meaningful ARIA | role="img" + aria-label on outer <svg> | No — add it yourself |
<title> in symbol | Optional accessible name inside <symbol> | No — not injected |
width/height | Required on outer <svg> to size the icon | No — symbol only carries viewBox |
Cookbook
Copy-paste patterns matched to the builder's real symbol IDs (filename-based, e.g. icon-cart).
Decorative icon (most common)
Icon is purely visual; its meaning is carried by adjacent text. Hide it from assistive tech.
<button> <svg width="20" height="20" aria-hidden="true"><use href="#icon-trash"/></svg> <span>Delete</span> </button>
Meaningful icon (icon IS the label)
Icon-only control with no visible text. It needs an accessible name the builder won't add for you.
<button aria-label="Delete item">
<svg width="20" height="20" role="img" aria-hidden="true">
<use href="#icon-trash"/>
</svg>
</button>
<!-- label on the button (preferred) so the control is named once -->External sprite reference with currentColor caveat
Same file, hosted. Note CSS color won't reach the symbol — the icon keeps its baked-in fill.
/* this does NOT recolour an EXTERNAL symbol */
.toolbar svg { color: #2563eb; }
<svg width="24" height="24" aria-hidden="true">
<use href="https://cdn.example.com/sprite.svg#icon-cart"/>
</svg>
<!-- cross-origin: the CDN must send Access-Control-Allow-Origin -->currentColor recolouring — inline only
With the sprite inline and the icon's fill set to currentColor, CSS color recolours it. This only works in the same document.
/* inline sprite in the page; symbol path uses fill="currentColor" */
.icon-danger { color: #dc2626; }
<svg class="icon-danger" width="20" height="20" aria-hidden="true">
<use href="#icon-alert"/>
</svg>
<!-- renders red because color cascades into currentColor -->Sizing with em to track text
Using 1em for the wrapper makes the icon scale with surrounding font-size, mimicking icon-font behaviour.
<p style="font-size:18px">
Search
<svg width="1em" height="1em" aria-hidden="true">
<use href="#icon-search"/>
</svg>
</p>
<!-- icon renders ~18px tall, tracking the paragraph text -->Edge cases and what actually happens
Icon renders blank / invisible
Sizing or ID missTwo usual causes: the outer <svg> has no width/height so the icon is 0×0, or the href fragment doesn't match any <symbol id> (capitalisation or wrong file-name stem). Open the sprite's View SVG source, copy the exact id, and set explicit dimensions on the wrapper.
External sprite ignores CSS color / currentColor
Cross-document scopeSymbols referenced from an external URL live in a separate scope your page CSS can't reach, so color/currentColor and fill rules don't apply. Inline the sprite to get CSS control, or bake colours into the icons. This is standard <use>-across-documents behaviour, not a bug.
Cross-origin external sprite won't render
CORS failureIf the sprite is on a different origin without Access-Control-Allow-Origin, the browser refuses to render its symbols. Add the CORS header on the sprite response, or host the sprite same-origin. Same-origin inline sprites avoid the issue entirely.
Mixed content: HTTP sprite on an HTTPS page
Blocked / failsAn HTTPS page referencing an http:// sprite is mixed content and browsers block it, leaving the icon blank. Always serve the sprite over HTTPS (or same-origin, which inherits the page scheme). This is most common when copy-pasting an old absolute URL.
Duplicate symbol IDs across two inlined sprites
ID collisionIf two inlined sprites both contain id="icon-cart", <use href="#icon-cart"> resolves to the first and ignores the rest. Rebuild one with a distinct spritePrefix (e.g. ui vs brand) so every symbol ID is unique within the document.
Symbol with no viewBox renders at the wrong size
Missing viewBoxThe builder copies a viewBox only if the source had one. A <symbol> without viewBox won't establish its own coordinate system, so it ignores the wrapper size and may overflow or clip. Fix the source with svg-viewbox-fixer before combining.
Using xlink:href because a tutorial said so
DeprecatedOld tutorials and IE polyfills pushed xlink:href. It's deprecated in SVG 2 and unnecessary in current browsers. Use plain href. Carrying both attributes just adds noise; drop xlink:href unless you genuinely target pre-2020 engines.
Screen reader announces nothing for an icon-only button
Missing labelThe builder adds no ARIA, and SVG icons are silent by default — so an icon-only control with no aria-label is unlabelled. Add aria-label to the button (preferred) or role="img" + aria-label to the <svg>. Decorative icons should instead carry aria-hidden="true".
Trying to use a sprite inside an email
UnsupportedEmail clients strip <svg> and <use>. A sprite simply won't render in email. Use rasterised PNG icons for email; reserve the sprite for the web. This is a client-capability limit, not a sprite defect.
Symbol appears but styling inside it can't be reached
Shadow scopeEven inline, <use> clones the symbol into a shadow tree, so descendant CSS selectors targeting internal elements may not apply across the boundary. currentColor and inherited properties cross fine; arbitrary per-path selectors often don't. Use currentColor or CSS variables for styling that must cross.
Frequently asked questions
Should I use href or xlink:href?
Use plain href. xlink:href is deprecated since SVG 2 and every current browser supports href for <use>. Only add xlink:href as a fallback for pre-2020 engines, which in 2026 is effectively never. Don't carry both unless you have a documented legacy requirement.
Why don't my CSS fills apply to icons from an external sprite?
Symbols referenced from an external URL render in a separate document scope your page CSS can't reach. To style fills, inline the sprite (the Sprite Builder's native output) so it's in the same document, and use currentColor or CSS variables. External references are best for icons that don't need CSS recolouring.
What fragment do I reference — what are the IDs?
The builder's web output makes IDs from file names: cart.svg with prefix icon becomes #icon-cart. The runner/API path instead numbers them #icon-1, #icon-2. Always confirm the exact id in the sprite source before writing the href — a mismatch renders blank.
Why is my icon blank?
Most often: no width/height on the outer <svg> (icon is 0×0), an href that doesn't match a <symbol id>, a cross-origin external sprite missing CORS headers, or mixed content (HTTP sprite on an HTTPS page). Check those four in order — they cover nearly every blank-icon case.
Do I need CORS headers for my sprite?
Only for cross-origin external sprites. If the sprite is on a different origin than the page, serve it with Access-Control-Allow-Origin or the browser won't render its symbols. Same-origin external sprites and inline sprites need no CORS configuration.
How do I make sprite icons accessible?
The builder adds no ARIA, so you add it at the use site. Decorative icons: aria-hidden="true" on the outer <svg>. Meaningful icons: role="img" + aria-label, or put the label on the surrounding control (e.g. aria-label on the button). Optionally add a <title> inside the symbol yourself.
Why does my icon render at the wrong size?
Either the outer <svg> has no size (set width/height or CSS), or the symbol has no viewBox so it can't scale to the wrapper. The builder copies a viewBox only when the source had one — fix missing viewBoxes at the source with svg-viewbox-fixer before combining.
Can I style individual parts of a symbol with CSS?
Only partially. <use> clones the symbol into a shadow tree; inherited properties like currentColor cross the boundary, but arbitrary descendant selectors often don't. For per-part styling, set the icon's fills to currentColor or expose them as CSS variables with svg-css-variable-injector, then override the variables.
Can I use SVG sprites in an email?
No. Email clients strip <svg> and <use> entirely. For email use rasterised PNG icons. Sprites are a web-only technique — this is a client limitation, not something the builder or your markup can work around.
Why does my icon appear in Chrome but blank in Firefox?
Usually a cross-origin external sprite without CORS, or a protocol mismatch (HTTP sprite on an HTTPS page). Browsers vary in how strictly they enforce these, so an icon can work in one and fail in another. Serve the sprite same-origin (or with CORS) over HTTPS, and the inconsistency disappears.
How should I size icons to match text?
Set the outer <svg> to width:1em; height:1em. The icon then scales with the surrounding font-size, reproducing the way icon-font glyphs sized themselves. For fixed sizes, use pixel dimensions. Never omit dimensions — an unsized <use> collapses to 0×0.
Does the builder generate the use markup or accessibility for me?
It emits a commented usage hint per symbol (e.g. <!-- <svg><use href="#icon-cart"/></svg> -->) in the browser output, but you write the real markup — adding width/height and ARIA. It does not inject <title> or role/aria-* into symbols. Accessibility belongs to the context where the icon is used, not the shared definition.
Privacy first
Every JAD SVG tool runs entirely in your browser using the DOM API and Canvas. Your SVG files never leave your device — verified by zero outbound network requests during processing.