Use variant prop to control button styling. Implementation: or . Component definition: defineProps<{ variant: 'primary' | 'secondary' | 'tertiary' }>();. CSS approach: .btn-primary { background: var(--color-primary); color: white; font-weight: 600; } .btn-secondary { background: transparent; color: var(--color-primary); border: 2px solid var(--color-primary); }. Design principles: (1) Primary button: most prominent, used for main call-to-action (CTA), one per page/screen, high saturation colors. (2) Secondary button: less visual prominence, subtle tonal weight, supports primary action, multiple allowed per page. (3) Tertiary/Ghost: lowest emphasis, text-only or minimal styling, for less important actions. Visual hierarchy: primary commands most attention, accompanied by medium (secondary) and low (tertiary) emphasis buttons. States: enabled, hovered, pressed, focused, disabled (5 states for web, 3 for mobile). Best practices: (1) One primary button per page, (2) Use semantic naming (variant not color), (3) Maintain 4.5:1 contrast ratio (WCAG), (4) Support light/dark modes, (5) Consistent spacing and sizing across variants. Tailwind example: variant="primary" → bg-blue-600 hover:bg-blue-700, variant="secondary" → border-2 border-blue-600 text-blue-600.
UI UX Styling FAQ & Answers
24 expert UI UX Styling answers researched from official documentation. Every answer cites authoritative sources you can verify.
unknown
24 questionsUse CSS custom properties (variables) for dynamic theming. Setup: define color tokens in :root: :root { --color-primary: #3B82F6; --color-secondary: #8B5CF6; --color-bg: #FFFFFF; --color-text: #1F2937; } [data-theme='dark'] { --color-primary: #60A5FA; --color-bg: #1F2937; --color-text: #F9FAFB; }. Apply in components: button { background: var(--color-primary); color: var(--color-text); }. Switch themes: document.documentElement.setAttribute('data-theme', 'dark');. Semantic tokens (2025 pattern): create two-tier system: (1) Primitive tokens: raw values (--blue-500: #3B82F6), (2) Semantic tokens: context-specific (--color-primary: var(--blue-500)). Benefits: change primitive once, all semantic tokens update. Color system: 50-900 scale per color (--blue-50 lightest to --blue-900 darkest), use 500 for primary, 600 for hover, 700 for active. Dynamic updates: CSS variables update at runtime (unlike Sass), no recompilation needed, perfect for user preferences. Animations: use @property for smooth transitions: @property --color-primary { syntax: '
Component libraries use design tokens for centralized color management. Tailwind CSS 4 (2025): use @theme directive: @theme { --color-primary: #3B82F6; --color-secondary: #8B5CF6; }. Access in components:
Design tokens abstract raw values into semantic meanings. Token types: (1) Primitive tokens: raw color values (--blue-500: #3B82F6, --spacing-4: 16px, --font-lg: 18px), (2) Semantic tokens: context-specific (--color-primary: var(--blue-500), --spacing-button: var(--spacing-4)). Bad practice:
Create variant system with distinct visual treatments. Variant types: (1) Primary: main CTA, filled background, high contrast (bg-blue-600 text-white), (2) Secondary: supporting action, outlined or subtle fill (border-2 border-blue-600 text-blue-600), (3) Tertiary/Ghost: lowest emphasis, text-only (text-blue-600 hover:bg-blue-50), (4) Danger/Destructive: warning actions, red palette (bg-red-600 text-white), (5) Success: positive actions (bg-green-600), (6) Icon-only: compact actions (p-2 rounded-full). Implementation: const buttonStyles = { primary: 'bg-blue-600 hover:bg-blue-700 text-white', secondary: 'border-2 border-blue-600 text-blue-600 hover:bg-blue-50', danger: 'bg-red-600 hover:bg-red-700 text-white', ghost: 'text-blue-600 hover:bg-blue-50' };
Variant props control visual appearance while maintaining component behavior. Purpose: (1) Visual hierarchy: differentiate importance (primary > secondary > tertiary), (2) Semantic meaning: convey intent (success, warning, danger), (3) Context adaptation: adjust styling for different contexts (toolbar button vs CTA button), (4) Reusability: one component, multiple styles, (5) Consistency: enforce design system rules. Example:
Visual hierarchy guides user attention to most important actions. Hierarchy levels: (1) High emphasis (Primary): one per page, filled button, saturated color, largest size, commands most attention. Example: 'Save', 'Submit', 'Buy Now'. (2) Medium emphasis (Secondary): multiple allowed, outlined or tinted, supports primary action. Example: 'Cancel', 'Learn More', 'View Details'. (3) Low emphasis (Tertiary/Ghost): unlimited, text-only or minimal styling, optional actions. Example: 'Skip', 'Dismiss', 'Not Now'. Visual properties: (1) Color saturation: primary uses vibrant colors (blue-600), secondary uses muted (blue-100 background, blue-600 border), tertiary minimal color. (2) Size: primary slightly larger (py-3 px-6), secondary standard (py-2 px-4), tertiary compact (py-1 px-3). (3) Weight: primary bold text (font-semibold), secondary medium (font-medium), tertiary regular. (4) Spacing: primary more padding, tertiary less. Layout guidelines: (1) Right-align primary in forms (scanning pattern), (2) Group related actions, (3) Destructive actions (red) separate from primary, (4) Disable competing primaries (show one at a time). Accessibility: maintain 3:1 contrast ratio for all states, 4.5:1 for text. Anti-patterns: (1) Multiple primary buttons (confusing), (2) All buttons same size (no hierarchy), (3) Low contrast secondary (invisibility). Best practice: A layout should contain a single high-emphasis button making it clear other buttons have less importance.
Use design tokens and component library for consistency. Strategies: (1) CSS custom properties: define once in :root: --spacing-sm: 8px; --spacing-md: 16px; --color-primary: #3B82F6;, reference everywhere: button { padding: var(--spacing-md); background: var(--color-primary); }. (2) Component library: create base components (Button, Input, Card), ensure all features use these, not custom implementations. (3) Utility classes (Tailwind): shared classes:
Theme systems provide structured approach to color management. Architecture: (1) Color palette: define full spectrum per color (blue-50 to blue-900), (2) Semantic mapping: map palette to semantic tokens (--color-primary: var(--blue-600)), (3) Component tokens: map semantic to components (--button-bg: var(--color-primary)). Implementation: :root { /* Palette / --blue-50: #EFF6FF; --blue-600: #2563EB; --blue-900: #1E3A8A; / Semantic / --color-primary: var(--blue-600); --color-primary-light: var(--blue-50); --color-primary-dark: var(--blue-900); / Components / --button-bg-primary: var(--color-primary); --button-text-primary: white; } [data-theme="dark"] { --blue-600: #3B82F6; / Adjust for dark mode */ }. Usage: button { background: var(--button-bg-primary); color: var(--button-text-primary); }. Benefits: (1) Change theme by updating root tokens, (2) Dark mode support built-in, (3) Brand refresh = update palette, (4) A/B test colors easily. Theme switching: const setTheme = (theme: 'light' | 'dark') => { document.documentElement.dataset.theme = theme; localStorage.setItem('theme', theme); };. Color scales: use tools like Tailwind's color generator or Radix Colors for perceptually uniform scales. Best practices: (1) Three-tier tokens (palette → semantic → component), (2) Test all combinations for contrast, (3) Support system preference (prefers-color-scheme), (4) Animate theme transitions with CSS, (5) Document color usage in design system.
Use mobile-first approach with breakpoints and fluid layouts. Breakpoints (Tailwind standard): sm (640px), md (768px), lg (1024px), xl (1280px), 2xl (1536px). Mobile-first CSS: write base styles for mobile, add complexity at larger screens: .container { padding: 1rem; } @media (min-width: 768px) { .container { padding: 2rem; } }. Tailwind approach:
CSS custom properties enable runtime dynamic styling and theming. Purpose: (1) Theming: define theme colors once, change at runtime, support light/dark modes automatically. (2) Component styling: pass values from parent to deeply nested children without prop drilling. (3) Dynamic updates: JavaScript can change variables, CSS updates automatically. (4) Maintainability: single source of truth, change once applies everywhere. (5) Performance: browser handles recalculation, faster than inline styles. Syntax: define with --: --primary-color: #3B82F6;, use with var(): color: var(--primary-color, blue); (blue is fallback). Inheritance: custom properties inherit down DOM tree, can be overridden at any level. Example: :root { --spacing: 16px; } .compact { --spacing: 8px; } div { padding: var(--spacing); }. JavaScript interaction: getComputedStyle(element).getPropertyValue('--primary-color'); document.documentElement.style.setProperty('--primary-color', '#FF0000');. Advanced (2025): @property for animation: @property --rotation { syntax: '
Use CSS custom properties with data-theme attribute for dark mode. Implementation: define colors for both themes: :root { --bg-primary: #FFFFFF; --text-primary: #1F2937; --color-primary: #3B82F6; } [data-theme="dark"] { --bg-primary: #1F2937; --text-primary: #F9FAFB; --color-primary: #60A5FA; }. Apply in components: body { background: var(--bg-primary); color: var(--text-primary); }. Toggle function: const toggleTheme = () => { const current = document.documentElement.dataset.theme; const next = current === 'dark' ? 'light' : 'dark'; document.documentElement.dataset.theme = next; localStorage.setItem('theme', next); };. Detect system preference: const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; if (prefersDark) document.documentElement.dataset.theme = 'dark';. Listen for changes: window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { if (!localStorage.getItem('theme')) setTheme(e.matches ? 'dark' : 'light'); });. Smooth transitions: use @property (2025): @property --bg-primary { syntax: '
Use variant prop to control button styling. Implementation:
Use CSS custom properties (variables) for dynamic theming. Setup: define color tokens in :root: :root { --color-primary: #3B82F6; --color-secondary: #8B5CF6; --color-bg: #FFFFFF; --color-text: #1F2937; } [data-theme='dark'] { --color-primary: #60A5FA; --color-bg: #1F2937; --color-text: #F9FAFB; }. Apply in components: button { background: var(--color-primary); color: var(--color-text); }. Switch themes: document.documentElement.setAttribute('data-theme', 'dark');. Semantic tokens (2025 pattern): create two-tier system: (1) Primitive tokens: raw values (--blue-500: #3B82F6), (2) Semantic tokens: context-specific (--color-primary: var(--blue-500)). Benefits: change primitive once, all semantic tokens update. Color system: 50-900 scale per color (--blue-50 lightest to --blue-900 darkest), use 500 for primary, 600 for hover, 700 for active. Dynamic updates: CSS variables update at runtime (unlike Sass), no recompilation needed, perfect for user preferences. Animations: use @property for smooth transitions: @property --color-primary { syntax: '
Component libraries use design tokens for centralized color management. Tailwind CSS 4 (2025): use @theme directive: @theme { --color-primary: #3B82F6; --color-secondary: #8B5CF6; }. Access in components:
Design tokens abstract raw values into semantic meanings. Token types: (1) Primitive tokens: raw color values (--blue-500: #3B82F6, --spacing-4: 16px, --font-lg: 18px), (2) Semantic tokens: context-specific (--color-primary: var(--blue-500), --spacing-button: var(--spacing-4)). Bad practice:
Create variant system with distinct visual treatments. Variant types: (1) Primary: main CTA, filled background, high contrast (bg-blue-600 text-white), (2) Secondary: supporting action, outlined or subtle fill (border-2 border-blue-600 text-blue-600), (3) Tertiary/Ghost: lowest emphasis, text-only (text-blue-600 hover:bg-blue-50), (4) Danger/Destructive: warning actions, red palette (bg-red-600 text-white), (5) Success: positive actions (bg-green-600), (6) Icon-only: compact actions (p-2 rounded-full). Implementation: const buttonStyles = { primary: 'bg-blue-600 hover:bg-blue-700 text-white', secondary: 'border-2 border-blue-600 text-blue-600 hover:bg-blue-50', danger: 'bg-red-600 hover:bg-red-700 text-white', ghost: 'text-blue-600 hover:bg-blue-50' };
Variant props control visual appearance while maintaining component behavior. Purpose: (1) Visual hierarchy: differentiate importance (primary > secondary > tertiary), (2) Semantic meaning: convey intent (success, warning, danger), (3) Context adaptation: adjust styling for different contexts (toolbar button vs CTA button), (4) Reusability: one component, multiple styles, (5) Consistency: enforce design system rules. Example:
Visual hierarchy guides user attention to most important actions. Hierarchy levels: (1) High emphasis (Primary): one per page, filled button, saturated color, largest size, commands most attention. Example: 'Save', 'Submit', 'Buy Now'. (2) Medium emphasis (Secondary): multiple allowed, outlined or tinted, supports primary action. Example: 'Cancel', 'Learn More', 'View Details'. (3) Low emphasis (Tertiary/Ghost): unlimited, text-only or minimal styling, optional actions. Example: 'Skip', 'Dismiss', 'Not Now'. Visual properties: (1) Color saturation: primary uses vibrant colors (blue-600), secondary uses muted (blue-100 background, blue-600 border), tertiary minimal color. (2) Size: primary slightly larger (py-3 px-6), secondary standard (py-2 px-4), tertiary compact (py-1 px-3). (3) Weight: primary bold text (font-semibold), secondary medium (font-medium), tertiary regular. (4) Spacing: primary more padding, tertiary less. Layout guidelines: (1) Right-align primary in forms (scanning pattern), (2) Group related actions, (3) Destructive actions (red) separate from primary, (4) Disable competing primaries (show one at a time). Accessibility: maintain 3:1 contrast ratio for all states, 4.5:1 for text. Anti-patterns: (1) Multiple primary buttons (confusing), (2) All buttons same size (no hierarchy), (3) Low contrast secondary (invisibility). Best practice: A layout should contain a single high-emphasis button making it clear other buttons have less importance.
Use design tokens and component library for consistency. Strategies: (1) CSS custom properties: define once in :root: --spacing-sm: 8px; --spacing-md: 16px; --color-primary: #3B82F6;, reference everywhere: button { padding: var(--spacing-md); background: var(--color-primary); }. (2) Component library: create base components (Button, Input, Card), ensure all features use these, not custom implementations. (3) Utility classes (Tailwind): shared classes:
Theme systems provide structured approach to color management. Architecture: (1) Color palette: define full spectrum per color (blue-50 to blue-900), (2) Semantic mapping: map palette to semantic tokens (--color-primary: var(--blue-600)), (3) Component tokens: map semantic to components (--button-bg: var(--color-primary)). Implementation: :root { /* Palette / --blue-50: #EFF6FF; --blue-600: #2563EB; --blue-900: #1E3A8A; / Semantic / --color-primary: var(--blue-600); --color-primary-light: var(--blue-50); --color-primary-dark: var(--blue-900); / Components / --button-bg-primary: var(--color-primary); --button-text-primary: white; } [data-theme="dark"] { --blue-600: #3B82F6; / Adjust for dark mode */ }. Usage: button { background: var(--button-bg-primary); color: var(--button-text-primary); }. Benefits: (1) Change theme by updating root tokens, (2) Dark mode support built-in, (3) Brand refresh = update palette, (4) A/B test colors easily. Theme switching: const setTheme = (theme: 'light' | 'dark') => { document.documentElement.dataset.theme = theme; localStorage.setItem('theme', theme); };. Color scales: use tools like Tailwind's color generator or Radix Colors for perceptually uniform scales. Best practices: (1) Three-tier tokens (palette → semantic → component), (2) Test all combinations for contrast, (3) Support system preference (prefers-color-scheme), (4) Animate theme transitions with CSS, (5) Document color usage in design system.
Use mobile-first approach with breakpoints and fluid layouts. Breakpoints (Tailwind standard): sm (640px), md (768px), lg (1024px), xl (1280px), 2xl (1536px). Mobile-first CSS: write base styles for mobile, add complexity at larger screens: .container { padding: 1rem; } @media (min-width: 768px) { .container { padding: 2rem; } }. Tailwind approach:
CSS custom properties enable runtime dynamic styling and theming. Purpose: (1) Theming: define theme colors once, change at runtime, support light/dark modes automatically. (2) Component styling: pass values from parent to deeply nested children without prop drilling. (3) Dynamic updates: JavaScript can change variables, CSS updates automatically. (4) Maintainability: single source of truth, change once applies everywhere. (5) Performance: browser handles recalculation, faster than inline styles. Syntax: define with --: --primary-color: #3B82F6;, use with var(): color: var(--primary-color, blue); (blue is fallback). Inheritance: custom properties inherit down DOM tree, can be overridden at any level. Example: :root { --spacing: 16px; } .compact { --spacing: 8px; } div { padding: var(--spacing); }. JavaScript interaction: getComputedStyle(element).getPropertyValue('--primary-color'); document.documentElement.style.setProperty('--primary-color', '#FF0000');. Advanced (2025): @property for animation: @property --rotation { syntax: '
Use CSS custom properties with data-theme attribute for dark mode. Implementation: define colors for both themes: :root { --bg-primary: #FFFFFF; --text-primary: #1F2937; --color-primary: #3B82F6; } [data-theme="dark"] { --bg-primary: #1F2937; --text-primary: #F9FAFB; --color-primary: #60A5FA; }. Apply in components: body { background: var(--bg-primary); color: var(--text-primary); }. Toggle function: const toggleTheme = () => { const current = document.documentElement.dataset.theme; const next = current === 'dark' ? 'light' : 'dark'; document.documentElement.dataset.theme = next; localStorage.setItem('theme', next); };. Detect system preference: const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; if (prefersDark) document.documentElement.dataset.theme = 'dark';. Listen for changes: window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { if (!localStorage.getItem('theme')) setTheme(e.matches ? 'dark' : 'light'); });. Smooth transitions: use @property (2025): @property --bg-primary { syntax: '