Icon formats
iconctl writes Iconify JSON, optional individual SVG files and SVG symbol sprites. That is the engineering source. How each app paints an icon is a separate choice. i-brand-arrow-left is a CSS class, usually a mask — not a font.
Catalog
Every paint scheme that has shown up in this product. Mainstream here means what new Web / mini-program UI actually ships in the 2020s, not what iconfont.cn still generates.
| Scheme | Status | Job |
|---|---|---|
| CSS mask | Mainstream | Product UI + mini programs. iconctl default. |
| Inline SVG | Mainstream | Vue/React components, animation, a11y. |
| Iconify runtime | Mainstream | Public sets / apps that already have @iconify/vue. |
| SVG file | Situational | Illustrations, logos, <img>. |
| CSS background | Situational | Multi-color icon as a CSS class. |
| Symbol sprite | Situational | Static <symbol> + <use> collections. |
| Webfont | Legacy | @font-face + PUA. Still common in CN. |
iconctl does not emit webfonts or symbol JS. iconfont Symbol URLs are an input. PNG / native iOS/Android vectors are out of scope.
CSS mask
Mainstream. mask-image plus background-color: currentColor. Same class API as iconfont (i-brand-arrow-left), no font metrics, tree-shaken by UnoCSS or @iconify/tailwind4. Monochrome only. This is the mini program recipe and iconctl’s Web default.
Follows the picker
<span class="i-demo-arrow-left"></span>Inline SVG
Mainstream in component apps. Put <svg> in HTML or a Vue/React SFC — same paint. Full CSS, animation, aria / title. Repeating the same icon in markup is heavy. Mini programs do not consume SVG the way a browser does. The demo gallery inlines JSON body for preview; that is not the production class API.
Follows the picker
<svg viewBox="0 0 24 24" aria-hidden="true">…</svg>Iconify runtime
Mainstream for public collections and apps that already run @iconify/vue (or the web component). JSON in, inline SVG out. Extra JS. Not a mini-program option. iconctl’s Web default still prefers build-time CSS.
Follows the picker
<Icon icon="demo:arrow-left" />SVG file
Situational. <img src="arrow-left.svg">. Easy to cache. Color is baked in, so it will not follow text-primary. Mini programs often reject or rasterize SVG <image>. Use for illustrations and logos, not for a 24px UI set.
Color baked in
<img src="arrow-left.svg" alt="" width="24" height="24">CSS background
Situational. background-image data-URI or file, no mask. Multi-color survives; currentColor does not. Use when the asset is inherently multi-color and you still want a CSS class.
Color baked in
.icon { background: url("arrow-left.svg") center / contain no-repeat; }Symbol sprite
Situational. Enable output.sprite: 'icons.svg' to write a static collection of <symbol> elements, then use <svg><use href="/icons.svg#iconctl-brand-home"></use></svg>. Each symbol preserves its viewport and currentColor; internal references are isolated. Serve external sprites from the same origin, or insert the generated symbols inline. The whole set downloads unless you regenerate per app. Mini programs generally do not support <use>. See SVG sprites for configuration and the supported static format. iconfont Symbol JavaScript injectors remain an input format.
Follows the picker
<svg><use href="#arrow-left" /></svg>Webfont
Legacy, still common via iconfont.cn. @font-face plus a Private Use Area glyph. Tiny HTML, familiar. Whole font ships, FOUT, baseline drift, PUA is not real text. The glyphs below are a demo font only (stroke icons collapsed to fills) — not an iconctl output. Do not generate a webfont from this pipeline. If you already have a Symbol CDN, ingest it and leave the font behind.
Follows the picker
<i class="icon-arrow-left"></i>Scores (1–5)
No grand total. Webfont’s tiny HTML would win a sum; that is not this pipeline. The last row is fit for iconctl apps, not a universal ranking.
| CSS mask | Inline SVG | Iconify runtime | SVG file | CSS background | Symbol | Webfont | |
|---|---|---|---|---|---|---|---|
| Theme / currentColor | 5 | 5 | 5 | 1 | 1 | 5 | 5 |
| Multi-color | 1 | 5 | 5 | 5 | 5 | 2 | 1 |
| Tree-shake | 5 | 4 | 4 | 4 | 5 | 2 | 1 |
| Requests / cache | 5 | 5 | 3 | 2 | 4 | 3 | 2 |
| Alignment | 5 | 5 | 5 | 5 | 5 | 4 | 2 |
| Accessibility | 3 | 5 | 5 | 3 | 3 | 3 | 1 |
| Mini program | 5 | 1 | 1 | 2 | 3 | 1 | 2 |
| Animation | 2 | 5 | 5 | 1 | 1 | 3 | 2 |
| Class-sized DX | 5 | 2 | 4 | 2 | 5 | 3 | 5 |
| Fit for iconctl apps | 5 | 3 | 3 | 2 | 2 | 2 | 1 |
When to use what
| Situation | Use | Avoid |
|---|---|---|
| Vite + UnoCSS / Tailwind | CSS mask, class i-{prefix}-{name} | A new webfont |
| WeChat / Alipay / Douyin | Same class names, CSS mask | <use>, webfont, Iconify Vue |
| Few icons, motion or multi-color SVG | Inline SVG or Iconify runtime | Mask (monochrome), webfont |
| Multi-color logo / illustration | <img>, CSS background, or a raster | Iconify / mask |
| Public set, already on @iconify/vue | Iconify runtime | Re-pipeline through iconctl |
| Legacy iconfont Symbol CDN | { type: 'iconfont' }, then paint with mask | Keep shipping the font |
| Design / QA preview | Inline SVG gallery (iconctl preview / Demo) | Treating preview as the production API |
Extra: the four names people say
People often say “SVG / webfont / symbol / CSS mask”. Those four mix file format, transport, and paint method:
| People say | What they usually mean |
|---|---|
| SVG | Inline <svg>, <img src="*.svg">, or CSS background-image |
| Symbol | SVG sprite <symbol> + <use>, or iconfont.cn Symbol JS |
| CSS mask | mask-image + background-color: currentColor |
| Webfont | @font-face + PUA glyph |
The catalog above is the split this product actually uses.