CSS Reference Guide

All TopicsPlayground

Typography

Master every CSS property that controls how text looks, reads, and responds across devices — from basic font stacks to advanced fluid sizing with clamp().

FontsTextReadabilityResponsive@font-face

font-family

The font-family property sets the typeface for an element. You supply a font stack — a prioritized list of family names. The browser walks the list and uses the first font it can find installed or loaded.

Generic Font Families

CSS defines five generic families that act as ultimate fallbacks. You should always end your stack with one.

CSS
/* Generic families */
body  { font-family: serif; }
code  { font-family: monospace; }
h1    { font-family: sans-serif; }
.hand { font-family: cursive; }
.fun  { font-family: fantasy; }

Font Stacks

A practical font stack lists the ideal font first, similar alternatives next, and a generic last.

CSS
body {
  font-family: "Inter", "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
}

pre, code {
  font-family: "Fira Code", "Cascadia Code",
               "JetBrains Mono", Consolas, monospace;
}
Quoting Rules

Font names that contain spaces (e.g. "Fira Code") must be quoted. Single-word names like Arial and generic families like sans-serif should not be quoted.

Live Example — Font Stacks

Serif stack: Georgia, Times New Roman, serif — The quick brown fox jumps over the lazy dog.

Sans-serif stack: Segoe UI, Roboto, Helvetica Neue, Arial — The quick brown fox jumps over the lazy dog.

Monospace stack: Fira Code, Cascadia Code, Consolas — const x = 42;

Cursive stack: Brush Script MT, Segoe Script, cursive — Elegant handwriting feel.

font-size

Controls how large text appears. There are several unit systems; choosing the right one matters for accessibility and responsiveness.

Common Units

CSS
/* Absolute */
p { font-size: 16px; }

/* Relative to parent */
p { font-size: 1.2em; }

/* Relative to root <html> */
p { font-size: 1rem; }

/* Percentage (relative to parent) */
p { font-size: 120%; }
Live Example — px vs em vs rem vs %
Parent: 16px

16px — This is 16 pixels (absolute).

1.5em — 1.5 × parent = 24px.

1.5rem — 1.5 × root (usually 24px).

120% — 120% of parent = 19.2px.

Parent: 20px

16px — Still 16px (absolute, ignores parent).

1.5em — 1.5 × 20px = 30px (bigger!).

1.5rem — Still 1.5 × root (unchanged).

120% — 120% of 20px = 24px (bigger!).

rem is Usually Best

Using rem keeps sizing relative to the root, making global adjustments easy and avoiding the compounding problem of nested em values. Set html { font-size: 62.5%; } to make 1rem = 10px for easy math.

font-weight

Sets the boldness of text. Values range from 100 (thinnest) to 900 (heaviest), in increments of 100. Keywords normal maps to 400, bold maps to 700.

CSS
h1     { font-weight: 700; }  /* bold */
p      { font-weight: 400; }  /* normal */
.light { font-weight: 300; }
.heavy { font-weight: 900; }
.bold  { font-weight: bold; }    /* keyword */
.rel   { font-weight: bolder; } /* relative */
Live Example — Weight Scale 100 – 900

100 — Thin: The quick brown fox

200 — Extra Light: The quick brown fox

300 — Light: The quick brown fox

400 — Regular (normal): The quick brown fox

500 — Medium: The quick brown fox

600 — Semi Bold: The quick brown fox

700 — Bold: The quick brown fox

800 — Extra Bold: The quick brown fox

900 — Black: The quick brown fox

Variable Fonts

Variable fonts support any weight between 1 and 1000 (e.g., font-weight: 450). If a non-variable font doesn't have the exact weight, the browser falls back to the nearest available one.

font-style

Applies italic or oblique styling to text.

CSS
.normal  { font-style: normal; }
.italic  { font-style: italic; }
.oblique { font-style: oblique; }
.angled  { font-style: oblique 15deg; } /* custom angle */
Live Example — font-style

normal — Standard upright text.

italic — Uses the italic variant of the font.

oblique — Slants the normal glyphs mechanically.

italic vs oblique

italic uses specially designed italic glyphs from the font file. oblique simply slants the regular glyphs algorithmically. If no true italic exists, browsers fall back to oblique rendering.

line-height

Sets the vertical spacing between lines of text. Crucial for readability.

CSS
/* Unitless (recommended) — multiplier of font-size */
p { line-height: 1.6; }

