When the same icon appears multiple times on a page, each inline <svg> duplicates the full markup. Sprite sheets replace those duplicates with lightweight <use> references to a shared symbol definition, cutting page weight.
How sprites work
Instead of embedding the full SVG markup for each icon, render a lightweight <svg><use href="#i-lucide-home"></use></svg> reference. At the end of the page, inject a hidden sprite sheet containing one <symbol> per unique icon. The browser resolves the <use> references to the symbols in the sheet.
Setup
import swarmicons "github.com/frostybee/go-swarm-icons"sc := swarmicons.NewSpriteCollector()NewSpriteCollector returns a ready-to-use collector. It is thread-safe and can be shared across concurrent render passes.
Register symbols
Call Register for each icon that should be available in the sprite sheet:
import swarmicons "github.com/frostybee/go-swarm-icons"sc := swarmicons.NewSpriteCollector()icon, _ := manager.Get("lucide:home")sc.Register("i-lucide-home", icon.Content(), "0 0 24 24")icon, _ = manager.Get("lucide:star")sc.Register("i-lucide-star", icon.Content(), "0 0 24 24")The id parameter should follow the "i-{prefix}-{name}" convention.
Generate the sprite sheet
After rendering page HTML with <use href="#i-..."> references, pass the page content to SpriteSheet:
import swarmicons "github.com/frostybee/go-swarm-icons"pageHTML := []byte(`<html><body> <svg><use href="#i-lucide-home"></use></svg> <svg><use href="#i-lucide-star"></use></svg> <svg><use href="#i-lucide-home"></use></svg></body></html>`)sheet := sc.SpriteSheet(pageHTML)SpriteSheet scans the page HTML for <use href="#i-..."> references, matches them against registered symbols, and returns a hidden <svg> element containing one <symbol> per unique referenced icon. Symbols are sorted by ID. Duplicate references produce only one <symbol>.
The returned markup looks like:
<svg aria-hidden="true" style="position:absolute;width:0;height:0;overflow:hidden"> <symbol id="i-lucide-home" viewBox="0 0 24 24">...</symbol> <symbol id="i-lucide-star" viewBox="0 0 24 24">...</symbol></svg>SpriteSheet returns nil if no matching references are found in the page HTML.
ID namespacing
When a symbol is registered, internal SVG references (id, url(#...), href="#...") in the body are automatically suffixed to prevent collisions. For an id of "i-lucide-star", the suffix is "lucide-star" (the id with the "i-" prefix stripped).
For example, a body containing id="g" and url(#g) becomes id="g-lucide-star" and url(#g-lucide-star). This prevents two symbols from sharing the same internal reference IDs.
Reuse across pages
Call Reset() between pages to clear all registered symbols:
sc.Reset()Full example: SSG pipeline
import ( "bytes" "fmt" swarmicons "github.com/frostybee/go-swarm-icons" "github.com/frostybee/go-swarm-icons/lucide")func main() { manager := swarmicons.Default("lucide", lucide.Provider()) sc := swarmicons.NewSpriteCollector() // Register the icons needed for this page for _, name := range []string{"home", "star", "search"} { icon, err := manager.Get(name) if err != nil { continue } _, _, w, h := icon.ViewBox() vb := fmt.Sprintf("0 0 %d %d", w, h) sc.Register(fmt.Sprintf("i-lucide-%s", name), icon.Content(), vb) } // Render page HTML with <use> references var page bytes.Buffer page.WriteString(`<nav>`) page.WriteString(`<svg><use href="#i-lucide-home"></use></svg>`) page.WriteString(`<svg><use href="#i-lucide-search"></use></svg>`) page.WriteString(`</nav>`) // Generate and inject the sprite sheet sheet := sc.SpriteSheet(page.Bytes()) if sheet != nil { page.Write(sheet) } fmt.Println(page.String()) // Reset for the next page sc.Reset()}See also
- Sprite Collector API reference: full
SpriteCollectortype,Register,SpriteSheet, andResetmethods - Performance & Caching: provider selection and caching strategies for SSG pipelines
- Hugo Integration: pre-generate a sprite sheet partial for Hugo sites and themes