Icon formats
iconctl writes Iconify JSON (and optional SVG files). 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 | Legacy | <use> / iconfont Symbol JS. Still common in CN. |
| 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
Legacy, still common in Chinese iconfont workflows. One file of <symbol id>, then <svg><use href="#id"></use></svg>. iconfont “Symbol” is this plus a JS injector. currentColor works on the host SVG. External sprites hit CORS; the whole set downloads unless you regenerate per app. <use> is generally missing in WeChat / Alipay / Douyin. iconctl will not write this.
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.