/* With units */
p { line-height: 24px; }
p { line-height: 1.5em; }
p { line-height: 150%; }
Live Example — Unitless vs Unit line-height
Unitless: 1.6

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.

Unitless: 1.0

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.

Unitless: 2.0

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Fixed: 16px (on 14px font)

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Always Use Unitless line-height

When you write line-height: 24px on a parent, children inherit the computed value (24px) regardless of their font size. With unitless line-height: 1.5, children inherit the multiplier, so spacing scales with each element's own font size. Unitless is almost always what you want.

letter-spacing & word-spacing

Fine-tune the horizontal space between characters and words.

CSS
.tight   { letter-spacing: -0.02em; }
.normal  { letter-spacing: normal; }
.wide    { letter-spacing: 0.1em; }
.heading { letter-spacing: 0.05em; }

.word-tight { word-spacing: -2px; }
.word-wide  { word-spacing: 8px; }
Live Example — Letter & Word Spacing

letter-spacing: -0.05em — Tightly packed characters

letter-spacing: normal — Default character spacing

letter-spacing: 0.1em — Wide character spacing

letter-spacing: 0.25em — Very wide character spacing


word-spacing: -3px — Words pulled closer together

word-spacing: normal — Default word spacing

word-spacing: 12px — Words pushed far apart

text-align

Sets the horizontal alignment of inline-level content inside a block container.

CSS
.left    { text-align: left; }
.center  { text-align: center; }
.right   { text-align: right; }
.justify { text-align: justify; }
Live Example — text-align Values
text-align: left

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

text-align: center

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

text-align: right

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

text-align: justify

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Justify Creates "Rivers"

text-align: justify can produce ugly gaps ("rivers of white space") in narrow containers or with long words. Always pair it with hyphens: auto and a lang attribute on the HTML element for best results.

text-decoration

Adds decorative lines to text — underlines, overlines, line-throughs, and more. The shorthand bundles line, style, color, and thickness.

