Lesson 07 / Typography

CSS Fonts

Time
55 min
Type
Reading + Interactive
Level
Beginner
Use
Core

Use fonts effectively in CSS, understand their design and performance impact, and apply best practices for selection and implementation.

Course Role

Core

Part of the main course path. Prioritize this before moving to optional polish or deeper references.

Teacher Notes / In-Class Use

Demo Live

  • Walk through the interactive demo before students start changing their own project files.
  • Connect the demo back to the first goal: Understand web-safe fonts, system fonts, font stacks, and generic font families

Try In Class

  • Create a system font stack for `body`.
  • Have students make one visible change, save, refresh, and explain what changed.

Submit Or Check

  • Ask students to show the work in the browser, not only in the editor.
  • Have students commit their progress with a clear message when the checkpoint is stable.

Watch For

  • Students copying code without checking file paths, spelling, or capitalization.
  • Visual changes that work locally but break when the project is published.

Learning Goals

  • Understand web-safe fonts, system fonts, font stacks, and generic font families
  • Import custom fonts with @font-face and Google Fonts
  • Choose font formats and performance strategies that support readability and speed

Interactive Demo

How to use this demo.

Use the demo as a small lab. Change one thing, observe the result, then connect it back to your own project.

What To Try

  • Change font family, size, line height, weight, and measure one at a time.
  • Make the text intentionally hard to read, then tune it back.

What Changes

  • The preview text responds immediately to each typography setting.
  • The generated CSS shows the exact properties controlling readability.

What To Notice

  • Line height and max-width often affect readability as much as the font family.
  • Body text needs different typography decisions than display headings.

Apply It

  • Set a readable body text size, line height, and max-width in your project stylesheet.

Interactive Demo

CSS Font Tester

Adjust typography settings and compare readability in a realistic text block.

Designing for Readability

Good typography helps readers move through content without fighting the page. Size, line height, weight, and measure all work together.

This demo uses extra JavaScript for teaching. The code sample shows the pattern to practice. View full demo source.

Introduction

Fonts play a central role in web design. They influence how a website looks and feels, and they affect how easily users can read your content.

The previous lesson focused on styling text. This lesson focuses on choosing fonts, building font stacks, loading custom fonts, checking licenses, and managing performance.

Font Decision Checklist

Before importing a font, decide whether it helps the project enough to justify the extra file request.

  • Is the font readable at small and large sizes?
  • Does the font match the tone of the site?
  • Do you need multiple weights, or would one or two be enough?
  • Is the font licensed for your project?
  • Will the font slow down the page?
  • Does the page still work if the custom font fails to load?

Web-Safe Fonts and System Fonts

Key Point: Fonts vary across devices. Some are more likely to be present, but none are truly universal.

  • "Web-safe" fonts are just widely available fonts, not guaranteed to be present on every device.
  • System fonts are defaults from the operating system. Your site may appear differently on various platforms if these are used as fallbacks.

Modern System Font Stack

A system font stack uses fonts that already exist on the user's device. This is fast, readable, and often a strong default.

