HTML Guides for font-family
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.
The CSS font shorthand property has a specific syntax defined in the CSS specification. At minimum, it requires both a font-size and a font-family value. Optionally, you can prepend font-style, font-variant, and font-weight, and you can append a line-height value after the font-size using a slash separator. The full syntax looks like this:
font: [font-style] [font-variant] [font-weight] font-size[/line-height] font-family;
When the W3C validator reports that a value “is not a font-family value,” it means the parser reached a point in the font declaration where it expected to find a font family name but instead found something it couldn’t interpret as one. This often happens in two scenarios:
- Using font when you meant a specific property — For example, writing font: 300 when you only intended to set the font weight. The validator tries to parse 300 as a complete font value, and since there’s no font-size or font-family, it fails.
- Incomplete font shorthand — Providing some values but forgetting the mandatory font-family at the end, such as font: 300 16px without a family name.
This matters because browsers may ignore an invalid font declaration entirely, causing your text to render with default or inherited styles instead of what you intended. Keeping your CSS valid also ensures consistent behavior across different browsers and helps maintain clean, predictable stylesheets.
How to fix it:
- If you only need to set a single font-related property, use the specific property (font-weight, font-size, font-style, font-variant, or font-family) instead of the font shorthand.
- If you want to use the font shorthand, make sure you include at least font-size and font-family, and that all values appear in the correct order.
- Remember that the font shorthand resets any omitted font sub-properties to their initial values, so use it deliberately.
Examples
Incorrect: Using font to set only the weight
<p style="font: 300;">This text has an invalid font declaration.</p>
The validator reports that 300 is not a valid font-family value because the font shorthand expects at least a font-size and font-family.
Correct: Using font-weight directly
<p style="font-weight: 300;">This text has a light font weight.</p>
Incorrect: Missing font-family in the shorthand
<p style="font: italic 300 16px;">This is also invalid.</p>
Even though font-style, font-weight, and font-size are all present, the required font-family is missing.
Correct: Complete font shorthand
<p style="font: italic 300 16px/1.5 'Helvetica', sans-serif;">This is valid.</p>
This includes all components in the correct order: font-style, font-weight, font-size/line-height, and font-family.
Correct: Minimal valid font shorthand
<p style="font: 16px sans-serif;">Only size and family — the minimum required.</p>
Correct: Using individual properties instead of the shorthand
<p style="font-style: italic; font-weight: 300; font-size: 16px; line-height: 1.5; font-family: 'Helvetica', sans-serif;">
Each property set individually.
</p>
Using individual properties avoids the pitfalls of the shorthand and gives you explicit control without accidentally resetting other font sub-properties.
The <tt> element was a purely presentational element — it described how text should look (monospaced) rather than what the text meant. HTML5 removed it as part of a broader effort to separate content from presentation. Browsers still render <tt> for backward compatibility, but validators will flag it as obsolete, and its use is discouraged in all new code.
The key issue is that <tt> was used for many different purposes — displaying code snippets, keyboard input, sample output, variables, filenames, and more — yet it conveyed none of that meaning to assistive technologies or search engines. HTML5 provides dedicated semantic elements for most of these use cases, making your content more meaningful and accessible.
Choosing the Right Replacement
Before reaching for a generic <span>, consider what the monospaced text actually represents:
- Code: Use <code> for inline code fragments (e.g., variable names, short statements).
- Keyboard input: Use <kbd> for text the user should type.
- Sample output: Use <samp> for output from a program or system.
- Variables: Use <var> for mathematical or programming variables.
- No semantic meaning: Use a <span> with CSS when the monospaced styling is purely visual and none of the above elements apply.
All of these elements render in a monospaced font by default in most browsers (except <var>, which is typically italic). You can further style them with CSS as needed.
Examples
❌ Obsolete usage with <tt>
<p>Run the command <tt>npm install</tt> to install dependencies.</p>
<p>The variable <tt>x</tt> holds the result.</p>
<p>The output was <tt>Hello, world!</tt></p>
These all trigger the validator error: The “tt” element is obsolete. Use CSS instead.
✅ Fixed with semantic elements
<p>Run the command <kbd>npm install</kbd> to install dependencies.</p>
<p>The variable <var>x</var> holds the result.</p>
<p>The output was <samp>Hello, world!</samp></p>
Each replacement conveys the meaning of the text. <kbd> tells assistive technologies this is something the user types, <var> marks a variable, and <samp> indicates program output.
✅ Fixed with <code> for inline code
<p>Use the <code>Array.prototype.map()</code> method to transform each element.</p>
✅ Fixed with a <span> and CSS when no semantic element fits
If the monospaced text doesn’t represent code, input, output, or a variable — for example, a stylistic choice for a filename or an arbitrary design decision — use a <span> with CSS:
<p>Edit the file <span class="mono">config.yaml</span> to change the settings.</p>
.mono {
font-family: monospace;
}
This keeps your HTML valid and your styling in the CSS layer where it belongs.
✅ Block-level code with <pre> and <code>
If you previously used <tt> inside a <pre> block for multi-line code, the standard approach is to combine <pre> with <code>:
<pre><code>function greet(name) {
return "Hello, " + name;
}</code></pre>
Summary
Replace every <tt> element with the semantic HTML element that best describes its content — <code>, <kbd>, <samp>, or <var>. If none of these fit, use a <span> styled with font-family: monospace in CSS. This keeps your markup valid, meaningful, and accessible.
Ready to validate your sites?
Start your free trial today.