CSS
/* Shorthand: line style color thickness */
a { text-decoration: underline; }
.fancy { text-decoration: underline wavy #ef4444 2px; }

/* Individual longhands */
.custom {
  text-decoration-line: underline overline;
  text-decoration-style: dashed;
  text-decoration-color: #646cff;
  text-decoration-thickness: 3px;
  text-underline-offset: 4px;
}
Live Example — text-decoration Styles

underline — The classic link look

overline — Line above the text

line-through — Strikethrough text

underline wavy red — Squiggly error style

underline dotted green — Abbreviation style

underline dashed blue — Custom dashed line

underline double amber — Double underline

all three combined — underline + overline + line-through

text-transform

Changes the capitalization of text visually, without altering the source HTML.

CSS
.upper  { text-transform: uppercase; }
.lower  { text-transform: lowercase; }
.cap    { text-transform: capitalize; }
.none   { text-transform: none; }
Live Example — text-transform

Source: the quick brown fox jumps over the lazy dog

uppercase: the quick brown fox jumps over the lazy dog

lowercase: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG

capitalize: the quick brown fox jumps over the lazy dog

Accessibility Tip

Screen readers ignore text-transform and read the original source text. If you need text to always be uppercase for semantic reasons, type it uppercase in the HTML. Use text-transform only for visual styling.

text-overflow & Multi-line Clamp

Control what happens when text overflows its container.

Single-line Ellipsis

CSS
.truncate {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
Live Example — Single-line Ellipsis

This is a very long sentence that should be truncated with an ellipsis when it overflows the container boundary.

Container width: 350px. The text is clipped and "..." appears.

Multi-line Clamp

CSS
.line-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
Live Example — Multi-line Clamp (3 lines)
Clamped to 3 lines

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Unclamped (same text)

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Browser Support

Despite the -webkit- prefix, line clamping works in all modern browsers including Firefox. It is part of the CSS Overflow Module Level 4 draft.

@font-face

Load custom font files directly. This gives you full control over which weights, styles, and formats you serve.

CSS
@font-face {
  font-family: "MyCustomFont";
  src: url("fonts/custom.woff2") format("woff2"),
       url("fonts/custom.woff")  format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Bold variant */
@font-face {
  font-family: "MyCustomFont";
  src: url("fonts/custom-bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Usage */
body {
  font-family: "MyCustomFont", sans-serif;
}

font-display Values

CSS
font-display: auto;     /* browser decides */
font-display: block;    /* invisible text until loaded (up to 3s) */
font-display: swap;     /* show fallback immediately, swap when ready */
font-display: fallback; /* tiny block period, short swap period */
font-display: optional; /* browser may skip custom font entirely */
Use font-display: swap

For body text, swap provides the best user experience: text is immediately visible in the fallback font, then re-rendered when the custom font finishes loading. For decorative fonts, consider optional.

Google Fonts

Google Fonts hosts free, open-source web fonts. You can load them with a <link> tag or an @import rule.

Method 1: Link Tag (Recommended)

HTML
<!-- In the <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=Inter:wght@400;500;600;700&display=swap"
      rel="stylesheet">

Method 2: CSS @import

CSS
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');

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

The <link> method is faster because the browser starts downloading the font stylesheet in parallel with the rest of your CSS. @import blocks rendering until the import is resolved, adding latency.

Fluid Typography with clamp()

The clamp() function lets text scale smoothly between a minimum and maximum size based on the viewport width — no media queries needed.

CSS
/* clamp(minimum, preferred, maximum) */
h1 {
  font-size: clamp(1.5rem, 4vw, 3rem);
}

p {
  font-size: clamp(0.9rem, 1.5vw, 1.125rem);
}

/* Fluid spacing too */
.section {
  padding: clamp(1rem, 3vw, 3rem);
}
Live Example — Fluid Typography with clamp()

This Heading Scales Fluidly

Resize the browser window to see this paragraph smoothly adjust. It will not go below 0.85rem or above 1.1rem, but between those bounds it scales proportionally with the viewport width. No media queries required!

Try resizing your browser window to see the text grow and shrink smoothly.

How clamp() Works

CSS
/*
  clamp(MIN, PREFERRED, MAX)

  - Below the breakpoint: font-size = MIN
  - In the sweet spot:    font-size = PREFERRED (scales with vw)
  - Above the breakpoint: font-size = MAX

  Example calculation:
  clamp(1rem, 2.5vw, 2rem)
  At 320px viewport:  2.5vw = 8px   -- clamps to 1rem (16px)
  At 800px viewport:  2.5vw = 20px  -- uses 20px (within range)
  At 1400px viewport: 2.5vw = 35px  -- clamps to 2rem (32px)
*/
Fluid Typography Formula

A common formula: font-size: clamp(minSize, calc(minSize + (maxSize - minSize) * (100vw - minViewport) / (maxViewport - minViewport)), maxSize). Or simply use the shortcut: pick your min/max sizes and use roughly 2vw to 5vw as the preferred value.

Common Gotchas

em Compounding

Nested em values compound. If a parent is 1.2em and a child is also 1.2em, the child renders at 1.2 x 1.2 = 1.44em of the grandparent. Use rem to avoid this trap.

Faux Bold & Italic

If you set font-weight: 700 but the loaded font only has 400, the browser will synthesize a "faux bold" that looks thicker but poorly kerned. Always load the actual weight variants you need via @font-face or Google Fonts.

text-overflow Needs Three Properties

text-overflow: ellipsis alone does nothing. You also need overflow: hidden and white-space: nowrap. All three are required for the ellipsis to appear.

Font Loading Flash (FOUT/FOIT)

FOUT (Flash of Unstyled Text): fallback font shown, then swapped. FOIT (Flash of Invisible Text): text hidden until font loads. Use font-display: swap and preload critical fonts to minimize these effects.

line-height on Inputs

Form inputs don't always inherit line-height from the body. Always explicitly set line-height on input, textarea, and button elements.

Pro Tips

System Font Stack

For maximum performance and a native feel, use the system font stack:
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

Optimal Measure (Line Length)

For comfortable reading, keep body text between 45 and 75 characters per line. Use max-width: 65ch on your text container — the ch unit equals the width of the "0" character.

Modular Scale

Use a mathematical ratio (e.g., 1.25, the "Major Third") to create harmonious heading sizes:
h4: 1rem, h3: 1.25rem, h2: 1.563rem, h1: 1.953rem.

Preload Critical Fonts

Add <link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin> in your <head> to start downloading fonts before CSS is even parsed.

font-variant-numeric for Numbers

Use font-variant-numeric: tabular-nums for tabular data (aligns columns of numbers) and font-variant-numeric: oldstyle-nums for body text (numbers that blend with lowercase letters).

Vertical Rhythm

Set all margins and padding as multiples of your base line-height to maintain a consistent vertical rhythm. If your line-height is 1.5rem, use 1.5rem, 3rem, and 4.5rem for spacing.

PreviousBox Model