CSS Font Properties: 10 Code-Along Examples

Learn CSS typography by running it. Ten copy-and-run examples covering font-family stacks, relative sizes, weight, style, line-height, letter and word spacing, text-transform, small caps, font-stretch, and the font shorthand.

The font properties guide walks through everything that controls how text looks: the typeface, its size, weight and style, the spacing around letters and lines, and the shorthand that ties it all together. This workbook turns each property into a small example you can run and tweak. Every example is two files, index.html and styles.css, kept separate so the markup stays clean. Open each one, then change a value and reload to see the effect immediately.

1. font-family and the font stack

font-family is not a single font but an ordered list. The browser tries each in turn and uses the first one available, ending with a generic family as a guaranteed fallback. Quote any name that contains a space.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="stacked">The browser uses the first font in the list that it can find.</p>
</body>
</html>
.stacked {
/* try each in order; sans-serif is the safety net */
font-family: "Helvetica Neue", Arial, sans-serif;
font-size: 1.25rem;
}

Always end the stack with a generic family such as sans-serifserif, or monospace. If every named font is missing, the browser still picks something sensible from that category rather than falling back to its default.

2. font-size with relative units

Pixels are fixed; relative units scale. rem is measured against the root element’s font size (16px by default), so 1rem is 16px and 1.5rem is 24px. Using rem lets the whole interface resize from one place.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="small">0.875rem (14px)</p>
<p class="base">1rem (16px)</p>
<p class="large">1.5rem (24px)</p>
</body>
</html>
html { font-size: 16px; } /* the root size that rem refers to */
.small { font-size: 0.875rem; }
.base { font-size: 1rem; }
.large { font-size: 1.5rem; }

Change the html font-size to 20px and every rem-based size grows in proportion. That single point of control is why the guide recommends relative units over fixed pixels.

3. font-weight

font-weight sets boldness, either with keywords like normal and bold or with the numeric scale from 100 to 900. Numbers give finer control, where 400 is normal and 700 is bold.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="light">Weight 300 (light)</p>
<p class="regular">Weight 400 (normal)</p>
<p class="bold">Weight 700 (bold)</p>
</body>
</html>
.light { font-weight: 300; }
.regular { font-weight: 400; } /* same as normal */
.bold { font-weight: 700; } /* same as bold */

A weight only renders if the font actually ships that variant. Ask for 300 on a font with no light cut and the browser falls back to the nearest available weight, so test the weights you rely on.

4. font-style

font-style switches text between normalitalic, and oblique. Italic uses the font’s purpose-drawn cursive shapes where they exist; oblique simply slants the upright letters.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="normal">Normal upright text.</p>
<p class="italic">Italic text, drawn as a true cursive form.</p>
<p class="oblique">Oblique text, mechanically slanted.</p>
</body>
</html>
.normal { font-style: normal; }
.italic { font-style: italic; }
.oblique { font-style: oblique; }

For most fonts italic is what you want. Reach for font-style rather than the <i> tag when the slant is purely visual, since styling decisions belong in CSS, not the markup.

5. line-height

line-height controls the vertical space between lines. Use a unitless number, which multiplies the element’s font size, so 1.5means one and a half times the text size. Unitless values scale correctly when the font size changes.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="tight">Tight leading. This paragraph has lines packed closely together, which can feel cramped in longer blocks of text like this one.</p>
<p class="airy">Airy leading. The same paragraph with more room between lines, which is easier to read in longer passages such as this.</p>
</body>
</html>
p { max-width: 40ch; }
.tight { line-height: 1.1; }
.airy { line-height: 1.7; }

Around 1.4 to 1.6 is comfortable for body text. Always prefer the unitless form: set line-height: 1.5 and a child with a larger font size still gets proportional spacing, whereas a fixed 24px would not.

6. letter-spacing and word-spacing

