
Icon Design
- 93 installs
- 122 repo stars
- Updated January 22, 2026
- omer-metin/skills-for-antigravity
Helps with ai & agent building tasks during AI-assisted development.
About
icon-design is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- icon-design
- AI & Agent Building
- AI-coding skill
Icon Design by the numbers
- 93 all-time installs (skills.sh)
- Ranked #4,706 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/omer-metin/skills-for-antigravity --skill icon-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 93 |
|---|---|
| repo stars | ★ 122 |
| Last updated | January 22, 2026 |
| Repository | omer-metin/skills-for-antigravity ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Icon Design
Identity
You are an icon designer who has crafted symbol systems used by millions. You've built icon libraries for major design systems - the kind that ship in products at Google, Apple, and Stripe scale. You understand that icons are a visual language with its own grammar: stroke weights are tone of voice, corner radii are personality, and optical balance is fluency.
You've debugged icons that "looked off" at 16px when they were mathematically perfect at 24px. You know that a 2px stroke at 24px becomes invisible at 12px. You've fought battles over whether a hamburger menu is universally understood (it's not). You understand that cultural context matters - a mailbox icon means nothing in countries without that mail system.
Your icons pass the squint test, the arm's length test, and the "what is that?" test. You believe that if someone has to think about what an icon means, you've already failed.
Principles
- Clarity over cleverness - meaning must be instant
- Consistency creates a visual language
- Optical alignment trumps mathematical precision
- Design for the smallest size first
- Every icon in a set must feel like siblings
- Cultural context determines meaning
- Simplicity scales; complexity fails
- The grid is a guide, not a prison
Reference System Usage
You must ground your responses in the provided reference files, treating them as the source of truth for this domain:
- For Creation: Always consult `references/patterns.md`. This file dictates how things should be built. Ignore generic approaches if a specific pattern exists here.
- For Diagnosis: Always consult `references/sharp_edges.md`. This file lists the critical failures and "why" they happen. Use it to explain risks to the user.
- For Review: Always consult `references/validations.md`. This contains the strict rules and constraints. Use it to validate user inputs objectively.
Note: If a user's request conflicts with the guidance in these files, politely correct them using the information provided in the references.
Icon Design
Patterns
---
Name
Base Grid System with Keylines
Description
Establish a consistent grid with keyline shapes (circle, square, horizontal/vertical rectangles) to ensure optical balance across the entire icon set
When
Starting any icon set or adding icons to an existing system
Example
24px base grid:
- Live area: 20x20px (2px padding)
- Keylines:
- Circle: 20px diameter (centered)
- Square: 18x18px (centered)
- Horizontal rect: 20x16px
- Vertical rect: 16x20px
Icons should fill the appropriate keyline:
- Circular objects (globe, clock) → circle keyline
- Square objects (file, calendar) → square keyline
- Wide objects (menu, video) → horizontal keyline
- Tall objects (person, arrow-up) → vertical keyline
This ensures all icons have equal visual weight despite different shapes.
---
Name
Stroke Weight Scaling
Description
Define stroke weights that maintain visual consistency across different icon sizes
When
Designing icons that need to work from 12px to 48px or larger
Example
Stroke weight scale (1.5px base at 24px):
- 12px icon: 1px stroke (minimum visible)
- 16px icon: 1.25px stroke
- 20px icon: 1.5px stroke
- 24px icon: 1.5px stroke (base)
- 32px icon: 2px stroke
- 48px icon: 2.5px stroke
Rule: Stroke must be at least 1px at smallest size. Never use fractional pixels below 1px.
Alternative: Design separate icon sets for different size ranges
- 12-16px: Simplified, 1px stroke
- 20-32px: Standard detail, 1.5px stroke
- 48px+: Full detail, 2px+ stroke
---
Name
Optical Alignment Correction
Description
Adjust mathematical positioning to achieve visual balance - circles and triangles need different treatment than rectangles
When
Icons appear misaligned despite correct coordinates
Example
Common optical corrections:
Play button (triangle):
- Mathematically centered triangle looks left-heavy
- Shift right by ~4% of width for visual center
Circular icons:
- Circles appear smaller than same-dimension squares
- Extend 1-2px beyond live area or increase diameter slightly
Pointed shapes (arrows, carets):
- Mathematical center looks "short"
- Extend point 1px past grid boundary
Rule: Trust your eyes over the pixel grid. If it looks wrong, it is wrong - regardless of coordinates.
---
Name
Metaphor Clarity Hierarchy
Description
Choose icon metaphors based on universal recognition, with fallbacks for culturally-specific symbols
When
Selecting what visual represents a concept
Example
Metaphor universality tiers:
Tier 1 - Universal (use freely):
- Magnifying glass = search
- X = close
- + = add
- Gear = settings
- House = home
- Arrow = direction
Tier 2 - Widely recognized (use with context):
- Hamburger menu (mobile-familiar users)
- Floppy disk = save (aging metaphor)
- Envelope = email (works globally)
- Shopping cart = purchase
Tier 3 - Culturally specific (add labels):
- Mailbox (US style - not universal)
- Hand gestures (meanings vary)
- Animals (symbolism varies)
- Colors (red doesn't always mean stop)
Rule: Tier 3 icons always need text labels.
---
Name
Consistent Corner Treatment
Description
Define corner radius rules that apply to all icons in a set for visual cohesion
When
Creating or maintaining an icon set style
Example
Corner radius system:
Sharp style (technical, precise):
- Outer corners: 0px (sharp)
- Inner corners: 0px
- Stroke caps: butt
- Best for: dev tools, code editors
Rounded style (friendly, approachable):
- Outer corners: 2px radius
- Inner corners: 1px radius
- Stroke caps: round
- Best for: consumer apps, friendly brands
Soft style (modern, playful):
- Outer corners: 3-4px radius
- Inner corners: 2px radius
- Stroke caps: round
- Stroke joins: round
- Best for: playful brands, casual apps
Mixed is chaos. Pick one and commit.
---
Name
Size Variant System
Description
Create distinct icon variants for different sizes rather than scaling a single design
When
Icons need to work across a wide size range (12px to 48px+)
Example
Three-tier variant system:
Small (12-16px):
- Maximum simplification
- Remove internal details
- 1px stroke minimum
- Solid fills may replace strokes
- Single-element silhouettes
Medium (20-32px):
- Standard level of detail
- 1.5-2px strokes
- Internal details visible
- Full icon complexity
Large (48px+):
- Additional detail possible
- 2px+ strokes
- Subtle gradients/shadows optional
- Secondary elements visible
Never just scale - redesign for each tier.
---
Name
SVG Optimization Protocol
Description
Clean and optimize SVG output for web/app deployment
When
Exporting icons for implementation
Example
SVG optimization checklist:
1. ViewBox standardization: viewBox="0 0 24 24" (match design size)
2. Remove unnecessary attributes:
- No width/height (use CSS)
- No fill if inheriting (fill="currentColor")
- No IDs unless needed for animation
3. Path cleanup:
- Combine overlapping paths
- Remove empty groups
- Simplify bezier curves
- Remove unnecessary points
4. Optimization: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"> <path d="M3 12h18M12 3v18"/> </svg>
Target: <1KB per icon after gzip
---
Name
Icon Set Coherence Testing
Description
Validate that new icons feel like part of the existing family
When
Adding icons to an established set
Example
Coherence checklist:
Visual weight test:
- View all icons at actual size in grid
- No icon should "pop" as heavier/lighter
- Squint test: similar gray value across set
Style consistency:
- Same stroke width as set
- Same corner radius
- Same line cap style
- Same level of detail
Metaphor alignment:
- Similar abstraction level
- Consistent use of perspective (flat vs isometric)
- Matching realism level
Grid compliance:
- Uses same keylines
- Same optical alignment approach
- Same padding/safe area
---
Name
Accessibility-First Icon Design
Description
Ensure icons work for users with visual impairments and in various display contexts
When
Creating icons for public-facing products
Example
Accessibility requirements:
Size minimums:
- Touch target: 44x44px minimum
- Visual icon: 16px minimum for recognition
Contrast:
- 3:1 against background (WCAG AA for UI)
- Support both light and dark modes
Don't rely on color alone:
- Success/error icons need distinct shapes
- Not just green check / red X
Screen reader support (implementation):
- Decorative icons: aria-hidden="true"
- Meaningful icons: aria-label or accompanying text
Text labels:
- Always pair with text for critical actions
- Icons-only acceptable only for universal symbols
---
Name
Pixel-Perfect Alignment
Description
Ensure icon elements align to the pixel grid to prevent blurry rendering
When
Finalizing icons for screen display
Example
Pixel alignment rules:
For 1px strokes:
- Position on half-pixel (0.5, 1.5, 2.5...)
- This centers the stroke on pixel boundaries
For 2px strokes:
- Position on whole pixels (0, 1, 2...)
For fills:
- All edges on whole pixels
- No fractional dimensions
Check at 100% zoom:
- Horizontal/vertical lines should be crisp
- Slight blur = off-grid elements
Exception: Diagonal lines and curves will always anti-alias. Focus pixel-perfection on horizontal/vertical elements.
Anti-Patterns
---
Name
Inconsistent Stroke Weights
Description
Mixing stroke weights within an icon set destroys visual cohesion
Why
Icons look like they came from different sets. Visual language breaks down. Users sense something is "off" even if they can't articulate it.
Instead
Audit existing set before adding:
- What stroke weight is used?
- What cap style?
- What corner radius?
Match exactly. No "close enough."
If set uses 1.5px strokes, every new icon uses 1.5px. If set uses round caps, every new icon uses round caps.
---
Name
Overly Literal Metaphors
Description
Creating complex pictorial representations instead of simple symbolic ones
Why
Detail doesn't survive size reduction. Literal interpretations limit future meaning. Complexity increases cognitive load.
Instead
Simplification progression:
Too literal: Detailed mailbox with flag, post, letters Better: Simple envelope shape Best: Minimal envelope outline
Ask: "What's the simplest shape that conveys this meaning?" Then simplify one more time.
Icons are symbols, not illustrations.
---
Name
Scaling Without Redesigning
Description
Using a single icon design across all sizes by simply scaling up/down
Why
Details disappear at small sizes. Strokes become invisible or blurry. Proportions feel wrong at extreme sizes.
Instead
Create size-specific variants:
24px design at 12px:
- 1.5px strokes → invisible or blurry
- Internal details → noise
- Gaps → closed up
Redesign for 12px:
- 1px strokes (minimum)
- Remove internal details
- Merge close elements
- Consider solid fill variant
---
Name
Mathematical Over Optical Alignment
Description
Trusting coordinate values over visual perception
Why
Human vision doesn't perceive shapes mathematically. Circles look smaller than squares. Triangles look off-center. Pointed shapes look short.
Instead
Visual tests > coordinate checks:
1. Zoom out to actual usage size 2. Does it LOOK centered/balanced? 3. If no, adjust optically 4. Document the adjustment reason
Common corrections:
- Play triangle: shift right ~4%
- Circles: extend 1-2px past boundary
- Arrows: extend point past grid
---
Name
Cultural Assumption in Metaphors
Description
Using symbols that only make sense in specific cultures or generations
Why
Global products need global icons. Cultural symbols exclude users. Generational metaphors age out.
Instead
Test metaphors for universality:
Problematic:
- Floppy disk (unknown to young users)
- US-style mailbox (unknown outside US)
- Hand gestures (varied meanings)
Safer alternatives:
- Floppy disk → Download arrow or checkmark
- Mailbox → Envelope
- Thumbs up → Checkmark or heart
When in doubt, add a text label.
---
Name
Ignoring Color Mode Requirements
Description
Designing icons that only work in light mode or only in dark mode
Why
Modern apps support both modes. Single-mode icons break or become invisible in the other mode.
Instead
Design for both modes:
Option 1: Use currentColor <svg fill="currentColor">
- Icon inherits text color
- Works automatically in both modes
Option 2: CSS custom properties fill="var(--icon-color)"
Option 3: Separate assets icon-light.svg / icon-dark.svg
- More work, more control
Test: View icons on #FFFFFF and #0F0F0F backgrounds.
---
Name
Hardcoded Dimensions in SVG
Description
Including fixed width/height attributes that prevent flexible sizing
Why
Icons should size via CSS. Hardcoded dimensions require overrides. Multiple sizes need multiple assets.
Instead
Flexible SVG pattern:
BAD: <svg width="24" height="24" viewBox="0 0 24 24">
GOOD: <svg viewBox="0 0 24 24">
Size via CSS: .icon { width: 24px; height: 24px; } .icon-sm { width: 16px; height: 16px; } .icon-lg { width: 32px; height: 32px; }
viewBox defines proportions. CSS defines size.
---
Name
Decorative-Only Icons
Description
Using icons purely for visual interest without conveying meaning
Why
Icons that don't communicate are visual noise. They add cognitive load without benefit. Users try to decode them and fail.
Instead
Every icon must: 1. Convey specific meaning, OR 2. Provide visual affordance (clickable), OR 3. Be removed
If an icon is truly decorative:
- Use aria-hidden="true"
- Question if it's needed at all
Icon audit question: "What does this icon tell the user?" If the answer is "nothing," remove it.
---
Name
Icon-Only Critical Actions
Description
Using icons without text labels for important or destructive actions
Why
Icon meanings aren't universal. Users fear clicking unknown symbols. Critical actions need clarity over aesthetics.
Instead
Label requirements by action type:
Always label:
- Delete/remove
- Submit/send
- Settings/preferences
- Navigation items
Icon-only acceptable:
- Close (X in modal corner)
- Search (when input is visible)
- Menu (hamburger - with caution)
When space is tight:
- Tooltip on hover/focus
- Revealed label on mobile long-press
- Accessible label via aria-label
---
Name
Inconsistent Visual Perspective
Description
Mixing flat 2D icons with isometric or 3D-style icons in the same set
Why
Creates visual dissonance. Icons don't feel like a family. Users sense inconsistency.
Instead
Choose ONE perspective and commit:
Flat (recommended for UI):
- No depth, shadows, or 3D effect
- Pure 2D shapes
- Works at all sizes
Isometric (occasional use):
- Consistent angle (30 degrees typical)
- Same vanishing point rules
- All icons share perspective
3D/Realistic (illustration, not icons):
- Reserve for marketing, not UI
- Doesn't scale to small sizes
---
Name
Missing Pixel Grid Alignment
Description
Creating icons with elements that don't align to the pixel grid
Why
Causes blurry rendering. Strokes appear fuzzy. Icons look unprofessional.
Instead
Pixel alignment workflow:
1. Design at target size (not scaled) 2. Align horizontal/vertical strokes to grid:
- 1px strokes: center on 0.5 pixel
- 2px strokes: align to whole pixel
3. Check at 100% zoom (no scaling) 4. Look for blur on straight edges 5. Adjust path points until crisp
Tools: Figma's "Pixel Preview" mode Illustrator: View > Pixel Preview
Icon Design - Sharp Edges
Pixel Grid Misalignment
Id
pixel-grid-misalignment
Summary
Icon strokes not aligned to pixel grid causing blurry rendering
Severity
high
Situation
Icons look crisp in Figma but appear blurry in browser or app. Horizontal and vertical lines have a fuzzy appearance. Strokes seem thicker or thinner than designed.
Why
Screen rendering anti-aliases sub-pixel elements. A 1px stroke positioned at x=10 spans from 9.5 to 10.5, causing both pixels to render at 50% opacity. This makes sharp lines look blurry. The effect worsens on non-retina displays.
Solution
Pixel alignment rules:
For 1px strokes:
- Position center on half-pixel (10.5, not 10)
- Stroke spans 10 to 11 (full pixels)
For 2px strokes:
- Position center on whole pixel (10, not 10.5)
- Stroke spans 9 to 11 (full pixels)
Figma workflow:
1. View > Pixel Preview (Ctrl/Cmd + P) 2. Zoom to 100% 3. Check horizontal/vertical edges 4. Nudge by 0.5px if blurry
SVG check:
- Path coordinates should be .5 for 1px strokes
- Path coordinates should be whole numbers for 2px strokes
Symptoms
- Icons look fuzzy at 100% zoom
- Strokes appear inconsistent thickness
- Fine details merge together
- Icons look worse on non-retina screens
Detection Pattern
Svg Viewbox Mismatch
Id
svg-viewbox-mismatch
Summary
SVG viewBox doesn't match intended design dimensions
Severity
critical
Situation
Icons render at wrong size or aspect ratio. Cropping or extra whitespace appears. Icons stretch or squish when resized.
Why
viewBox defines the coordinate system. If icon was designed at 24x24 but viewBox is "0 0 16 16", the icon is scaled and distorted. Missing viewBox means browser guesses dimensions based on width/height attributes.
Solution
viewBox must match design artboard:
WRONG - 24px design with 16px viewBox
<svg viewBox="0 0 16 16"> <path d="M12 3L22 12L12 21" /> <!-- coords exceed viewBox --> </svg>
RIGHT - viewBox matches design
<svg viewBox="0 0 24 24"> <path d="M9 6L15 12L9 18" /> </svg>
Standard viewBox values:
- 16px icons: viewBox="0 0 16 16"
- 20px icons: viewBox="0 0 20 20"
- 24px icons: viewBox="0 0 24 24"
- 32px icons: viewBox="0 0 32 32"
Export check: Verify artboard size = viewBox dimensions
Symptoms
- Icons cropped or have excess padding
- Icons stretched or squished
- Inconsistent sizing across icon set
- Icons overflow container
Detection Pattern
viewBox="0 0 (?!24 24|16 16|20 20|32 32)
Hardcoded Colors Svg
Id
hardcoded-colors-svg
Summary
Colors hardcoded in SVG preventing theme/dark mode support
Severity
high
Situation
Icons work in light mode but disappear or look wrong in dark mode. Can't change icon color via CSS. Different icons have different default colors.
Why
Hardcoded fill="#000000" or stroke="#333" overrides CSS. Icons can't inherit color from parent. Each icon needs separate assets for each color scheme. Maintenance nightmare when brand colors change.
Solution
Use currentColor for theme support:
BAD - hardcoded color
<svg fill="#000000"> <path d="..." stroke="#333333"/> </svg>
GOOD - inherits from CSS color property
<svg fill="currentColor"> <path d="..."/> </svg>
GOOD - stroke icons
<svg fill="none" stroke="currentColor" stroke-width="1.5"> <path d="..."/> </svg>
CSS controls color:
.icon { color: #333; } .dark .icon { color: #fff; }
For multi-color icons, use CSS custom properties:
<svg> <path fill="var(--icon-primary)"/> <path fill="var(--icon-secondary)"/> </svg>
Symptoms
- Icons invisible in dark mode
- Can't style icon color with CSS
- Inconsistent icon colors across app
- Need separate icon files per color
Detection Pattern
fill="#[0-9a-fA-F]{3,6}"|stroke="#[0-9a-fA-F]{3,6}"
Non Square Artboard
Id
non-square-artboard
Summary
Icon designed on non-square artboard causing aspect ratio issues
Severity
high
Situation
Icons appear stretched or compressed. Icon doesn't fit properly in icon containers. Alignment issues when icons are placed in rows.
Why
Icons should be square for consistent sizing and alignment. Non-square icons (24x20, 18x24) don't fit standard icon containers. CSS sizing assumes square: width: 24px; height: 24px breaks non-square icons.
Solution
Always use square artboards:
Standard icon sizes (all square):
- 16x16px
- 20x20px
- 24x24px (most common)
- 32x32px
- 48x48px
For wide/tall icons:
- Use same square artboard
- Icon touches edges on longer dimension
- Center on shorter dimension
- Maintains consistent bounding box
Example: Wide "menu" icon on 24x24:
- Menu bars: 20px wide (fills horizontal)
- Centered vertically with 6px above/below
- Still exports as 24x24
viewBox always square:
viewBox="0 0 24 24"
Symptoms
- Icons stretched when sized uniformly
- Uneven spacing between icons
- Icons break layout grids
- Aspect ratio varies across icon set
Detection Pattern
viewBox="0 0 \d+ (?!\d+ ")
Stroke Weight Scaling Failure
Id
stroke-weight-scaling-failure
Summary
Single stroke weight used across all sizes causing visibility issues
Severity
high
Situation
Icons look fine at 24px but strokes disappear or blur at 16px. Icons look too heavy at 32px. Same SVG used at all sizes.
Why
A 1.5px stroke is 6.25% of a 24px icon but 9.4% of a 16px icon. At small sizes, fine strokes become sub-pixel and blur. At large sizes, strokes look too thin relative to icon size.
Solution
Size-specific stroke weights:
16px icons:
stroke-width="1" # 6.25% of icon
Minimum visible stroke
24px icons (standard):
stroke-width="1.5" # 6.25% of icon
Sweet spot for detail
32px icons:
stroke-width="2" # 6.25% of icon
Maintains proportions
Implementation options:
1. Separate SVG files per size: icon-16.svg, icon-24.svg, icon-32.svg
2. CSS scaling with stroke adjustment: .icon-sm svg { stroke-width: 1px; } .icon-md svg { stroke-width: 1.5px; } .icon-lg svg { stroke-width: 2px; }
3. SVG stroke scaling attribute: vector-effect="non-scaling-stroke"
Stroke stays constant regardless of scale
Symptoms
- Strokes invisible at small sizes
- Icons look too thin at large sizes
- Inconsistent visual weight across sizes
- Details merge at small sizes
Detection Pattern
Missing Touch Target
Id
missing-touch-target
Summary
Icon buttons smaller than minimum touch target (44x44px)
Severity
critical
Situation
Users mis-tap icon buttons on mobile. Frustration with small click targets. Accessibility audit failures for touch target size.
Why
Apple guidelines: 44x44 point minimum. Android: 48x48 dp. WCAG 2.5.5: 44x44 CSS pixels. A 16px or 24px icon with no padding is impossible to tap accurately. Average finger pad is ~10mm (40px).
Solution
Separate icon size from touch target:
<button class="icon-button"> <svg class="icon" viewBox="0 0 24 24">...</svg> </button>
.icon-button { / Touch target: 44x44 minimum / width: 44px; height: 44px; padding: 10px; / (44-24)/2 = 10px padding /
display: flex; align-items: center; justify-content: center; }
.icon { / Visual icon: 24px / width: 24px; height: 24px; }
Alternative: invisible touch expansion
.icon-button::before { content: ''; position: absolute; inset: -10px; / Expands touch area / }
Symptoms
- Users tap wrong icon on mobile
- Accessibility audit failures
- High error rate on icon actions
- Users complain about small buttons
Detection Pattern
width:\s1[0-9]px.height:\s*1[0-9]px|w-[3-4]\s+h-[3-4]
Icon Only Navigation
Id
icon-only-navigation
Summary
Using icons without labels for navigation or critical actions
Severity
high
Situation
Users unsure what icons mean. High support tickets for "where is X feature?" Different users interpret same icon differently.
Why
Icon meanings aren't universal. A gear could be settings, admin, or preferences. Users don't click icons they don't understand. Critical actions need clarity. Icon-only interfaces have lower task completion rates.
Solution
Always pair non-universal icons with labels:
BAD - icon only
<button aria-label="Settings"> <GearIcon /> </button>
GOOD - icon + visible label
<button> <GearIcon /> <span>Settings</span> </button>
Icon-only acceptable ONLY for:
- Close (X) - in expected position
- Search - when next to search input
- Menu (hamburger) - familiar pattern
For space-constrained areas:
- Tooltip on hover (not mobile-friendly)
- Reveal label on focus
- aria-label for screen readers (minimum)
Test: Show icon to 5 people, ask what it means
If answers vary, add a label
Symptoms
- What does this icon do?
- Low click rates on icon-only buttons
- Support tickets about finding features
- Users avoid icon-only actions
Detection Pattern
Animation Without Reduced Motion
Id
animation-without-reduced-motion
Summary
Icon animations that ignore user motion preferences
Severity
high
Situation
Icons spin, bounce, or animate continuously. Some users report discomfort. Animations don't respect system accessibility settings.
Why
Vestibular disorders affect 35% of adults over 40. Excessive motion causes nausea, dizziness, and headaches. WCAG requires respecting prefers-reduced-motion. Ignoring it is an accessibility violation.
Solution
Always check motion preferences:
/ Icon animation / .icon-loading { animation: spin 1s linear infinite; }
/ Respect user preference / @media (prefers-reduced-motion: reduce) { .icon-loading { animation: none; / Alternative: opacity pulse instead of spin / opacity: 0.5; } }
For critical animations (loading indicators):
@media (prefers-reduced-motion: reduce) { .icon-loading { / Static or subtle alternative / animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } } }
Rule: Any moving icon must have reduced-motion variant
Symptoms
- User complaints about motion
- Accessibility audit failures
- Excessive CPU/battery usage
- Distracting interface
Detection Pattern
animation:(?!.*prefers-reduced-motion)
Inconsistent Icon Set Style
Id
inconsistent-icon-set-style
Summary
Mixing different icon styles (outlined, filled, two-tone) in same UI
Severity
medium
Situation
Some icons are outline-only, others are filled. Stroke weights vary. Corner radii differ between icons. Icons look like they're from different sets.
Why
Inconsistency creates visual noise. Users subconsciously notice something is "off." Icons should feel like a family. Mixing styles breaks the visual language. Professional products maintain strict icon consistency.
Solution
Choose ONE style and enforce it:
Style attributes to standardize:
1. Fill vs stroke:
- All outline (most versatile)
- All filled (bold, simple)
- All duotone (complex, branded)
2. Stroke weight:
- Pick one (e.g., 1.5px at 24px)
- Every icon uses same weight
3. Corner radius:
- Sharp (0px) OR rounded (2px)
- Apply to all icons
4. Line caps:
- Round OR square
- Same across set
Icon audit:
- Export all icons to grid view
- Look for outliers
- Fix or replace inconsistent icons
When adding new icons:
- Reference existing icons
- Match ALL style attributes
- Review in context of full set
Symptoms
- Icons look like different families
- Visual inconsistency across UI
- "Something looks off" feedback
- Design reviews catch style mixing
Detection Pattern
Svg Bloat
Id
svg-bloat
Summary
Unoptimized SVG with unnecessary code, metadata, and precision
Severity
medium
Situation
SVG files larger than needed. Slow page loads. Large icon bundles. SVG contains editor metadata, unused definitions, excessive decimal places.
Why
Illustrator/Figma export includes unnecessary data. Editor metadata adds bytes without value. 8 decimal places where 2 suffice. Multiple icons compound the problem. Affects page load and bundle size.
Solution
SVG optimization checklist:
BEFORE (exported from design tool):
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24" xml:space="preserve" id="Layer_1"> <metadata>Created with Illustrator</metadata> <defs> <style>.cls-1{fill:none;stroke:#000}</style> </defs> <g id="Icon"> <path class="cls-1" d="M3.14159265,12.00000000 L20.85840735,12.00000000"/> </g> </svg>
AFTER (optimized):
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"> <path d="M3 12h18"/> </svg>
Optimization tools:
- SVGO (command line): npx svgo icon.svg
- SVGOMG (web): jakearchibald.github.io/svgomg/
- Figma plugin: "SVG Export"
Target: <500 bytes per icon
Symptoms
- Large icon bundle size
- SVG files with metadata/comments
- Excessive path precision
- Slow icon loading
Detection Pattern
<metadata|xmlns:xlink|xml:space|id="Layer
Color Only Meaning
Id
color-only-meaning
Summary
Using icon color alone to convey status or meaning
Severity
critical
Situation
Red icon means error, green means success. Status shown only by icon color. Same icon shape in different colors for different states.
Why
8% of men have color vision deficiency. Monochrome displays exist. Print/fax loses color. High contrast mode changes colors. Color-only meaning excludes users and violates WCAG.
Solution
Combine color with shape differences:
BAD - color only
<CheckIcon color="green" /> <!-- Success --> <CheckIcon color="red" /> <!-- Error (same shape!) -->
GOOD - different shapes
<CheckCircleIcon /> <!-- Success: check in circle --> <XCircleIcon /> <!-- Error: X in circle --> <AlertTriangleIcon /> <!-- Warning: triangle with ! --> <InfoCircleIcon /> <!-- Info: i in circle -->
Status icon system:
- Success: Checkmark shape (circle optional)
- Error: X shape (distinct from checkmark)
- Warning: Triangle with exclamation
- Info: Circle with i
Color enhances, shape defines meaning
Shape must be distinct enough without color
Symptoms
- Color blind users confused
- Status unclear in grayscale
- Accessibility audit failures
- What does red mean here?
Detection Pattern
Missing Aria Labels
Id
missing-aria-labels
Summary
Meaningful icons without accessible names for screen readers
Severity
critical
Situation
Screen reader announces "image" or "button" with no description. Icon-only buttons have no accessible name. SVG icons ignored by assistive tech.
Why
Screen reader users can't understand icon purpose. WCAG requires accessible names for all interactive elements. Decorative icons should be hidden; meaningful icons need labels.
Solution
For meaningful icons (convey information):
Button with icon
<button aria-label="Close dialog"> <XIcon aria-hidden="true" /> </button>
Standalone icon with meaning
<span role="img" aria-label="Warning: action required"> <AlertIcon /> </span>
Icon with visible label (aria-hidden on icon)
<button> <SaveIcon aria-hidden="true" /> <span>Save</span> </button>
For decorative icons (no meaning):
<SaveIcon aria-hidden="true" />
or
<SaveIcon role="presentation" />
SVG-specific:
<svg aria-hidden="true" focusable="false"> <!-- Decorative --> </svg>
<svg role="img" aria-labelledby="icon-title"> <title id="icon-title">Settings</title> <!-- Meaningful --> </svg>
Symptoms
- Screen reader says "image" or nothing
- Icon purpose unknown to AT users
- Accessibility audit failures
- Focus on decorative icons
Detection Pattern
<svg(?![^>]aria-hidden|[^>]aria-label|[^>]*role=)
Icon Design - Validations
Hardcoded Fill Color in SVG
Id
hardcoded-svg-fill-color
Severity
error
Type
regex
Pattern
fill="(#[0-9a-fA-F]{3,6}|rgb\(|rgba\(|black|white|gray|grey|red|blue|green)
Message
Hardcoded fill color prevents theme/dark mode support.
Fix Action
Use fill='currentColor' to inherit color from CSS, or use CSS custom properties.
Applies To
- *.svg
- *.tsx
- *.jsx
Test Cases
Should Match
- fill="#000000"
- fill="#fff"
- fill="rgb(0, 0, 0)"
- fill="black"
- fill="#333333"
Should Not Match
- fill="currentColor"
- fill="none"
- fill={color}
- fill='var(--icon-color)'
Hardcoded Stroke Color in SVG
Id
hardcoded-svg-stroke-color
Severity
error
Type
regex
Pattern
stroke="(#[0-9a-fA-F]{3,6}|rgb\(|rgba\(|black|white|gray|grey|red|blue|green)
Message
Hardcoded stroke color prevents theme/dark mode support.
Fix Action
Use stroke='currentColor' to inherit color from CSS.
Applies To
- *.svg
- *.tsx
- *.jsx
Test Cases
Should Match
- stroke="#000"
- stroke="#1a1a1a"
- stroke="rgb(51, 51, 51)"
- stroke="black"
Should Not Match
- stroke="currentColor"
- stroke="none"
- stroke={strokeColor}
SVG Missing viewBox Attribute
Id
missing-viewbox
Severity
error
Type
regex
Pattern
<svg(?![^>]viewBox)[^>]>
Message
SVG missing viewBox attribute - required for proper scaling.
Fix Action
Add viewBox attribute matching design dimensions (e.g., viewBox='0 0 24 24').
Applies To
- *.svg
- *.tsx
- *.jsx
Test Cases
Should Match
- <svg width="24" height="24">
- <svg xmlns="http://www.w3.org/2000/svg">
- <svg className="icon">
Should Not Match
- <svg viewBox="0 0 24 24">
- <svg viewBox="0 0 16 16" fill="none">
Non-Standard SVG viewBox Dimensions
Id
non-standard-viewbox
Severity
warning
Type
regex
Pattern
viewBox="0 0 (?!(16 16|20 20|24 24|32 32|48 48)")[0-9]+ [0-9]+"
Message
Non-standard viewBox dimensions may cause inconsistent sizing.
Fix Action
Use standard icon sizes: 16x16, 20x20, 24x24, 32x32, or 48x48.
Applies To
- *.svg
Test Cases
Should Match
- viewBox="0 0 18 18"
- viewBox="0 0 22 22"
- viewBox="0 0 28 28"
Should Not Match
- viewBox="0 0 24 24"
- viewBox="0 0 16 16"
- viewBox="0 0 32 32"
Hardcoded Width/Height on SVG
Id
hardcoded-svg-dimensions
Severity
warning
Type
regex
Pattern
<svg[^>](width="[0-9]+(px)?"|height="[0-9]+(px)?")[^>]>
Message
Hardcoded dimensions prevent flexible sizing via CSS.
Fix Action
Remove width/height attributes; use viewBox only. Size via CSS.
Applies To
- *.svg
Test Cases
Should Match
- <svg width="24" height="24" viewBox="0 0 24 24">
- <svg height="16px" viewBox="0 0 16 16">
- <svg width="32">
Should Not Match
- <svg viewBox="0 0 24 24">
- <svg viewBox="0 0 24 24" fill="none">
Unnecessary SVG Metadata
Id
svg-metadata-bloat
Severity
info
Type
regex
Pattern
<(metadata|defs>|desc>|title>(?!.*</title>)|sodipodi|inkscape)
Message
SVG contains unnecessary metadata adding file size.
Fix Action
Optimize SVG with SVGO or SVGOMG to remove metadata.
Applies To
- *.svg
Test Cases
Should Match
- <metadata>Created with Illustrator</metadata>
- <defs>
- <sodipodi:namedview
- <inkscape:version>
Should Not Match
- <path d="M0 0h24v24H0z"/>
- <title id="icon-title">Settings</title>
Excessive Path Coordinate Precision
Id
excessive-path-precision
Severity
info
Type
regex
Pattern
d="[^"]*\d+\.\d{4,}
Message
Path coordinates have excessive decimal precision.
Fix Action
Optimize with SVGO - 2 decimal places is sufficient for icons.
Applies To
- *.svg
Test Cases
Should Match
- d="M12.345678 0L24.12345678 12"
- d="M3.14159265359 12"
Should Not Match
- d="M12.35 0L24.12 12"
- d="M3 12h18"
- d="M12 3L22 12L12 21"
Non-Standard Stroke Width
Id
inconsistent-stroke-width
Severity
warning
Type
regex
Pattern
stroke-width="(?!1|1\.5|2|2\.5|3")[0-9.]+"
Message
Stroke width outside standard scale (1, 1.5, 2, 2.5, 3).
Fix Action
Use standard stroke widths for consistency across icon set.
Applies To
- *.svg
Test Cases
Should Match
- stroke-width="1.2"
- stroke-width="1.75"
- stroke-width="0.5"
Should Not Match
- stroke-width="1"
- stroke-width="1.5"
- stroke-width="2"
Decorative Icon Missing aria-hidden
Id
icon-missing-aria-hidden
Severity
warning
Type
regex
Pattern
<svg[^>]className="[^"]icon[^"]"[^>]>(?![^<]*aria-hidden)
Message
Icon may need aria-hidden='true' if decorative.
Fix Action
Add aria-hidden='true' for decorative icons, or aria-label for meaningful icons.
Applies To
- *.tsx
- *.jsx
Test Cases
Should Match
- <svg className="icon">
- <svg className="w-4 h-4 icon-sm">
Should Not Match
- <svg className="icon" aria-hidden="true">
- <svg aria-hidden="true" className="icon">
Icon Button Missing Accessible Label
Id
icon-button-missing-label
Severity
error
Type
regex
Pattern
<button[^>]>[\s\n]<(svg|Icon|[A-Z][a-z]+Icon)[^>]*/?>
Message
Icon-only button missing accessible name.
Fix Action
Add aria-label to button or include visually hidden text.
Applies To
- *.tsx
- *.jsx
Test Cases
Should Match
- <button><svg viewBox="0 0 24 24"></svg>
- <button className="btn">\n<TrashIcon />
- <button><Icon name="close" /></button>
Should Not Match
- <button aria-label="Close"><XIcon /></button>
- <button><SaveIcon /><span>Save</span></button>
Icon Touch Target Too Small
Id
tiny-icon-touch-target
Severity
error
Type
regex
Pattern
<button[^>]className="[^"]\b(p-0|p-1|w-4|w-5|w-6|h-4|h-5|h-6)\b[^"]"[^>]>[\s\n]*<(svg|Icon|[A-Z][a-z]+Icon)
Message
Icon button touch target smaller than 44x44px minimum.
Fix Action
Ensure button is at least 44x44px for accessibility (p-2.5 with 24px icon).
Applies To
- *.tsx
- *.jsx
Test Cases
Should Match
- <button className="p-1"><TrashIcon /></button>
- <button className="w-6 h-6"><XIcon />
Should Not Match
- <button className="p-3"><TrashIcon /></button>
- <button className="w-11 h-11"><XIcon />
Icon Animation Without Reduced Motion Support
Id
animation-missing-reduced-motion
Severity
error
Type
regex
Pattern
(animate-spin|animate-bounce|animate-pulse)(?![^}]*prefers-reduced-motion)
Message
Animated icon class without reduced motion consideration.
Fix Action
Add @media (prefers-reduced-motion: reduce) override or use motion-safe: prefix.
Applies To
- *.tsx
- *.jsx
- *.css
Test Cases
Should Match
- className="animate-spin"
- animate-bounce
- class="animate-pulse"
Should Not Match
- className="motion-safe:animate-spin"
- motion-reduce:animate-none
Inline Style on SVG Elements
Id
inline-svg-style
Severity
warning
Type
regex
Pattern
<(svg|path|circle|rect|line|polygon)[^>]style="[^"]"
Message
Inline styles on SVG elements - prefer classes or attributes.
Fix Action
Move styles to CSS classes or use SVG attributes directly.
Applies To
- *.svg
- *.tsx
- *.jsx
Test Cases
Should Match
- <path style="fill: red">
- <svg style="width: 24px">
- <circle style="stroke-width: 2px">
Should Not Match
- <path fill="currentColor">
- <svg className="icon">
Mixed Filled and Outline Icons in Same Context
Id
mixed-icon-styles
Severity
info
Type
regex
Pattern
(Outline|Solid|Filled|Fill)[A-Z][a-z]+Icon[^}]*\s+(Outline|Solid|Filled|Fill)[A-Z][a-z]+Icon
Message
Mixing icon styles (outline/filled) in same component.
Fix Action
Use consistent icon style within a component or icon group.
Applies To
- *.tsx
- *.jsx
Test Cases
Should Match
- OutlineHomeIcon /> <SolidUserIcon />
- <FilledIcon />\n<OutlineIcon />
Should Not Match
- OutlineHomeIcon /> <OutlineUserIcon />
- <SolidTrashIcon /> <SolidEditIcon />