An icon library, an arrow, a star, a heart, defined once and then called at ten different spots in an interface, each at its own size: that is exactly what <symbol> allows, a drawing blueprint that never renders by itself.
Without it, every repeated icon would mean copying and pasting the same complex outline as many times as it appears on screen, with all the file weight and copy-paste errors that brings.
Definition
<symbol> defines a reusable shape or group of shapes, identified by an id, but never renders it directly on screen. A <symbol> placed inside an SVG shows nothing until some other element references it: it is a blueprint on standby, not a drawing.
Main attributes
| Attribute | Role |
|---|---|
id | Identifier used by <use> to call this symbol |
viewBox | Internal coordinate system, independent from the document calling it |
preserveAspectRatio | Controls how the symbol adapts when its proportions change |
A symbol's viewBox is what lets it adapt to any display size without distortion, exactly like the one on a regular SVG <image>.
Concrete rendering example
A star symbol defined once, then called three times at different sizes and colours.
<svg viewBox="0 0 300 100" xmlns="http://www.w3.org/2000/svg">
<symbol id="star" viewBox="0 0 24 24">
<path
d="M12 2 L15 9 L22 9 L16.5 13.5 L18.5 21 L12 16.5 L5.5 21 L7.5 13.5 L2 9 L9 9 Z"
fill="currentColor"
/>
</symbol>
<use href="#star" x="10" y="10" width="40" height="40" color="#f59e0b" />
<use href="#star" x="90" y="20" width="24" height="24" color="#f59e0b" />
<use href="#star" x="160" y="30" width="16" height="16" color="#f59e0b" />
</svg>The <symbol> draws nothing until it is called: it is <use> that triggers the rendering, each time with its own size and colour.
Difference with the HTML <template>
<symbol> behaves like the HTML <template> element: both define content that stays completely inert until something clones or references it. An HTML <template> has to be duplicated with JavaScript before it can appear in the page; an SVG <symbol> simply renders by being referenced with <use>, with no code copy and no script needed.
Classic trap: forgetting that a <symbol>'s content is never directly visible, even when everything looks correctly written. A beginner who drops a symbol into their SVG and then wonders why nothing shows up has simply forgotten to add the <use> that triggers it.
Real-world use case
SVG icon libraries, for menus, buttons or badges, almost all rely on this principle: a single file gathers dozens of symbols, each one called on demand with <use> across the interface, without duplicating each icon's outline. This split also cuts down file weight: instead of repeating an outline made of hundreds of points every time the icon appears, the document stores it only once, and the browser reuses the same definition in memory for every copy shown on screen.
Frequently asked questions
Yes, a <symbol> behaves like a small group: it can gather several shapes, <path> elements, circles or blocks of text, all of which render together every time the symbol is called.
use?No, a <symbol> stays invisible under all circumstances until a <use> references it. That is a key difference from a plain group, which renders directly as soon as it appears in the document.
Often right at the top of the SVG, sometimes inside a hidden block at the top of the HTML page with a "display: none" style on the enclosing SVG, so the browser loads them without ever drawing them directly. Some projects go further and gather every symbol into a single external file, a true sprite sheet, loaded once and cached by the browser instead of being downloaded again on every page of the site.