Files
2025-11-30 08:27:59 +08:00

16 KiB

Frontend Design Reference

Comprehensive guide to aesthetic principles, advanced techniques, and deep-dive guidance for creating exceptional frontend interfaces.


Table of Contents

  1. Advanced Typography Techniques
  2. Color Theory & Application
  3. Motion Design Principles
  4. Spatial Composition Techniques
  5. Visual Depth & Atmosphere
  6. Responsive Design Patterns
  7. Accessibility & Inclusive Design
  8. Performance Optimization
  9. Design System Patterns

Advanced Typography Techniques

Font Pairing Strategies

Rule of Contrast Pair fonts that are different enough to create hierarchy, but harmonious enough to feel cohesive.

Successful Pairings:

/* Display + Sans */
--font-display: 'Clash Display', sans-serif;  /* Bold, geometric */
--font-body: 'Inter', sans-serif;             /* Clean, readable */

/* Serif + Sans */
--font-display: 'Fraunces', serif;            /* Classic, elegant */
--font-body: 'Untitled Sans', sans-serif;     /* Modern, neutral */

/* Mono + Sans */
--font-code: 'JetBrains Mono', monospace;     /* Technical */
--font-body: 'Work Sans', sans-serif;         /* Professional */

Font Pairing Framework:

  1. Contrast in style - Serif vs Sans, Geometric vs Humanist
  2. Harmony in proportion - Similar x-heights or cap heights
  3. Shared characteristics - Similar stroke contrast or terminals
  4. Appropriate mood - Both match the aesthetic direction

Variable Fonts

Advantages:

  • Single file, multiple styles
  • Smooth animations between weights/widths
  • Fine-tuned responsive typography
  • Performance benefits

Implementation:

@font-face {
  font-family: 'InterVariable';
  src: url('/fonts/Inter-Variable.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap;
}

.heading {
  font-family: 'InterVariable', sans-serif;
  font-weight: 700;

  @media (max-width: 768px) {
    font-weight: 600;  /* Lighter weight on mobile */
  }
}

/* Animate weight on interaction */
.button {
  font-weight: 500;
  transition: font-weight 0.2s ease;
}

.button:hover {
  font-weight: 700;
}

Typographic Rhythm

Vertical Rhythm: Consistent spacing based on baseline grid.

:root {
  --baseline: 8px;
  --line-height: 1.5;
}

h1 {
  font-size: 48px;
  line-height: calc(var(--baseline) * 8);  /* 64px */
  margin-bottom: calc(var(--baseline) * 4); /* 32px */
}

p {
  font-size: 16px;
  line-height: calc(var(--baseline) * 3);  /* 24px */
  margin-bottom: calc(var(--baseline) * 3); /* 24px */
}

Modular Scale: Type sizes based on mathematical ratio.

:root {
  --ratio: 1.25;  /* Major third */
  --base-size: 16px;
}

.text-xs   { font-size: calc(var(--base-size) / var(--ratio) / var(--ratio)); }
.text-sm   { font-size: calc(var(--base-size) / var(--ratio)); }
.text-base { font-size: var(--base-size); }
.text-lg   { font-size: calc(var(--base-size) * var(--ratio)); }
.text-xl   { font-size: calc(var(--base-size) * var(--ratio) * var(--ratio)); }
.text-2xl  { font-size: calc(var(--base-size) * var(--ratio) * var(--ratio) * var(--ratio)); }

Advanced Typography CSS

Optical alignment:

.heading {
  /* Hanging punctuation */
  hanging-punctuation: first last;

  /* Adjust spacing for visual balance */
  letter-spacing: -0.02em;  /* Tighter tracking for large headings */
}

OpenType features:

.body-text {
  /* Enable ligatures and contextual alternates */
  font-feature-settings:
    "liga" 1,    /* Standard ligatures */
    "calt" 1,    /* Contextual alternates */
    "kern" 1;    /* Kerning */

  /* Better for body text */
  text-rendering: optimizeLegibility;
}

.numbers {
  /* Tabular figures for alignment */
  font-variant-numeric: tabular-nums;
}

Color Theory & Application

Color Psychology

Warm Colors - Energy, passion, urgency

  • Red: Bold, attention-grabbing, urgent
  • Orange: Friendly, enthusiastic, creative
  • Yellow: Optimistic, cheerful, attention

Cool Colors - Trust, calm, professionalism

  • Blue: Trustworthy, stable, corporate
  • Green: Natural, growth, health
  • Purple: Luxury, creativity, wisdom

Neutral Colors - Balance, sophistication

  • Black: Elegant, powerful, formal
  • White: Clean, minimal, pure
  • Gray: Professional, timeless, neutral

Advanced Color Systems

HSL-Based Design: Benefits of HSL over RGB/Hex:

  • Easier to create variations (lighter, darker)
  • Intuitive manipulation (hue, saturation, lightness)
  • Better for programmatic generation
:root {
  /* Base color in HSL */
  --hue: 220;
  --saturation: 70%;
  --lightness: 50%;

  /* Generate color scale */
  --color-50:  hsl(var(--hue), var(--saturation), 95%);
  --color-100: hsl(var(--hue), var(--saturation), 90%);
  --color-200: hsl(var(--hue), var(--saturation), 80%);
  --color-300: hsl(var(--hue), var(--saturation), 70%);
  --color-400: hsl(var(--hue), var(--saturation), 60%);
  --color-500: hsl(var(--hue), var(--saturation), 50%);
  --color-600: hsl(var(--hue), var(--saturation), 40%);
  --color-700: hsl(var(--hue), var(--saturation), 30%);
  --color-800: hsl(var(--hue), var(--saturation), 20%);
  --color-900: hsl(var(--hue), var(--saturation), 10%);
}

Semantic Color Tokens:

:root {
  /* Primitive colors */
  --blue-500: hsl(220, 70%, 50%);
  --red-500: hsl(0, 70%, 50%);
  --green-500: hsl(140, 60%, 45%);

  /* Semantic tokens */
  --color-primary: var(--blue-500);
  --color-danger: var(--red-500);
  --color-success: var(--green-500);

  /* Contextual usage */
  --button-bg: var(--color-primary);
  --error-text: var(--color-danger);
}

/* Easily theme by changing primitives */
[data-theme="orange"] {
  --blue-500: hsl(30, 70%, 50%);  /* Override to orange */
}

Color Accessibility

WCAG Contrast Requirements:

  • AA (minimum): 4.5:1 for normal text, 3:1 for large text
  • AAA (enhanced): 7:1 for normal text, 4.5:1 for large text

Testing contrast:

/* Bad: Insufficient contrast */
.low-contrast {
  color: #999;           /* Gray */
  background: #fff;      /* White */
  /* Ratio: ~2.8:1 - FAILS AA */
}

/* Good: Meets AA */
.good-contrast {
  color: #666;           /* Darker gray */
  background: #fff;      /* White */
  /* Ratio: ~5.7:1 - PASSES AA */
}

/* Better: Meets AAA */
.best-contrast {
  color: #333;           /* Even darker */
  background: #fff;      /* White */
  /* Ratio: ~12.6:1 - PASSES AAA */
}

Motion Design Principles

Easing Functions

Never use linear easing - it feels robotic and unnatural.

Standard easings:

/* Ease-out: Fast start, slow end (entering elements) */
.enter {
  animation: slideIn 0.3s cubic-bezier(0, 0, 0.2, 1);
}

/* Ease-in: Slow start, fast end (exiting elements) */
.exit {
  animation: slideOut 0.2s cubic-bezier(0.4, 0, 1, 1);
}

/* Ease-in-out: Smooth both ends (position changes) */
.move {
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Spring/bounce: Playful, energetic */
.bounce {
  animation: bounce 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55);
}

Custom easings for character:

:root {
  --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-bounce: cubic-bezier(0.68, -0.55, 0.27, 1.55);
  --ease-snap: cubic-bezier(0.87, 0, 0.13, 1);
}

Orchestrated Animations

Staggered delays create rhythm:

.card-grid > .card {
  opacity: 0;
  animation: fadeInUp 0.5s var(--ease-smooth) forwards;
}

.card:nth-child(1) { animation-delay: 0.1s; }
.card:nth-child(2) { animation-delay: 0.2s; }
.card:nth-child(3) { animation-delay: 0.3s; }
.card:nth-child(4) { animation-delay: 0.4s; }

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

Or programmatic delays:

{items.map((item, index) => (
  <Card
    key={item.id}
    style={{
      animationDelay: `${index * 0.1}s`
    }}
  />
))}

Performance-First Animation

Use transform and opacity only - these are GPU-accelerated.

/* ❌ BAD: Causes repaints */
.slow {
  transition: width 0.3s, height 0.3s, top 0.3s, left 0.3s;
}

/* ✅ GOOD: GPU-accelerated */
.fast {
  transition: transform 0.3s, opacity 0.3s;
}

Will-change hint:

.animated-element {
  /* Tell browser this will animate */
  will-change: transform;
}

/* Remove after animation completes */
.animated-element.animation-done {
  will-change: auto;
}

Scroll-Triggered Animations

Intersection Observer pattern:

useEffect(() => {
  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          entry.target.classList.add('visible');
        }
      });
    },
    { threshold: 0.1 }
  );

  document.querySelectorAll('.reveal-on-scroll').forEach((el) => {
    observer.observe(el);
  });

  return () => observer.disconnect();
}, []);
.reveal-on-scroll {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.6s var(--ease-smooth),
              transform 0.6s var(--ease-smooth);
}

.reveal-on-scroll.visible {
  opacity: 1;
  transform: translateY(0);
}

Spatial Composition Techniques

Grid Breaking

Start with a grid, then selectively break it:

.grid-container {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1.5rem;
}

/* Standard grid items */
.grid-item {
  grid-column: span 4;
}

/* Break the grid for emphasis */
.featured-item {
  grid-column: 1 / -1;      /* Full width */
  grid-row: span 2;         /* Double height */
}

.offset-item {
  grid-column: 3 / 11;      /* Offset from edges */
}

Asymmetric Layouts

Visual tension creates interest:

/* Asymmetric two-column */
.asymmetric-layout {
  display: grid;
  grid-template-columns: 2fr 1fr;  /* 66% / 33% split */
  gap: 3rem;
}

/* Diagonal composition */
.diagonal-section {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  transform: rotate(-2deg);  /* Subtle tilt */
}

.diagonal-section > * {
  transform: rotate(2deg);   /* Counter-rotate content */
}

Z-Index Layering

Create depth through layering:

:root {
  /* Z-index scale */
  --z-base: 0;
  --z-elevated: 10;
  --z-sticky: 100;
  --z-overlay: 1000;
  --z-modal: 10000;
}

.layered-composition {
  position: relative;
}

.background-shape {
  position: absolute;
  z-index: var(--z-base);
  opacity: 0.1;
}

.content {
  position: relative;
  z-index: var(--z-elevated);
}

.floating-element {
  position: absolute;
  z-index: calc(var(--z-elevated) + 1);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}

Visual Depth & Atmosphere

Shadow System

Layered shadows for realism:

:root {
  /* Elevation system */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1),
               0 2px 4px rgba(0, 0, 0, 0.06);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1),
               0 4px 6px rgba(0, 0, 0, 0.05);
  --shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.1),
               0 10px 10px rgba(0, 0, 0, 0.04);
}

/* Colored shadows for vibrancy */
.vibrant-button {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
}

Gradient Meshes

Complex, organic color transitions:

.gradient-mesh {
  background:
    radial-gradient(at 20% 30%, hsl(220, 70%, 60%) 0px, transparent 50%),
    radial-gradient(at 80% 20%, hsl(280, 70%, 60%) 0px, transparent 50%),
    radial-gradient(at 40% 80%, hsl(180, 70%, 50%) 0px, transparent 50%),
    radial-gradient(at 90% 70%, hsl(30, 80%, 60%) 0px, transparent 50%),
    hsl(240, 20%, 10%);
}

Texture & Grain

Subtle texture adds tactility:

.noise-texture {
  position: relative;
}

.noise-texture::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' /%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' /%3E%3C/svg%3E");
  opacity: 0.03;
  pointer-events: none;
}

Glass Morphism

Frosted glass effect:

.glass {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(10px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 12px;
}

/* Dark mode variation */
[data-theme="dark"] .glass {
  background: rgba(0, 0, 0, 0.3);
  border-color: rgba(255, 255, 255, 0.1);
}

Responsive Design Patterns

Container Queries

Component-based responsive design:

.card-container {
  container-type: inline-size;
}

.card {
  display: flex;
  flex-direction: column;
}

/* Respond to container width, not viewport */
@container (min-width: 400px) {
  .card {
    flex-direction: row;
  }
}

Fluid Typography

Smooth scaling between viewports:

:root {
  --fluid-min-width: 320;
  --fluid-max-width: 1200;

  --fluid-screen: 100vw;
  --fluid-bp: calc(
    (var(--fluid-screen) - var(--fluid-min-width) / 16 * 1rem) /
    (var(--fluid-max-width) - var(--fluid-min-width))
  );
}

h1 {
  font-size: clamp(2rem, calc(2rem + 2 * var(--fluid-bp)), 4rem);
}

/* Or use modern clamp directly */
h1 {
  font-size: clamp(2rem, 5vw, 4rem);
  /* Min: 2rem, Preferred: 5vw, Max: 4rem */
}

Accessibility & Inclusive Design

Focus Management

Visible, clear focus indicators:

/* Remove default outline, add custom */
:focus {
  outline: none;
}

:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* High contrast for keyboard users */
.button:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 4px;
  box-shadow: 0 0 0 6px rgba(var(--primary-rgb), 0.2);
}

Screen Reader Considerations

Visually hidden but accessible:

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}
<button>
  <Icon />
  <span className="sr-only">Open menu</span>
</button>

Reduced Motion

Respect user preferences:

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Performance Optimization

Critical CSS

Inline critical CSS, defer rest:

<head>
  <!-- Critical CSS inline -->
  <style>
    /* Above-the-fold styles */
    body { margin: 0; font-family: system-ui; }
    .header { /* ... */ }
  </style>

  <!-- Defer non-critical CSS -->
  <link rel="preload" href="/styles/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="/styles/main.css"></noscript>
</head>

Image Optimization

Modern formats with fallbacks:

<picture>
  <source srcSet="/image.avif" type="image/avif" />
  <source srcSet="/image.webp" type="image/webp" />
  <img src="/image.jpg" alt="Description" loading="lazy" />
</picture>

Design System Patterns

Token Architecture

Layered token system:

:root {
  /* Layer 1: Primitive tokens */
  --color-blue-500: hsl(220, 70%, 50%);
  --color-red-500: hsl(0, 70%, 50%);
  --spacing-4: 1rem;

  /* Layer 2: Semantic tokens */
  --color-primary: var(--color-blue-500);
  --color-danger: var(--color-red-500);
  --button-padding: var(--spacing-4);

  /* Layer 3: Component tokens */
  --button-bg: var(--color-primary);
  --button-text: white;
  --button-padding-x: var(--button-padding);
}

This reference provides deep-dive guidance. For workflows, see: