HTML Guides for font-display
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
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-displaydescriptor in your@font-facerule, you lose control over how the browser handles text rendering while custom fonts load. Usingfont-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-displayexclusively as a@font-facedescriptor. 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
- Remove
font-displayfrom any regular CSS rule (selectors likebody,h1,.class, etc.). - Add
font-displayinside the@font-faceat-rule where you define your custom font. - If you're loading fonts via a third-party service (like Google Fonts), you can often append a
&display=swapparameter to the font URL instead of writing your own@font-faceblock.
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:
<linkrel="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.
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
Pro Trial
Full Pro access. Cancel anytime.
Start Pro Trial →Join teams across 40+ countries