3.7: Typography & Colors

Master web typography by learning how to control fonts, text styling, spacing, and readability. Discover how to integrate custom web fonts from Google Fonts and implement professional typographic principles.

1. Typography Fundamentals

Typography is the art of arranging text to make it readable and appealing.

Font Family

/* System fonts (fast, no download) */
body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Generic font families */
.serif {
  font-family: Georgia, 'Times New Roman', Times, serif;
}

.sans-serif {
  font-family: Arial, Helvetica, sans-serif;
}

.monospace {
  font-family: 'Courier New', Courier, monospace;
}

.cursive {
  font-family: 'Brush Script MT', cursive;
}

.fantasy {
  font-family: Papyrus, fantasy;
}

Font stack: List multiple fonts as fallbacks

h1 {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  /* Browser uses first available font */
}

Font Size

/* Absolute units */
.text {
  font-size: 16px;      /* Pixels */
  font-size: 12pt;      /* Points */
}

/* Relative units (recommended) */
.text {
  font-size: 1rem;      /* Relative to root (16px default) */
  font-size: 1.5em;     /* Relative to parent */
  font-size: 100%;      /* Relative to parent */
}

/* Viewport units */
.hero-text {
  font-size: 5vw;       /* 5% of viewport width */
}

/* Responsive with clamp */
h1 {
  font-size: clamp(24px, 5vw, 72px);
  /* min: 24px, preferred: 5vw, max: 72px */
}

Font Weight

.text {
  font-weight: normal;   /* 400 */
  font-weight: bold;     /* 700 */
  font-weight: lighter;  /* Relative to parent */
  font-weight: bolder;   /* Relative to parent */

  /* Numeric values */
  font-weight: 100;      /* Thin */
  font-weight: 200;      /* Extra Light */
  font-weight: 300;      /* Light */
  font-weight: 400;      /* Normal */
  font-weight: 500;      /* Medium */
  font-weight: 600;      /* Semi Bold */
  font-weight: 700;      /* Bold */
  font-weight: 800;      /* Extra Bold */
  font-weight: 900;      /* Black */
}

Font Style

.text {
  font-style: normal;
  font-style: italic;
  font-style: oblique;
  font-style: oblique 10deg; /* Angle for oblique */
}

Line Height

Controls spacing between lines.

/* Bad - fixed units */
.text {
  font-size: 16px;
  line-height: 24px;
}

/* Good - unitless (relative to font-size) */
.text {
  font-size: 16px;
  line-height: 1.5; /* 24px (16 × 1.5) */
}

/* Best practices */
body {
  line-height: 1.6; /* Readable for body text */
}

h1, h2, h3 {
  line-height: 1.2; /* Tighter for headings */
}

Letter Spacing

.heading {
  letter-spacing: 0.05em;    /* Loose */
  letter-spacing: -0.02em;   /* Tight */
  letter-spacing: 2px;       /* Fixed spacing */
  letter-spacing: normal;    /* Default */
}

/* Use cases */
.uppercase-heading {
  text-transform: uppercase;
  letter-spacing: 0.1em; /* Uppercase needs more spacing */
}

Word Spacing

.text {
  word-spacing: 0.3em;
  word-spacing: 5px;
  word-spacing: normal;
}

Text Transform

.text {
  text-transform: uppercase;   /* ALL CAPS */
  text-transform: lowercase;   /* all lowercase */
  text-transform: capitalize;  /* First Letter Capitalized */
  text-transform: none;        /* As written */
}

Text Decoration

.text {
  text-decoration: underline;
  text-decoration: overline;
  text-decoration: line-through;
  text-decoration: none;

  /* Multiple */
  text-decoration: underline overline;

  /* With color and style */
  text-decoration: underline wavy red;
  text-decoration: underline dotted blue;
}

