typography

Font Selection

Selecting the right font for your app is more than an aesthetic choice—it shapes your brand identity and directly impacts how users read and interact with your content. Here’s a guide to help you make thoughtful decisions.

Brand Identity

Your font communicates your brand’s personality. Consider:
  • Tone and personality: Are you aiming for playful, professional, modern, or traditional? Fonts convey emotion. For example, rounded sans-serifs often feel approachable, while serif fonts convey reliability and authority.
  • Consistency: Use fonts that complement your brand logo, colors, and overall design language. Consistency strengthens recognition and trust.
  • Hierarchy: Different font weights and styles can emphasize key content without introducing new typefaces unnecessarily.

Legibility and Readability

Your users must be able to read your content effortlessly. Key considerations include:
  • Font size and line height: Ensure text is large enough on all screen sizes, with adequate spacing between lines.
  • Character clarity: Choose fonts with distinct letterforms—avoid fonts where “I,” “l,” and “1” look identical.
  • Contrast: Ensure sufficient contrast between text and background colors to make reading easy under various lighting conditions.
  • Avoid excessive styles: Stick to regular, bold, and italic as needed. Decorative or script fonts should be reserved for accents, not body text.

Cross-Platform Versatility

  • Applications often display text across multiple devices. Choose fonts that:
  • Render well on different screens and resolutions.
  • Support multiple languages and character sets if your app is global.
  • Are compatible with system or web-safe options to reduce load times and maintain consistent rendering.

Font Pairing

  • Limit the number of fonts: Two fonts (a primary and a secondary) are usually enough.
  • Contrast and complement: Pair a serif with a sans-serif, or a bold headline font with a neutral body font.
  • Maintain hierarchy: Use size, weight, and style to distinguish headings, subheadings, and body text.

Font Stack Example

font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 
             'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 
             'Fira Sans', 'Droid Sans', 'Helvetica Neue', 
             sans-serif;

Typography Hierarchy

Varying font weights and styles can highlight important content, helping users navigate the app more smoothly.

Heading Levels

  • H1: Page title, 32px-48px
  • H2: Section title, 24px-32px
  • H3: Subsection title, 20px-24px
  • H4: Component title, 18px-20px
  • H5: Small heading, 16px-18px
  • H6: Smallest heading, 14px-16px

Body Text

  • Large body: 18px-20px for important content
  • Body: 16px for standard content
  • Small body: 14px for secondary content
  • Caption: 12px-14px for labels and metadata

Font Properties

Font Weight

  • Light: 300 for large headings
  • Regular: 400 for body text
  • Medium: 500 for emphasis
  • Semi-bold: 600 for subheadings
  • Bold: 700 for strong emphasis

Line Height

  • Headings: 1.1-1.3 for tight spacing
  • Body text: 1.4-1.6 for readability
  • Large text: 1.3-1.5 for better flow
  • Small text: 1.4-1.6 for clarity

Letter Spacing

  • Headings: -0.5px to 0px for tightness
  • Body text: 0px for normal reading
  • Small caps: 0.5px-1px for clarity
  • All caps: 1px-2px for readability

Mobile-First Considerations

  • Minimum size: 16px to prevent zoom on iOS
  • Touch targets: 44px minimum height
  • Readable text: 14px minimum for body text
  • Comfortable reading: 16px+ for extended reading

Implementation Examples

Standard CSS

:root {
  /* Font families */
  --font-primary: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'SF Mono', Monaco, 'Cascadia Code', monospace;
  
  /* Font sizes */
  --text-xs: 12px;
  --text-sm: 14px;
  --text-base: 16px;
  --text-lg: 18px;
  --text-xl: 20px;
  --text-2xl: 24px;
  --text-3xl: 32px;
  --text-4xl: 48px;
  
  /* Line heights */
  --leading-tight: 1.1;
  --leading-normal: 1.4;
  --leading-relaxed: 1.6;
  
  /* Font weights */
  --font-normal: 400;
  --font-medium: 500;
  --font-semibold: 600;
  --font-bold: 700;
}

Typography Classes

.text-xs { font-size: var(--text-xs); }
.text-sm { font-size: var(--text-sm); }
.text-base { font-size: var(--text-base); }
.text-lg { font-size: var(--text-lg); }

.font-normal { font-weight: var(--font-normal); }
.font-medium { font-weight: var(--font-medium); }
.font-semibold { font-weight: var(--font-semibold); }
.font-bold { font-weight: var(--font-bold); }

.leading-tight { line-height: var(--leading-tight); }
.leading-normal { line-height: var(--leading-normal); }
.leading-relaxed { line-height: var(--leading-relaxed); }

Tailwind CSS

For projects using Tailwind CSS, configure your typography system in tailwind.config.js:
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'sans-serif'],
        mono: ['SF Mono', 'Monaco', 'Cascadia Code', 'monospace'],
      },
      fontSize: {
        'xs': '12px',
        'sm': '14px',
        'base': '16px',
        'lg': '18px',
        'xl': '20px',
        '2xl': '24px',
        '3xl': '32px',
        '4xl': '48px',
      },
      lineHeight: {
        'tight': '1.1',
        'normal': '1.4',
        'relaxed': '1.6',
      },
      fontWeight: {
        'normal': '400',
        'medium': '500',
        'semibold': '600',
        'bold': '700',
      }
    }
  }
}
<!-- HTML with Tailwind typography classes -->
<div class="font-sans">
  <h1 class="text-4xl font-bold leading-tight text-gray-900 dark:text-white">
    Page Title
  </h1>
  <h2 class="text-2xl font-semibold leading-normal text-gray-800 dark:text-gray-200">
    Section Title
  </h2>
  <p class="text-base leading-relaxed text-gray-600 dark:text-gray-300">
    Body text with proper line height for readability.
  </p>
  <p class="text-sm text-gray-500 dark:text-gray-400">
    Small text for captions and metadata.
  </p>
</div>
// React component with Tailwind typography
const TypographyExample = () => {
  return (
    <div className="font-sans max-w-4xl mx-auto p-6">
      <h1 className="text-4xl font-bold leading-tight mb-4 text-gray-900 dark:text-white">
        Responsive Typography
      </h1>
      <h2 className="text-2xl font-semibold leading-normal mb-3 text-gray-800 dark:text-gray-200">
        Mobile-First Approach
      </h2>
      <p className="text-base leading-relaxed mb-4 text-gray-600 dark:text-gray-300">
        This text scales appropriately across different screen sizes using 
        Tailwind's responsive utilities.
      </p>
      <code className="text-sm font-mono bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded">
        Code snippets use monospace font
      </code>
    </div>
  );
};

Common Mistakes

Avoid These Issues

  • Too small text: Hard to read on mobile devices
  • Poor contrast: Text that’s hard to see
  • Inconsistent hierarchy: Confusing information structure
  • No fallbacks: Fonts that don’t load properly

Testing Typography

Visual Testing

  • Test on various devices and screen sizes
  • Check readability in different lighting
  • Verify font loading and fallbacks
  • Test with different content lengths

Accessibility Testing

  • Use screen readers to test navigation
  • Check contrast ratios with tools
  • Test keyboard navigation
  • Validate semantic HTML structure

Tools and Resources

  • Google Fonts: Font selection and pairing
  • Type Scale: Generate consistent typography scales
  • Font loading: Google Fonts, Adobe Fonts