Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Apply typography, color theory, spacing systems, and iconography principles to create cohesive visual designs. Use when establishing design tokens, building style guides, or improving visual hierarchy and consistency.
.claude/skills/itamarzand88-visual-design-foundations/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 96% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 109% | 0% |
| case-20 | ✓→✗ | ▼ Worse | 101% | 0% |
| case-14 | ✓→✓ | = Same ✓ | 60% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 92% | 0% |
<!-- source: wshobson-visual-design-foundations — https://raw.githubusercontent.com/wshobson/agents/main/plugins/ui-design/skills/visual-design-foundations/SKILL.md -->
Build cohesive, accessible visual systems using typography, color, spacing, and iconography fundamentals.
Modular Scale (ratio-based sizing):
css:root { --font-size-xs: 0.75rem; /* 12px */ --font-size-sm: 0.875rem; /* 14px */ --font-size-base: 1rem; /* 16px */ --font-size-lg: 1.125rem; /* 18px */ --font-size-xl: 1.25rem; /* 20px */ --font-size-2xl: 1.5rem; /* 24px */ --font-size-3xl: 1.875rem; /* 30px */ --font-size-4xl: 2.25rem; /* 36px */ --font-size-5xl: 3rem; /* 48px */ }
Line Height Guidelines: | Text Type | Line Height | |-----------|-------------| | Headings | 1.1 - 1.3 | | Body text | 1.5 - 1.7 | | UI labels | 1.2 - 1.4 |
8-point grid (industry standard):
css:root { --space-1: 0.25rem; /* 4px */ --space-2: 0.5rem; /* 8px */ --space-3: 0.75rem; /* 12px */ --space-4: 1rem; /* 16px */ --space-5: 1.25rem; /* 20px */ --space-6: 1.5rem; /* 24px */ --space-8: 2rem; /* 32px */ --space-10: 2.5rem; /* 40px */ --space-12: 3rem; /* 48px */ --space-16: 4rem; /* 64px */ }
Semantic color tokens:
css:root { /* Brand */ --color-primary: #2563eb; --color-primary-hover: #1d4ed8; --color-primary-active: #1e40af; /* Semantic */ --color-success: #16a34a; --color-warning: #ca8a04; --color-error: #dc2626; --color-info: #0891b2; /* Neutral */ --color-gray-50: #f9fafb; --color-gray-100: #f3f4f6; --color-gray-200: #e5e7eb; --color-gray-300: #d1d5db; --color-gray-400: #9ca3af; --color-gray-500: #6b7280; --color-gray-600: #4b5563; --color-gray-700: #374151; --color-gray-800: #1f2937; --color-gray-900: #111827; }
js// tailwind.config.js module.exports = { theme: { extend: { fontFamily: { sans: ["Inter", "system-ui", "sans-serif"], mono: ["JetBrains Mono", "monospace"], }, fontSize: { xs: ["0.75rem", { lineHeight: "1rem" }], sm: ["0.875rem", { lineHeight: "1.25rem" }], base: ["1rem", { lineHeight: "1.5rem" }], lg: ["1.125rem", { lineHeight: "1.75rem" }], xl: ["1.25rem", { lineHeight: "1.75rem" }], "2xl": ["1.5rem", { lineHeight: "2rem" }], }, colors: { brand: { 50: "#eff6ff", 500: "#3b82f6", 600: "#2563eb", 700: "#1d4ed8", }, }, spacing: { // Extends default with custom values 18: "4.5rem", 88: "22rem", }, }, }, };
Safe combinations:
css/* Fluid typography using clamp() */ h1 { font-size: clamp(2rem, 5vw + 1rem, 3.5rem); line-height: 1.1; } p { font-size: clamp(1rem, 2vw + 0.5rem, 1.125rem); line-height: 1.6; max-width: 65ch; /* Optimal reading width */ }
css/* Prevent layout shift */ @font-face { font-family: "Inter"; src: url("/fonts/Inter.woff2") format("woff2"); font-display: swap; font-weight: 400 700; }
| Element | Minimum Ratio | | ------------------ | ------------- | | Body text | 4.5:1 (AA) | | Large text (18px+) | 3:1 (AA) | | UI components | 3:1 (AA) | | Enhanced | 7:1 (AAA) |
css:root { --bg-primary: #ffffff; --bg-secondary: #f9fafb; --text-primary: #111827; --text-secondary: #6b7280; --border: #e5e7eb; } [data-theme="dark"] { --bg-primary: #111827; --bg-secondary: #1f2937; --text-primary: #f9fafb; --text-secondary: #9ca3af; --border: #374151; }
tsx// Check contrast programmatically function getContrastRatio(foreground: string, background: string): number { const getLuminance = (hex: string) => { const rgb = hexToRgb(hex); const [r, g, b] = rgb.map((c) => { c = c / 255; return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); }); return 0.2126 * r + 0.7152 * g + 0.0722 * b; }; const l1 = getLuminance(foreground); const l2 = getLuminance(background); const lighter = Math.max(l1, l2); const darker = Math.min(l1, l2); return (lighter + 0.05) / (darker + 0.05); }
Card padding: 16-24px (--space-4 to --space-6)
Section gap: 32-64px (--space-8 to --space-16)
Form field gap: 16-24px (--space-4 to --space-6)
Button padding: 8-16px vertical, 16-24px horizontal
Icon-text gap: 8px (--space-2)css/* Consistent vertical rhythm */ .prose > * + * { margin-top: var(--space-4); } .prose > h2 + * { margin-top: var(--space-2); } .prose > * + h2 { margin-top: var(--space-8); }
css:root { --icon-xs: 12px; --icon-sm: 16px; --icon-md: 20px; --icon-lg: 24px; --icon-xl: 32px; }
tsxinterface IconProps { name: string; size?: "xs" | "sm" | "md" | "lg" | "xl"; className?: string; } const sizeMap = { xs: 12, sm: 16, md: 20, lg: 24, xl: 32, }; export function Icon({ name, size = "md", className }: IconProps) { return ( <svg width={sizeMap[size]} height={sizeMap[size]} className={cn("inline-block flex-shrink-0", className)} aria-hidden="true" > <use href={`/icons.svg#${name}`} /> </svg> ); }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-14 | pass→pass | 13,737 | 7,818 | -43% | 1 | 1 | 0% | 2,822 | 4,519 | +60% | 0 | 0 | — |
case-01 | fail→fail | 14,955 | 15,423 | +3% | 1 | 1 | 0% | 4,591 | 7,376 | +61% | 0 | 0 | — |
case-02 | fail→fail | 18,113 | 17,239 | -5% | 1 | 1 | 0% | 4,139 | 7,002 | +69% | 0 | 0 | — |
case-03 | fail→fail | 12,044 | 14,123 | +17% | 1 | 1 | 0% | 3,496 | 6,669 | +91% | 0 | 0 | — |
case-04 | fail→pass | 11,237 | 9,619 | -14% | 1 | 1 | 0% | 2,643 | 5,188 | +96% | 0 | 0 | — |
case-05 | pass→pass | 10,746 | 9,445 | -12% | 1 | 1 | 0% | 2,481 | 4,768 | +92% | 0 | 0 | — |
case-06 | pass→pass | 11,946 | 8,882 | -26% | 1 | 1 | 0% | 2,838 | 4,885 | +72% | 0 | 0 | — |
case-07 | fail→fail | 9,158 | 11,591 | +27% | 1 | 1 | 0% | 2,064 | 5,887 | +185% | 0 | 0 | — |
case-08 | fail→fail | 11,667 | 10,918 | -6% | 1 | 1 | 0% | 2,303 | 5,024 | +118% | 0 | 0 | — |
case-09 | pass→pass | 8,288 | 6,686 | -19% | 1 | 1 | 0% | 1,722 | 4,344 | +152% | 0 | 0 | — |
case-10 | pass→pass | 11,659 | 9,795 | -16% | 1 | 1 | 0% | 2,387 | 5,068 | +112% | 0 | 0 | — |
case-11 | pass→pass | 9,356 | 5,866 | -37% | 1 | 1 | 0% | 1,784 | 3,980 | +123% | 0 | 0 | — |
case-12 | pass→pass | 12,304 | 10,945 | -11% | 1 | 1 | 0% | 2,756 | 5,243 | +90% | 0 | 0 | — |
case-13 | pass→pass | 13,391 | 13,328 | -0% | 1 | 1 | 0% | 2,576 | 5,484 | +113% | 0 | 0 | — |
case-15 | fail→pass | 8,859 | 7,022 | -21% | 1 | 1 | 0% | 2,038 | 4,262 | +109% | 0 | 0 | — |
case-16 | pass→pass | 13,297 | 14,880 | +12% | 1 | 1 | 0% | 2,596 | 5,845 | +125% | 0 | 0 | — |
case-17 | pass→pass | 16,268 | 17,822 | +10% | 1 | 1 | 0% | 2,716 | 6,103 | +125% | 0 | 0 | — |
case-18 | pass→pass | 4,769 | 4,243 | -11% | 1 | 1 | 0% | 1,071 | 3,677 | +243% | 0 | 0 | — |
case-19 | pass→pass | 10,796 | 8,227 | -24% | 1 | 1 | 0% | 2,038 | 4,322 | +112% | 0 | 0 | — |
case-20 | pass→fail | 13,283 | 11,305 | -15% | 1 | 1 | 0% | 2,408 | 4,847 | +101% | 0 | 0 | — |
case-21 | pass→pass | 12,905 | 10,027 | -22% | 1 | 1 | 0% | 2,284 | 4,536 | +99% | 0 | 0 | — |
case-22 | pass→pass | 13,237 | 12,830 | -3% | 1 | 1 | 0% | 2,608 | 5,275 | +102% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.