body {
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

Using Font Stacks

The browser will try each font in order. If one is unavailable, it moves to the next. The generic family, such as sans-serif, ensures a fallback display.

body {
  font-family: "Helvetica Neue", Arial, sans-serif;
}

Generic Families

  • serif: with decorative strokes
  • sans-serif: without strokes, often cleaner
  • monospace: all characters take up the same space
  • cursive: handwriting-style
  • fantasy: decorative or stylized

In most class projects, serif, sans-serif, and monospace are the most practical generic families.

Importing Custom Fonts with @font-face

Use @font-face when you are self-hosting a font file in your project.

A beginner-friendly modern setup can start with woff2, which is the recommended format for current browsers.

font-display: swap helps pages load faster by showing fallback fonts until the custom font is ready.

@font-face {
  font-family: "MyFont";
  src: url("fonts/myfont.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

How @font-face Works

PartPurposeExample
font-familyNames the custom font so you can use it later in CSS.font-family: "MyFont";
srcPoints to the font file.src: url("fonts/myfont.woff2") format("woff2");
font-weightDefines which weight this font file represents.font-weight: 400;
font-styleDefines whether the file is normal, italic, or another style.font-style: normal;
font-displayControls what happens while the font is loading.font-display: swap;

Older Font Formats

Most modern projects should prefer woff2. Older formats are useful to recognize, but you usually do not need all of them for class projects.

FormatUse
.woff2Best compression and most recommended.
.woffOlder fallback format.
.ttfOlder format that may appear in font downloads.
.eotLegacy Internet Explorer format. Usually obsolete.

Google Fonts Integration

Google Fonts gives you the HTML link elements and the CSS font-family value to use.

Only select the weights and styles you actually need. Loading every weight makes the page heavier.

<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=Open+Sans:wght@400;700&display=swap" rel="stylesheet">

Using the Google Font in CSS

Always include a fallback font, such as sans-serif, serif, or monospace.

body {
  font-family: "Open Sans", sans-serif;
}

Hosted vs. Self-Hosted Fonts

Hosted font services like Google Fonts are convenient because they provide the files and embed code.

Self-hosted fonts give you more control over files, privacy, caching, and performance, but they require more setup.

Font Pairing

A font pairing is the combination of fonts used across a site. Keep pairings simple while you are learning.

  • One font for everything is often enough.
  • One heading font plus one body font can create contrast without getting messy.
  • Avoid using three or more fonts early. It usually makes the design harder to control.

Finding Fonts

Always check the license terms before using a font, even if it's free.

Styling with Fonts

h1 {
  font-family: "Open Sans", sans-serif;
  font-weight: 700;
  font-size: 2em;
}

p {
  font-family: "Lora", serif;
  font-style: italic;
  line-height: 1.5;
}

Performance Tips

ActionWhy it helps
Prefer .woff2It usually gives the best compression.
Load only needed weights and stylesEvery extra weight can add another file request.
Avoid unused fontsDo not load fonts that never get applied in CSS.
Use font-display: swapFallback text appears while the custom font loads.
Test fallback fontsThe layout should still work if the custom font fails.

Accessibility Considerations

  • Avoid overly decorative fonts for body text.
  • Check readability at small sizes.
  • Use relative units like em or rem.
  • Avoid relying only on font weight or style to communicate meaning.
  • Make sure fallback fonts still keep the page readable.
  • Use tools to check contrast ratios when choosing text and background colors.
body {
  font-size: 1rem;
}

p {
  font-size: 1.2rem;
}

Common Mistakes

MistakeWhy it mattersFix
Missing fallback fontThe browser may choose an unpredictable fallback.End the stack with a generic family like sans-serif.
Importing too many weightsThe page becomes heavier than necessary.Load only the weights you actually use.
Decorative font for paragraphsLong text becomes harder to read.Save decorative fonts for short display text.
License not checkedThe font may not be allowed for your use.Read the license before publishing.
@font-face name mismatchThe custom font loads but is never applied.Match the font-family name exactly.
Loaded but unused fontThe site pays a performance cost for no visual benefit.Remove unused font imports or apply the font intentionally.
No font-display settingUsers may see invisible text while the font loads.Use font-display: swap.

Activity: Try It Yourself

Use this activity to test font loading, fallback behavior, and font choice.

  • Create a system font stack.
  • Import a Google Font of your choice.
  • Apply the imported font to headings or body text.
  • Limit the import to two weights or fewer.
  • Open developer tools and inspect the font network requests.
  • Temporarily remove the import and check whether the fallback still looks acceptable.
  • Document the font source and license.

Checkpoint

Before moving on, make sure these feel true.

  • I can explain the main concept in my own words.
  • I can apply this lesson to my current project.
  • I can verify the result in the browser.
  • I can commit the change with a clear message.

Practice

  • Create a system font stack for body.
  • Import one Google Font and apply it to headings or body text.
  • Limit the imported font to two weights or fewer.
  • Create a font stack with at least one named font and one generic fallback.
  • Inspect the font request in developer tools.
  • Temporarily remove the font import and test the fallback.
  • Document the font source and license in a project note or comment.