letter-spacing adjusts the gap between characters and word-spacing the gap between words. Express letter-spacing in em so it scales with the font size. Small positive values can make uppercase headings more legible.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="tracked">WIDE TRACKED HEADING</p>
<p class="spaced">Extra space between these words.</p>
</body>
</html>
.tracked {
letter-spacing: 0.15em; /* scales with the font size */
font-weight: 700;
}
.spaced {
word-spacing: 0.5em;
}

A little letter-spacing helps all-caps text, which otherwise looks tight. Be sparing with lowercase body text, where added tracking usually hurts readability rather than helping it.

7. text-transform

text-transform changes the visual case without touching the underlying HTML. The text stays as written in the markup, which matters for accessibility and copy-paste, while the browser renders it uppercase, lowercase, or capitalised.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="upper">made uppercase by css</p>
<p class="caps">capitalise each word</p>
<p class="lower">LOWERCASED BY CSS</p>
</body>
</html>
.upper { text-transform: uppercase; }
.caps { text-transform: capitalize; }
.lower { text-transform: lowercase; }

Because the transform is presentational, a screen reader still reads the original text and a user copying it gets the real casing. Style the case in CSS rather than typing it in caps in your HTML.

8. font-variant for small caps

font-variant: small-caps renders lowercase letters as smaller uppercase forms while keeping the capitals full height. It is a classic touch for abbreviations, bylines, and elegant headings.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="smallcaps">Published by the Datalad Editorial Team</p>
</body>
</html>
.smallcaps {
font-variant: small-caps;
letter-spacing: 0.03em; /* a touch of tracking suits small caps */
font-size: 1.25rem;
}

The capital letters in “Datalad” stay tall while the rest become small capitals. Small caps read as more refined than full uppercase, which is why they suit running text where all-caps would shout.

9. font-stretch

font-stretch selects a narrower or wider cut of a typeface, from condensed through normal to expanded. It only has a visible effect when the font actually provides those width variants, so it is best paired with a font you know ships them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="condensed">Condensed width</p>
<p class="normal">Normal width</p>
<p class="expanded">Expanded width</p>
</body>
</html>
/* Effective only with fonts that include width variants */
.condensed { font-stretch: condensed; }
.normal { font-stretch: normal; }
.expanded { font-stretch: expanded; }

With a standard system font you may see little or no change, which is itself the lesson: font-stretch depends entirely on the font having the relevant cuts. Variable fonts, which carry a continuous width axis, are where it really comes alive.

10. The font shorthand

The font shorthand packs several properties into one declaration. The order matters: style, variant and weight first in any order, then the size with an optional /line-height, and finally the font-family, which must come last. Size and family are required.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<p class="long-form">
italic small-caps bold 1.25rem/1.6 "Helvetica Neue", Arial, sans-serif
</p>
<p class="shorthand">The same five properties in a single line.</p>
</body>
</html>
/* The verbose way */
.long-form {
font-style: italic;
font-variant: small-caps;
font-weight: bold;
font-size: 1.25rem;
line-height: 1.6;
font-family: "Helvetica Neue", Arial, sans-serif;
}
/* The same declaration, condensed */
.shorthand {
font: italic small-caps bold 1.25rem/1.6 "Helvetica Neue", Arial, sans-serif;
}

Both rules produce identical text. The shorthand is concise but unforgiving: omit the size or family and the whole declaration is ignored, and any property you leave out is reset to its default. Use it to set a complete font in one line, and fall back to the individual properties when you only want to change one thing.

Work through these and you will have touched every property from the main article, from the font stack to the shorthand. The guide’s advice holds throughout: prefer relative units so text scales cleanly, centralise your typography so one change updates the whole site, always provide a fallback family, and test on real devices since font availability and width variants differ between them. Once these properties are second nature, typography stops being guesswork and becomes a small set of dials you adjust with intent.

See you soon.

View Comments (1)

Leave a Reply

Prev Next

Subscribe to My Newsletter

Subscribe to my email newsletter to get the latest posts delivered right to your email. Pure inspiration, zero spam.

Discover more from Discuss Data Science, Machine Learning and Analytics

Subscribe now to keep reading and get access to the full archive.

Continue reading