A practical, opinionated guide to integrating IconFlow SVG icons into your product — covering design system architecture, accessibility compliance, and performance optimization. Written by our design engineering team after shipping icons to 2,400+ teams.
Icons are not decorative afterthoughts — they are core tokens in your design system. Treat them with the same rigor as color palettes, type scales, and spacing grids. Here is how leading teams structure icon usage across products.
Icon Naming Conventions
Adopt a consistent naming pattern across your system. IconFlow uses kebab-case with semantic names: arrow-narrow-up, shield-check, folder-open. Avoid names like icon-42 or button-icon. When creating custom icons, follow the pattern <object>-<modifier>. This makes autocomplete in your component library predictable and reduces cognitive load for developers hunting for the right icon.
| Pattern | Example | Use Case |
|---|---|---|
<object> |
search |
Simple, unmodified icon |
<object>-<modifier> |
search-plus |
Object with action or state |
<object>-<direction> |
arrow-left |
Directional variants |
<object>-<size> |
image-large |
Size-differentiated variants |
Icons convey meaning. When they are the only visual cue for an action or state, screen reader users are left in the dark. Accessibility is not a checkbox — it is a design requirement. Follow these patterns to ensure every user can understand and interact with your icons.
aria-hidden="true" and remove any <title> element. This prevents screen readers from announcing redundant information like "home, link" when the button text already says "Go to Home".<!-- Decorative: icon reinforces visible label -->
<button class="btn">
<svg aria-hidden="true" focusable="false">
<use href="#icon-home"/>
</svg>
Home
</button>
<title> inside the SVG paired with role="img", or wrap the icon in a button with visible or visually-hidden text. Never rely on alt attributes on SVGs served as <img> unless you control the server response.<!-- Functional: icon carries all the meaning -->
<button aria-label="Close dialog">
<svg role="img" aria-hidden="false">
<title>Close dialog</title>
<use href="#icon-x"/>
</svg>
</button>
Icon-Only Navigation: A Common Pitfall
Bottom navigation bars and toolbars often use icon-only buttons. This is where accessibility breaks down most frequently. Every icon-only button must have an aria-label that describes the action, not the visual. Label a magnifying glass icon "Search" not "Magnifying glass". Label a house icon "Home" not "House". The label should describe what happens when the user activates it.
SVG icons should add zero perceptible latency to your page. When implemented correctly, an icon library loads in under 50ms and paints before the first frame. Here is how to achieve that.
<svg> sprite file served via HTTP/2 multiplexing. Reference icons with <use href="#icon-name">. This eliminates N HTTP requests for N icons. IconFlow's sprite pack for the full 12,800-icon library is 14.2kb gzipped. For most projects, a curated subset of 50–100 icons weighs under 2kb gzipped.cleanAttrs, removeDimensions, removeUselessDefs, and minifyStyles plugins. IconFlow ships pre-optimized icons — a typical icon goes from 1.8kb (raw Figma export) to 420 bytes (optimized). That is a 77% reduction per icon.Icon Loading Strategies Compared
Choose the right strategy based on your application's icon count and rendering requirements. There is no single best approach — only the best approach for your constraints.
| Strategy | Bundle Size | HTTP Requests | Best For |
|---|---|---|---|
| SVG Sprite (external) | 2–14kb gzipped | 1 | Large icon sets, SPAs, design systems |
| Inlined SVG | 0 (part of HTML) | 0 | Critical icons, small pages, static sites |
| Icon Font | 8–20kb | 1–2 | Legacy projects, dynamic icon switching |
| Individual SVG files | ~500 bytes each | N (one per icon) | Not recommended for production |
Code-Splitting Your Icon Pack
If you are using IconFlow with a bundler like Vite or Webpack, you can tree-shake icons to include only what your application uses. Import icons individually from the npm package:
// ✅ Tree-shakeable — only used icons enter your bundle
import { IconSearch, IconHome, IconSettings } from '@iconflow/icons';
// ❌ Not tree-shakeable — entire library loaded
import * as AllIcons from '@iconflow/icons';
For a typical SaaS dashboard using 67 icons, tree-shaking reduces the icon payload from 14.2kb to 1.1kb — a 92% reduction. Combine this with gzip or Brotli compression on your CDN, and the actual transfer size drops to approximately 480 bytes for your entire icon set.
<use href="#icon-" references, then generates a minimal sprite containing only those icons. This automated approach guarantees your production sprite never includes unused icons. Our team uses this pipeline and maintains a sprite under 1.5kb for our marketing site despite the full library containing 12,800 icons.
Start with one section. Audit your current icon implementation against the accessibility checklist, then measure your icon payload and optimize. Small improvements compound — teams that follow all three sections typically see faster pages, fewer support tickets, and more consistent interfaces.
- Every icon-only button has an
aria-label - Decorative icons have
aria-hidden="true" - Stroke color meets 3:1 contrast minimum
- Icon state changes (active, disabled) are announced
- No icon relies on color alone to convey meaning
- Run
npx svgo --folder ./iconsto optimize all SVGs - Check Lighthouse "Eliminate render-blocking resources"
- Measure icon payload with Chrome DevTools Network panel
- Verify sprite loads in under 50ms with WebPageTest
- Confirm zero icon requests in Lighthouse audit