/* Links without underline */
a {
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

Text Alignment

.text {
  text-align: left;      /* Default */
  text-align: right;
  text-align: center;
  text-align: justify;   /* Full width (newspapers) */
}

Text Indent

/* First line indent (books/articles) */
.paragraph {
  text-indent: 2em;
}

/* Negative indent (hanging) */
.list-item {
  text-indent: -1em;
  padding-left: 1em;
}

2. Web Fonts

Google Fonts

Step 1: Choose font at fonts.google.com

Step 2: Add to HTML:

<head>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
</head>

Step 3: Use in CSS:

body {
  font-family: 'Roboto', sans-serif;
}

Multiple weights:

<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap" rel="stylesheet">
body {
  font-family: 'Open Sans', sans-serif;
  font-weight: 400;
}

h1 {
  font-weight: 700;
}

.light {
  font-weight: 300;
}

@font-face (Custom Fonts)

@font-face {
  font-family: 'CustomFont';
  src: url('fonts/custom-font.woff2') format('woff2'),
       url('fonts/custom-font.woff') format('woff');
  font-weight: normal;
  font-style: normal;
  font-display: swap; /* Shows fallback while loading */
}

body {
  font-family: 'CustomFont', Arial, sans-serif;
}

Font Display

@font-face {
  font-family: 'MyFont';
  src: url('font.woff2') format('woff2');
  font-display: swap;    /* Show fallback, swap when loaded */
  font-display: block;   /* Hide text, show when loaded */
  font-display: fallback; /* Brief invisible period, then fallback */
  font-display: optional; /* Skip if not loaded quickly */
}

3. Advanced Typography

Text Shadow

.heading {
  /* x-offset y-offset blur color */
  text-shadow: 2px 2px 4px rgba(0,0,0,0.5);

  /* Multiple shadows */
  text-shadow:
    2px 2px 4px rgba(0,0,0,0.5),
    -1px -1px 2px rgba(255,255,255,0.3);

  /* Glow effect */
  text-shadow: 0 0 10px rgba(66,184,131,0.8);
}

Text Overflow

/* Truncate with ellipsis */
.truncate {
  width: 200px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Result: "This is a long text tha..." */

/* Multi-line truncation (webkit only) */
.truncate-3-lines {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

Writing Mode

/* Vertical text */
.vertical {
  writing-mode: vertical-rl;  /* Right to left */
  writing-mode: vertical-lr;  /* Left to right */
}

4. Color Formats

Hexadecimal

.element {
  color: #ff0000;      /* Red */
  color: #f00;         /* Short form */
  color: #ff000080;    /* With alpha (50% opacity) */
}

RGB / RGBA

.element {
  color: rgb(255, 0, 0);           /* Red */
  color: rgba(255, 0, 0, 0.5);     /* 50% transparent red */

  /* New syntax (space-separated) */
  color: rgb(255 0 0);
  color: rgb(255 0 0 / 0.5);       /* With alpha */
}

HSL / HSLA

HSL = Hue, Saturation, Lightness

.element {
  /* hsl(hue, saturation%, lightness%) */
  color: hsl(0, 100%, 50%);        /* Red */
  color: hsl(120, 100%, 50%);      /* Green */
  color: hsl(240, 100%, 50%);      /* Blue */

  /* With alpha */
  color: hsla(0, 100%, 50%, 0.5);  /* 50% transparent red */

  /* New syntax */
  color: hsl(0 100% 50%);
  color: hsl(0 100% 50% / 0.5);
}

HSL is intuitive:

  • Hue: 0-360 (color wheel: 0=red, 120=green, 240=blue)
  • Saturation: 0-100% (0=gray, 100=vivid)
  • Lightness: 0-100% (0=black, 50=pure color, 100=white)

Named Colors

.element {
  color: red;
  color: blue;
  color: transparent;
  color: currentColor; /* Inherits current color value */
}

5. Color Theory Basics

Color Wheel Relationships

Complementary (opposite on wheel):

.primary { color: hsl(0, 100%, 50%); }    /* Red */
.accent { color: hsl(180, 100%, 50%); }   /* Cyan */

Analogous (adjacent on wheel):

.color-1 { color: hsl(0, 100%, 50%); }    /* Red */
.color-2 { color: hsl(30, 100%, 50%); }   /* Orange */
.color-3 { color: hsl(60, 100%, 50%); }   /* Yellow */

Triadic (120° apart):

.color-1 { color: hsl(0, 100%, 50%); }    /* Red */
.color-2 { color: hsl(120, 100%, 50%); }  /* Green */
.color-3 { color: hsl(240, 100%, 50%); }  /* Blue */

Creating Color Schemes

Monochromatic (same hue, different lightness):

:root {
  --primary-dark: hsl(220, 70%, 30%);
  --primary: hsl(220, 70%, 50%);
  --primary-light: hsl(220, 70%, 70%);
  --primary-lighter: hsl(220, 70%, 90%);
}

Shades and tints:

/* Base color */
--blue: hsl(220, 70%, 50%);

/* Tints (add white - increase lightness) */
--blue-tint-1: hsl(220, 70%, 60%);
--blue-tint-2: hsl(220, 70%, 70%);

/* Shades (add black - decrease lightness) */
--blue-shade-1: hsl(220, 70%, 40%);
--blue-shade-2: hsl(220, 70%, 30%);

6. CSS Variables for Colors

Defining Color Variables

:root {
  /* Primary colors */
  --primary-color: #42b883;
  --secondary-color: #35495e;

  /* Semantic colors */
  --success: #4caf50;
  --warning: #ff9800;
  --error: #f44336;
  --info: #2196f3;

  /* Neutral colors */
  --text-primary: #333;
  --text-secondary: #666;
  --text-disabled: #999;

  /* Background colors */
  --bg-primary: #ffffff;
  --bg-secondary: #f5f5f5;
  --border-color: #ddd;
}

Using Variables

.button {
  background: var(--primary-color);
  color: white;
  border: 2px solid var(--primary-color);
}

.button:hover {
  background: var(--primary-dark, #2c7a5e); /* With fallback */
}

Dark Mode with Variables

:root {
  --bg-primary: #ffffff;
  --text-primary: #333;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg-primary: #1a1a1a;
    --text-primary: #f5f5f5;
  }
}

body {
  background: var(--bg-primary);
  color: var(--text-primary);
}

7. Gradients

Linear Gradients

/* Top to bottom (default) */
.gradient {
  background: linear-gradient(#42b883, #35495e);
}

/* Direction */
.gradient {
  background: linear-gradient(to right, red, blue);
  background: linear-gradient(to bottom right, red, blue);
  background: linear-gradient(45deg, red, blue);
}

/* Multiple colors */
.gradient {
  background: linear-gradient(to right, red, yellow, green);
}

/* Color stops */
.gradient {
  background: linear-gradient(
    to right,
    red 0%,
    yellow 50%,
    green 100%
  );
}

/* Sharp transitions */
.gradient {
  background: linear-gradient(
    to right,
    red 50%,
    blue 50%  /* Hard edge at 50% */
  );
}

Radial Gradients

/* Center to edges */
.gradient {
  background: radial-gradient(circle, red, blue);
}

/* Ellipse (default) */
.gradient {
  background: radial-gradient(ellipse, red, blue);
}

/* Position */
.gradient {
  background: radial-gradient(circle at top left, red, blue);
  background: radial-gradient(circle at 20% 30%, red, blue);
}

/* Size */
.gradient {
  background: radial-gradient(circle closest-side, red, blue);
  background: radial-gradient(circle farthest-corner, red, blue);
}

Conic Gradients

/* Pie chart effect */
.gradient {
  background: conic-gradient(red, yellow, green, blue, red);
}

/* From angle */
.gradient {
  background: conic-gradient(from 45deg, red, blue);
}

/* Color wheel */
.color-wheel {
  background: conic-gradient(
    hsl(0, 100%, 50%),
    hsl(60, 100%, 50%),
    hsl(120, 100%, 50%),
    hsl(180, 100%, 50%),
    hsl(240, 100%, 50%),
    hsl(300, 100%, 50%),
    hsl(360, 100%, 50%)
  );
  border-radius: 50%;
}

Repeating Gradients

.stripes {
  background: repeating-linear-gradient(
    45deg,
    #42b883,
    #42b883 10px,
    #35495e 10px,
    #35495e 20px
  );
}

8. Accessibility

Color Contrast

WCAG Guidelines:

  • Normal text: 4.5:1 minimum
  • Large text (18pt+): 3:1 minimum
  • UI elements: 3:1 minimum

Good contrast:

.text {
  color: #333;              /* Dark gray */
  background: #fff;         /* White */
  /* Contrast ratio: 12.6:1 ✓ */
}

Poor contrast:

.text {
  color: #ccc;              /* Light gray */
  background: #fff;         /* White */
  /* Contrast ratio: 1.6:1 ✗ */
}

Tools: Use WebAIM Contrast Checker

Color Blindness

Don't rely on color alone:

/* Bad - color only */
.error { color: red; }
.success { color: green; }

/* Good - color + icon/text */
.error {
  color: red;
}
.error::before {
  content: "⚠ ";
}

9. Practical Exercises

Exercise 3.7.1: Typography System

Create a typography scale:

  • Base: 16px
  • Scale ratio: 1.25
  • Sizes: 12px, 16px, 20px, 25px, 31px, 39px
  • Use rem units

Exercise 3.7.2: Color Palette

Design a color palette with:

  • Primary color
  • 3 shades
  • 3 tints
  • Complementary accent
  • Use CSS variables

Exercise 3.7.3: Web Fonts

Implement Google Fonts:

  • Choose 2 fonts (heading + body)
  • Use 2-3 weights
  • Optimize loading

Exercise 3.7.4: Gradient Background

Create a hero section with:

  • Linear gradient background
  • Overlay text (ensure readability)
  • Responsive gradient

10. Knowledge Check

Question 1: What's the difference between em and rem?

Show answer em is relative to parent font-size. rem is relative to root (html) font-size.

Question 2: Why use unitless line-height?

Show answer Unitless line-height scales proportionally with font-size changes, preventing overlap issues.

Question 3: What's the advantage of HSL over RGB?

Show answer HSL is more intuitive for creating color variations. Easy to adjust hue, saturation, or lightness independently.

Question 4: What's a good color contrast ratio for body text?

Show answer Minimum 4.5:1 for normal text, 3:1 for large text (18pt+ or 14pt+ bold).

Question 5: How do you create a color scheme using CSS variables?

Show answer Define variables in :root, then use var(--variable-name) throughout CSS. Easy to maintain and theme.

11. Key Takeaways

Font stacks - Provide fallbacks for custom fonts ✅ Unitless line-height - Use 1.5-1.6 for body text, 1.2 for headings ✅ Web fonts - Use Google Fonts or @font-face for custom fonts ✅ Color formats - Hex for quick, RGB for precision, HSL for intuitive ✅ CSS variables - Centralize colors for easy theming ✅ Gradients - Linear, radial, and conic for visual interest ✅ Contrast - Maintain 4.5:1 for accessibility ✅ Typography scale - Use consistent sizing system ✅ Letter spacing - Increase for uppercase text ✅ Text shadows - Add depth but use sparingly


12. Further Resources

Typography:

Colors:

Gradients:


Next Steps

Excellent! You now have the skills to create beautiful typography and color schemes.

In Lesson 3.8: Transitions & Animations, you'll learn to bring your designs to life with motion and interactivity.