From harness-claude
Guides icon design with pixel grid alignment, stroke weight consistency, optical sizing, metaphor clarity, icon families, and filled vs outlined states. Use for building, auditing, or selecting UI icon sets.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Icon design principles — optical sizing, stroke consistency, pixel grid alignment, metaphor clarity, icon families, filled vs outlined states, and icon as a systematic visual language
Designs scalable UI icons using grid systems, optical alignment, stroke consistency, metaphor selection, and SVG optimization for coherent icon sets.
Creates icon system specs with grid, sizing, naming conventions, categories, SVG/Figma delivery, accessibility rules, and maintenance best practices.
Provides Iconsax icon library with Linear, Bold, and Two-tone styles plus AI generation for premium UI/UX icons. Use for navigation menus, toolbars, action buttons, and custom concepts.
Share bugs, ideas, or general feedback.
Icon design principles — optical sizing, stroke consistency, pixel grid alignment, metaphor clarity, icon families, filled vs outlined states, and icon as a systematic visual language
Design to the pixel grid, not the mathematical center. Every icon canvas has a pixel grid — typically 16x16, 20x20, or 24x24. Align all straight edges to full pixel boundaries. Diagonal and curved lines are exempt from grid snapping but should start and end on pixel intersections. Decision procedure: at your target render size, export the icon at 1x and zoom to 800%. If any horizontal or vertical edge falls between pixels, the renderer will anti-alias it — producing a blurry 2px line where you intended a crisp 1px line. Apple's SF Symbols enforce a 1px grid at each of 3 scales (small, medium, large) to guarantee sharpness on retina and non-retina displays alike.
Establish a stroke weight system and never deviate. Stroke weight is the single most visible consistency signal in an icon family. Material Symbols uses a stroke weight axis from 100 to 700 in 100-unit increments. For a typical product icon set at 24px canvas, common stroke weights are:
Decision procedure: pick ONE stroke weight for your entire icon set. If you need weight variation, define explicit weight tiers (light/regular/bold) with specific pixel values. Never approximate — a 1.75px stroke next to a 2px stroke is visibly inconsistent.
Apply optical sizing, not linear scaling. A 16px icon is not a scaled-down 24px icon. At smaller sizes, details collapse: 1px gaps disappear, thin strokes become invisible, interior detail becomes noise. Optical sizing means redesigning the icon for each size tier. Apple's SF Symbols provide 3 optical scales:
GitHub's Octicons ship two discrete sizes — 16px and 24px — with different path geometry for each. The 16px repo icon has 2 simplified elements; the 24px version has 4 detailed elements. Concrete rule: if your icon set supports sizes below 20px, you need a separate optical variant with at minimum 0.5px thicker strokes and 30-50% fewer interior details.
Choose icon metaphors that survive the 5-second test. Show the icon to someone unfamiliar with your product for 5 seconds. If they cannot identify the referent or action, the metaphor is too abstract. Proven metaphors:
When no established metaphor exists, prefer a concrete noun over an abstract concept. "Cloud with arrow" for upload is more scannable than an abstract upward-pointing triangle.
Define the filled vs. outlined decision systematically. Do not mix arbitrarily. The two styles carry different visual weight and semantic implications:
Google's Material Symbols uses filled for selected/active states and outlined for unselected/inactive states — a toggle pattern. iOS Tab Bar follows the same convention: outlined icons for unselected tabs, filled for the active tab. Decision procedure: use outlined as the default state. Switch to filled for selected, active, or emphasized states. Never use filled and outlined versions of the same icon at the same hierarchy level — the weight difference creates unintended emphasis.
Maintain consistent optical weight across shape families. A circle, a square, and a triangle at the same bounding box size do not appear the same size. Circles and triangles look smaller than squares of identical dimensions — this is a well-documented optical illusion. Compensate:
Material Design's icon grid includes a "trim area" (the full canvas) and a "live area" (where content sits, slightly inset). The live area is 20x20 inside a 24x24 canvas. But circular icons like the info circle occupy 22x22 — exceeding the live area — to optically match the weight of square icons that sit within 20x20.
Build icon families, not icon collections. A family shares DNA: consistent stroke weight, consistent corner radius, consistent level of detail, consistent metaphor style (outline realism vs. geometric abstraction). When adding a new icon to an existing family, match these attributes before matching the concept. A geometrically perfect new icon that has 1px rounded corners in a set using 2px rounded corners will feel foreign regardless of how well-drawn it is. Airbnb's icon system enforces: 2px stroke, 2px corner radius, 24px canvas, no fills, single-color rendering — every icon must pass all five constraints to enter the family.
Professional icon sets define keyline shapes — canonical bounding geometries that icons are designed around. Material Design defines four keylines for its 24px grid:
| Keyline Shape | Dimensions | Use Case |
|---|---|---|
| Square | 18x18 | Rectangular content (document, screen) |
| Circle | 20x20 | Circular content (avatar, globe, record) |
| Vertical rectangle | 16x20 | Portrait content (person, bottle, phone) |
| Horizontal rectangle | 20x16 | Landscape content (laptop, car, envelope) |
All four keylines produce optically equivalent weight within the 24px canvas. When designing a new icon, first determine which keyline shape it falls into, then draw within that keyline. This prevents the common failure of icons that are technically the same canvas size but visually different weights.
Icons in interactive contexts need touch/click targets that exceed their visual bounds. WCAG 2.5.8 requires a minimum 24x24 CSS pixel target size. Apple's HIG recommends 44x44pt minimum. This means:
min-width and min-height on the button element, not on the icon SVG — the icon stays visually small while the hit target stays accessibleSeemingly minor stroke attributes create visible inconsistency at scale:
Decision procedure: round caps + round joins for consumer products (friendly, approachable). Square caps + miter joins for technical/professional products. Never mix cap styles within an icon family.
Stroke Weight Drift. Mixing 1.5px, 2px, and 2.25px strokes within the same icon set because individual designers "eyeballed" the weight. At UI scale, even 0.25px differences are visible and make the set feel unpolished. Fix: define an exact stroke weight in the design system tokens, enforce it in the SVG export pipeline, and lint exported SVGs for stroke-width consistency. Lucide runs automated CI checks that reject contributions with non-conforming stroke weights.
Detail Overload at Small Sizes. Designing an icon at 48px with fine interior detail (hatching, small counters, thin negative space) and rendering it at 16px where the detail becomes muddy noise. Fix: follow Apple's optical sizing model — create separate path geometry for each size tier. At minimum, remove interior detail and increase stroke weight for any icon rendered below 20px.
Metaphor Ambiguity. Using a "star" icon for both "favorites" and "ratings" in the same product. Or using a "bell" for both "notifications" and "alarms." When the same visual metaphor maps to two different functions, users cannot build reliable mental models. Fix: one metaphor, one function per product. If you need both favorites and ratings, use a star for one and a heart or bookmark for the other. Document the metaphor map in your design system.
Pixel Grid Misalignment. Designing icons in Figma at 1x without checking the pixel grid, resulting in paths that fall on half-pixel boundaries. The icon looks crisp in Figma's vector preview but renders blurry in the browser at 1x resolution. Fix: in Figma, enable "Snap to pixel grid" and verify at 1x export. In SVG code, audit path coordinates — values like x="3.5" on horizontal edges indicate half-pixel alignment. Round to integers for horizontal/vertical edges.
Filled/Outlined Inconsistency. Using filled icons for some navigation items and outlined for others at the same hierarchy level, creating unintended visual weight differences that imply hierarchy where none exists. Fix: apply the Material Symbols convention — all icons at the same level use the same variant. Reserve the alternate variant for state changes (active/inactive).
Apple SF Symbols — The Gold Standard for Optical Sizing. SF Symbols offers over 5,000 icons with 9 weights (ultralight through black) and 3 scales (small, medium, large), producing 27 variants per symbol. Each variant has unique path geometry — the small-scale, ultralight gear has thicker relative strokes and fewer teeth than the large-scale, bold gear. The system also supports variable color (progressive fill based on a 0-1 value) and automatic alignment with San Francisco text at any size. SF Symbols enforces a 1px stroke grid at each scale, ensuring pixel-perfect rendering on all Apple displays. Key lesson: optical sizing is not optional — it is the difference between a professional and an amateur icon system.
GitHub Octicons — Two-Size Discrete System. Octicons ships exactly two sizes: 16px and 24px. Each size has independent path geometry. The 16px alert triangle has 2px strokes and minimal interior detail (just the exclamation mark). The 24px alert has 1.5px relative strokes and additional interior structure. GitHub chose discrete sizes over continuous scaling because their UI uses only these two sizes — a pragmatic constraint that eliminates optical sizing edge cases. Key lesson: you do not need a continuous size spectrum. Identify your actual render sizes and optimize for those.
Material Symbols — Weight and Fill as Axes. Material Symbols treats stroke weight (100-700), fill (0 or 1), and optical size (20, 24, 40, 48) as independent variable font axes. A single icon file can render at any combination. At weight 400, optical size 24, fill 0: the icon shows 2px outlined strokes. At weight 700, optical size 48, fill 1: the same icon renders as a bold filled shape. This approach eliminates the need for separate icon files per variant — the browser interpolates the correct paths via variable font technology. Key lesson: if your icon system must support many contexts (navigation, content, headers, mobile, desktop), variable axes dramatically reduce maintenance cost.
Vercel — Minimalist Monochrome. Vercel's icon set uses 1.5px strokes, no fills, single color (foreground only), and a deliberately constrained vocabulary (~60 icons). Every icon is reducible to 2-3 strokes — the deploy icon is a single upward arrow with a horizontal base line. This extreme minimalism aligns with Vercel's brand: developer-focused, no-nonsense, maximally functional. Key lesson: icon family personality comes from constraints. Fewer strokes, fewer icons, tighter rules = stronger visual identity.
Airbnb Icons — Hospitality Through Roundness. Airbnb's icon system uses 2px strokes with 2px corner radius — every corner is rounded, every terminal is rounded. This produces icons that feel warm and approachable, matching the "belong anywhere" brand. The roundness is a deliberate departure from the sharp geometric style of tech-company icon sets. Even functional icons like "filter" and "map pin" carry the rounded DNA. Key lesson: corner radius is a brand signal. Sharp corners = precision, authority. Rounded corners = warmth, approachability. The choice must be consistent and intentional.
Icons carry interaction and meaning, making accessibility non-negotiable:
aria-label or aria-labelledby on interactive icon buttons. A button containing only an SVG icon has no accessible name unless explicitly provided. <button aria-label="Close dialog"><svg>...</svg></button> is the minimum. Never rely on the icon's visual metaphor for screen reader users.aria-hidden="true". An icon next to a text label that repeats the icon's meaning (a trash can icon next to "Delete") should be hidden from screen readers to avoid redundancy: <svg aria-hidden="true">.#9CA3AF, ~4.5 relative luminance) on a white background (#FFFFFF, 21 relative luminance) has a contrast ratio of 2.8:1 — failing the requirement. Use #6B7280 (4.6:1) or darker.Icon delivery affects both rendering quality and performance:
currentColor inheritance and CSS custom property theming. An icon that changes color on hover needs to be inline, not an <img> reference.<svg> sprite with <symbol> elements, referenced via <use href="#icon-name">. This reduces HTTP requests to 1 and enables browser caching of the entire set.removeViewBox: false (viewBox is needed for responsive scaling) and removeDimensions: true (use CSS for sizing). A typical icon SVG optimizes from 800 bytes to 200 bytes — a 75% reduction.viewBox — typically "0 0 24 24" for a 24px grid. Inconsistent viewBoxes cause icons to render at different effective sizes even when the CSS width and height are identical.A systematic naming convention prevents icon confusion at scale:
{category}-{object}-{variant}. Example: nav-home-filled, action-delete-outlined, status-check-circle.nav (navigation), action (user actions), status (state indicators), content (content type indicators), social (social platform logos).filled, outlined, two-tone, sharp. Never use ambiguous suffixes like v2 or alt.close (X mark) and cancel (circle X), the names must clearly distinguish them: action-close vs. action-cancel-circle.