Skip to main content
HTML Validation

CSS: “font-display”: Property “font-display” doesn't exist.

About This CSS Issue

font-display controls how a font face is displayed based on whether and when it has been downloaded and is ready to use. Its accepted values — auto, block, swap, fallback, and optional — determine the behavior during the font-loading timeline (block period, swap period, and failure period). Because it governs the loading behavior of a font face definition, it only makes sense within a @font-face rule, not as a property applied to an HTML element.

When you place font-display inside a regular selector like body or .heading, the CSS validator correctly flags it as an unknown property. Browsers will silently ignore it, meaning your intended font-loading strategy won’t take effect. Users may experience a flash of invisible text (FOIT) or other unwanted behavior because the browser falls back to its default font-display strategy.

Why this matters

  • Font-loading performance: Without a valid font-display descriptor in your @font-face rule, you lose control over how the browser handles text rendering while custom fonts load. Using font-display: swap, for example, ensures text remains visible with a fallback font until the custom font is ready — a key web performance best practice.
  • Standards compliance: The CSS Fonts Module Level 4 specification defines font-display exclusively as a @font-face descriptor. Using it elsewhere produces invalid CSS.
  • Silent failure: Browsers won’t throw visible errors — they simply ignore the invalid property, which can make it difficult to diagnose why your font-loading behavior isn’t working as expected.

How to fix it

  1. Remove font-display from any regular CSS rule (selectors like body, h1, .class, etc.).
  2. Add font-display inside the @font-face at-rule where you define your custom font.
  3. If you’re loading fonts via a third-party service (like Google Fonts), you can often append a &display=swap parameter to the font URL instead of writing your own @font-face block.

Examples

❌ Incorrect: font-display used as a CSS property

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

This triggers the validator error because font-display is not a valid CSS property for element selectors.

✅ Correct: font-display used inside @font-face

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/open-sans.woff2") format("woff2"),
       url("/fonts/open-sans.woff") format("woff");
  font-display: swap;
}

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

Here, font-display: swap is correctly placed inside the @font-face rule, telling the browser to immediately render text with a fallback font and then swap in “Open Sans” once it finishes loading.

✅ Correct: Using display=swap with Google Fonts

If you use Google Fonts, you don’t need to write your own @font-face block. Instead, add the display parameter to the URL:

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap">

Google Fonts will generate the @font-face rules with font-display: swap included automatically.

❌ Incorrect: font-display in a class selector

.heading {
  font-family: "Roboto", sans-serif;
  font-display: optional;
}

✅ Correct: Separate the descriptor from the styling rule

@font-face {
  font-family: "Roboto";
  src: url("/fonts/roboto.woff2") format("woff2");
  font-display: optional;
}

.heading {
  font-family: "Roboto", sans-serif;
}

The font-display: optional descriptor now correctly lives in the @font-face block, where it tells the browser to use the custom font only if it’s already cached — otherwise, stick with the fallback. The .heading rule simply references the font family by name.

Find issues like this automatically

Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.

Help us improve our guides

Was this guide helpful?

Ready to validate your sites?
Start your free trial today.