Text and typography

The CSS Podcast - 036: Text & Typography

Text is one of the core building blocks of the web.

When making a website, you don't necessarily need to style your text; HTML actually has some pretty reasonable default styling.

However, text will likely make up the majority of your website, so it's worthwhile to add some styling to spruce it up. By changing a few basic properties, you can significantly improve the reading experience for your users!

In this module, we'll start with the @font-face rule, which lets you import custom fonts into your webpages. This ensures that you have the exact typography you need, independent of user-installed fonts.

Following that, we'll cover essential CSS font properties including font-family, font-style, font-weight, and font-size. These basics set the stage for manipulating text for both style and readability.

We'll also touch on paragraph-specific properties like text-indent and word-spacing, before concluding with advanced topics such as variable fonts and pseudo-elements, which further refine your typographic control.

Practical examples and tips will be provided throughout to solidify your understanding and application of these CSS techniques.

The @font-face rule

The @font-face CSS at-rule is instrumental in web design, letting you specify and use custom fonts to display text. The beauty of @font-face is in its versatility: it lets you source fonts from a remote server, or from a font installed on the user's device.

Syntax

@font-face {
  font-family: "Trickster";
  src:
    local("Trickster"),
    url("trickster-COLRv1.otf") format("opentype") tech(color-COLRv1),
    url("trickster-outline.otf") format("opentype"),
    url("trickster-outline.woff") format("woff")
}

Descriptors

ascent-override
Customizes the ascent metric, impacting the space above the baseline.
descent-override
Adjusts the descent metric, affecting the space below the baseline.
font-display
Controls the font's display behavior depending on its download status.
font-family
Names the font for use within font-related properties.
font-stretch
Sets acceptable horizontal scaling, specified as a single value or range.
font-style
Defines the font style, supporting angle ranges for oblique styles.
font-weight
Determines the font's weight or range of weights available.
font-feature-settings
Enables access to OpenType font features.
font-variation-settings
Provides fine-tuned control over variable font settings.
line-gap-override
Overrides the font's default line gap.
size-adjust
Applies a scaling factor to the font's outline and metrics.
src
Defines the font source, whether local or remote. This is required for the @font-face rule. Combining url() and local() within the src is a common strategy that uses a local font if available, reverting to a remote font file as a fallback. Browsers prioritize resources based on the order of declaration, so local() should typically precede url().
unicode-range
Limits the characters this font should be used for.

Description

@font-face frees designers from the constraints of "web-safe" fonts by letting them use custom typography. The local() function's ability to search for a font on the user's device offers a seamless experience that doesn't necessarily depend on an internet connection.

Font MIME types

Format MIME Type
TrueType font/ttf
OpenType font/otf
Web Open Font Format font/woff
Web Open Font Format 2 font/woff2

The difference between @font-face and font-family

In CSS, @font-face and font-family are often confused, but they serve distinct purposes.

As we've discussed, @font-face is a rule used to define any custom fonts you want to use in your web application. It tells the browser where to download the font, how to display it during loading (with the font-display property), and specifies which subset of characters to download (with the unicode-range).

In contrast, font-family is a CSS property used within a CSS rule to assign a particular font or a list of fonts to an element. The fonts listed under font-family can be web-safe fonts, system fonts, or custom fonts defined with @font-face.

To summarize, @font-face declares a font and gives it a name, and font-family applies this declared font to HTML elements.

Here's an example of using both:

<table>
  <thead>
    <tr>
      <th><p><pre>
@font-face {
  font-family: "CustomFont";
  src: url("customfont.woff2") format("woff2");
}

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

In this example, @font-face defines "CustomFont" and tells the browser where to find it. The font-family property then applies it to the body element, with Arial as a fallback if "CustomFont" isn't available.

Change the typeface

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Use font-family to change the typeface of your text.

The font-family property accepts a comma-separated list of strings, either referring to specific or generic font families. Specific font families are quoted strings, such as "Helvetica", "EB Garamond", or "Times New Roman". Generic font families are keywords such as serif, sans-serif, and monospace (find the full list of options on MDN). The browser will display the first available typeface from the provided list.

When using font-family, you should specify at least one generic font family in case the user's browser doesn't have your preferred fonts. Generally, the fallback generic font family should be similar to your preferred fonts: if using font-family: "Helvetica" (a sans-serif font family), your fallback should be sans-serif to match.

Use italic and oblique fonts

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Use font-style to set whether text should be italic or not. font-style accepts one of the following keywords: normal, italic, and oblique.

Make text bold

Browser Support

  • Chrome: 2.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Use font-weight to set the "boldness" of text. This property accepts keyword values (normal, bold), relative keyword values (lighter, bolder), and numeric values (100 to 900).

The keywords normal and bold are equivalent to the numeric values 400 and 700, respectively.

The keywords lighter and bolder are calculated relative to the parent element. See MDN's Meaning of Relative Weights for a handy chart showing how this value is determined.

Change the size of text

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Use font-size to control the size of your text elements. This property accepts length values, percentages, and a handful of keyword values.

In addition to length and percentage values, font-size accepts some absolute keyword values (xx-small, x-small, small, medium, large, x-large, xx-large) and a couple of relative keyword values (smaller, larger). The relative values are relative to the parent element's font-size.

Change the space between lines

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Use line-height to specify the height of each line in an element. This property accepts either a number, length, percentage, or the keyword normal. Generally, it's recommended to use a number instead of a length or percentage to avoid issues with inheritance.

Change the space between characters

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Source

Use letter-spacing to control the amount of horizontal space between characters in your text. This property accepts length values such as em,