Skip to content

CSS Fonts

Learn how to work with fonts in CSS

At the dawn of the web you only had a handful of fonts you could choose from.

Thankfully today you can load any kind of font on your pages.

CSS has gained many nice capabilities over the years in regards to fonts.

The font property is the shorthand for a number of properties:

Let’s see each one of them and then we’ll cover font.

Then we’ll talk about how to load custom fonts, using @import or @font-face, or by loading a font stylesheet.

font-family

Sets the font family that the element will use.

Why “family”? Because what we know as a font is actually composed of several sub-fonts. which provide all the style (bold, italic, light..) we need.

Here’s an example from my Mac’s Font Book app - the Fira Code font family hosts several dedicated fonts underneath:

This property lets you select a specific font, for example:

body {
  font-family: Helvetica;
}

You can set multiple values, so the second option will be used if the first cannot be used for some reason (if it’s not found on the machine, or the network connection to download the font failed, for example):

body {
  font-family: Helvetica, Arial;
}

I used some specific fonts up to now, ones we call Web Safe Fonts, as they are pre-installed on different operating systems.

We divide them in Serif, Sans-Serif, and Monospace fonts. Here’s a list of some of the most popular ones:

Serif

Sans-Serif

Monospace

You can use all of those as font-family properties, but they are not guaranteed to be there for every system. Others exist, too, with a varying level of support.

You can also use generic names:

Those are typically used at the end of a font-family definition, to provide a fallback value in case nothing else can be applied:

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

font-weight

This property sets the width of a font. You can use those predefined values:

Or using the numeric keywords

where 100 is the lightest font, and 900 is the boldest.

Some of those numeric values might not map to a font, because that must be provided in the font family. When one is missing, CSS makes that number be at least as bold as the preceding one, so you might have numbers that point to the same font.

font-stretch

Allows to choose a narrow or wide face of the font, if available.

This is important: the font must be equipped with different faces.

Values allowed are, from narrower to wider:

font-style

Allows you to apply an italic style to a font:

p {
  font-style: italic;
}

This property also allows the values oblique and normal. There is very little, if any, difference between using italic and oblique. The first is easier to me, as HTML already offers an i element which means italic.

font-size

This property is used to determine the size of fonts.

You can pass 2 kinds of values:

  1. a length value, like px, em, rem etc, or a percentage
  2. a predefined value keyword

In the second case, the values you can use are:

Usage:

p {
  font-size: 20px;
}

li {
  font-size: medium;
}

font-variant

This property was originally used to change the text to small caps, and it had just 3 valid values:

Small caps means the text is rendered in “smaller caps” beside its uppercase letters.

font

The font property lets you apply different font properties in a single one, reducing the clutter.

We must at least set 2 properties, font-size and font-family, the others are optional:

body {
  font: 20px Helvetica;
}

If we add other properties, they need to be put in the correct order.

This is the order:

font: <font-stretch> <font-style> <font-variant> <font-weight> <font-size> <line-height> <font-family>;

Example:

body {
  font: italic bold 20px Helvetica;
}

section {
  font: small-caps bold 20px Helvetica;
}

Loading custom fonts using @font-face

@font-face lets you add a new font family name, and map it to a file that holds a font.

This font will be downloaded by the browser and used in the page, and it’s been such a fundamental change to typography on the web - we can now use any font we want.

We can add @font-face declarations directly into our CSS, or link to a CSS dedicated to importing the font.

In our CSS file we can also use @import to load that CSS file.

A @font-face declaration contains several properties we use to define the font, including src, the URI (one or more URIs) to the font. This follows the same-origin policy, which means fonts can only be downloaded form the current origin (domain + port + protocol).

Fonts are usually in the formats

The following properties allow us to define the properties to the font we are going to load, as we saw above:

A note on performance

Of course loading a font has performance implications which you must consider when creating the design of your page.


→ Here's my latest YouTube video

→ Get my CSS Handbook

→ I wrote 17 books to help you become a better developer, download them all at $0 cost by joining my newsletter

JOIN MY CODING BOOTCAMP, an amazing cohort course that will be a huge step up in your coding career - covering React, Next.js - next edition February 2025

Bootcamp 2025

Join the waiting list