HTML Guides for css
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 <table> element in HTML supports a limited set of attributes — primarily global attributes like class, id, and style. The height attribute was never part of the HTML standard for tables (unlike width, which was valid in HTML 4 but has since been deprecated). Despite this, many browsers historically accepted height on <table> as a non-standard extension, which led to its widespread but incorrect use.
Because height is not a recognized attribute on <table>, using it means your markup is invalid and may behave inconsistently across browsers. Some browsers might honor it, others might ignore it entirely, and future browser versions could change their behavior at any time. Relying on non-standard attributes makes your code fragile and harder to maintain.
The fix is straightforward: remove the height attribute from the <table> element and use CSS to set the desired height. You can apply the CSS inline via the style attribute, or better yet, use an external or internal stylesheet with a class or ID selector.
Examples
❌ Invalid: height attribute on <table>
<table height="300">
<tr>
<td>Name</td>
<td>Score</td>
</tr>
<tr>
<td>Alice</td>
<td>95</td>
</tr>
</table>
This triggers the validator error: Attribute “height” not allowed on element “table” at this point.
✅ Fixed: Using inline CSS
<table style="height: 300px;">
<tr>
<td>Name</td>
<td>Score</td>
</tr>
<tr>
<td>Alice</td>
<td>95</td>
</tr>
</table>
✅ Fixed: Using a CSS class (preferred)
<style>
.tall-table {
height: 300px;
}
</style>
<table class="tall-table">
<tr>
<td>Name</td>
<td>Score</td>
</tr>
<tr>
<td>Alice</td>
<td>95</td>
</tr>
</table>
Using a class keeps your HTML clean and makes it easy to adjust the styling later without touching the markup. Note that min-height is often a better choice than height for tables, since table content can naturally grow beyond a fixed height, and min-height ensures the table is at least a certain size without clipping content.
The device-width and device-height media features (along with their min- and max- prefixed variants) originally referred to the physical dimensions of the device’s entire screen, regardless of how much space was actually available to the document. In practice, this distinction caused confusion and inconsistent behavior across browsers. On most modern devices and browsers, device-width and width return the same value anyway, making the device-* variants redundant.
The device-* media features were frequently used as a proxy to detect mobile devices, but this was never a reliable approach. A narrow browser window on a desktop monitor would not trigger a max-device-width query even though the available layout space was small. Conversely, modern phones and tablets with high-resolution screens can report large device widths that don’t reflect the actual CSS viewport size. The viewport-based alternatives (width, height, aspect-ratio) more accurately represent the space available for rendering your content.
Using deprecated media features causes W3C validation warnings and may eventually lose browser support entirely. Replacing them ensures your stylesheets are future-proof, standards-compliant, and behave consistently across all devices and window sizes.
How to fix it
Replace any device-width, device-height, or device-aspect-ratio media feature (including min- and max- prefixed versions) with the corresponding viewport-based equivalent:
| Deprecated feature | Replacement |
|---|---|
| device-width | width |
| min-device-width | min-width |
| max-device-width | max-width |
| device-height | height |
| min-device-height | min-height |
| max-device-height | max-height |
| device-aspect-ratio | aspect-ratio |
The width media feature describes the width of the viewport (the targeted display area of the output device), including the size of a rendered scroll bar if any. This is the value you almost always want when writing responsive styles.
Examples
Incorrect: using deprecated max-device-width
This triggers the validation error because max-device-width is deprecated:
<link rel="stylesheet" media="only screen and (max-device-width: 768px)" href="mobile.css">
Correct: using max-width instead
Replace max-device-width with max-width to query the viewport width:
<link rel="stylesheet" media="only screen and (max-width: 768px)" href="mobile.css">
Incorrect: using deprecated min-device-width in a range
<link rel="stylesheet" media="screen and (min-device-width: 768px) and (max-device-width: 1024px)" href="tablet.css">
Correct: using viewport-based equivalents
<link rel="stylesheet" media="screen and (min-width: 768px) and (max-width: 1024px)" href="tablet.css">
Incorrect: using deprecated device-aspect-ratio
<link rel="stylesheet" media="screen and (device-aspect-ratio: 16/9)" href="widescreen.css">
Correct: using aspect-ratio
<link rel="stylesheet" media="screen and (aspect-ratio: 16/9)" href="widescreen.css">
Applying the same fix in CSS @media rules
The same deprecation applies to @media rules inside stylesheets. While the W3C validator specifically flags the media attribute on <link> elements, you should update your CSS as well:
/* Deprecated */
@media only screen and (max-device-width: 768px) {
.sidebar { display: none; }
}
/* Correct */
@media only screen and (max-width: 768px) {
.sidebar { display: none; }
}
If your site relies on a <meta name="viewport"> tag (as most responsive sites do), the viewport width already matches the device’s CSS pixel width, so switching from device-width to width will produce identical results in virtually all cases.
The device-width, device-height, and device-aspect-ratio media features (including their min- and max- prefixed variants) refer to the physical dimensions of the entire screen, not the available space where your content is actually rendered. This distinction matters because the viewport size — the area your page occupies — can differ significantly from the full device screen size. For example, a browser window might not be maximized, or browser chrome might consume screen real estate. Using device-based queries means your responsive breakpoints may not match what users actually see.
These features were also commonly used as a proxy for detecting mobile devices, but this approach is unreliable. A small-screened laptop and a large tablet can have similar device widths, making device-based detection a poor heuristic. The W3C deprecated these features and recommends using viewport-based alternatives that more accurately reflect the rendering context of your document.
Beyond standards compliance, using deprecated media features can cause issues with future browser support. While current browsers still recognize them, there is no guarantee they will continue to do so. Replacing them now ensures your stylesheets remain functional and forward-compatible.
How to fix it
Replace each deprecated device-* media feature with its viewport-based equivalent:
| Deprecated feature | Replacement |
|---|---|
| device-width | width |
| min-device-width | min-width |
| max-device-width | max-width |
| device-height | height |
| min-device-height | min-height |
| max-device-height | max-height |
| device-aspect-ratio | aspect-ratio |
| min-device-aspect-ratio | min-aspect-ratio |
| max-device-aspect-ratio | max-aspect-ratio |
The width media feature describes the width of the targeted display area of the output device. For continuous media, this is the width of the viewport including the size of a rendered scroll bar (if any). This is almost always the value you actually want when building responsive layouts.
Examples
Incorrect: using deprecated min-device-width
This triggers the validation error because min-device-width is deprecated:
<link rel="stylesheet" media="only screen and (min-device-width: 768px)" href="tablet.css">
Correct: using min-width instead
Replace min-device-width with min-width to query the viewport width:
<link rel="stylesheet" media="only screen and (min-width: 768px)" href="tablet.css">
Incorrect: using max-device-width for a mobile breakpoint
<link rel="stylesheet" media="screen and (max-device-width: 480px)" href="mobile.css">
Correct: using max-width
<link rel="stylesheet" media="screen and (max-width: 480px)" href="mobile.css">
Incorrect: using device-aspect-ratio
<link rel="stylesheet" media="screen and (device-aspect-ratio: 16/9)" href="widescreen.css">
Correct: using aspect-ratio
<link rel="stylesheet" media="screen and (aspect-ratio: 16/9)" href="widescreen.css">
Incorrect: combining multiple deprecated features
<link rel="stylesheet" media="screen and (min-device-width: 768px) and (max-device-width: 1024px)" href="tablet.css">
Correct: using viewport-based equivalents
<link rel="stylesheet" media="screen and (min-width: 768px) and (max-width: 1024px)" href="tablet.css">
The same replacements apply when these deprecated features appear in CSS @media rules or in the media attribute on <style> and <source> elements. Updating them across your entire codebase ensures consistent, standards-compliant responsive behavior.
The sizes attribute works together with srcset to help the browser choose the most appropriate image source for the current layout. It accepts a comma-separated list of entries, where each entry is an optional media condition followed by a CSS length value (called a “source size value”). The browser evaluates these entries to determine the intended display width of the image before it downloads it. Valid length values include viewport-relative units like 100vw, absolute units like 472px, or calc() expressions like calc(100vw - 2rem).
The value auto was not part of the original HTML specification for the sizes attribute. However, the sizes="auto" value has been added to the HTML living standard specifically for use with lazy-loaded images (loading="lazy"). When both loading="lazy" and sizes="auto" are present, the browser can defer size calculation until layout time, since the image won’t be fetched immediately anyway. Some validators may not yet recognize this newer addition, or the error may appear because auto is being used without loading="lazy", or combined incorrectly with other size entries like sizes="auto, 100vw".
This validation error matters for several reasons. First, if the browser doesn’t understand the sizes value, it may fall back to a default of 100vw, which could cause it to download a larger image than necessary, hurting performance. Second, malformed attribute values can lead to unpredictable behavior across different browsers. Third, standards compliance ensures your markup works reliably now and in the future.
How to Fix
You have a few options depending on your situation:
-
Replace auto with a valid CSS length. If you know the intended display size of the image, specify it directly. This is the most broadly compatible approach.
-
Use sizes="auto" only with loading="lazy". If you want the browser to automatically determine the size, ensure you also include loading="lazy" and a width attribute on the image. Note that some validators may still flag this until they update their rules.
-
Remove auto from a comma-separated list. If you have something like sizes="auto, (max-width: 600px) 100vw, 50vw", remove the auto entry entirely.
Examples
Incorrect: Using auto without lazy loading
This triggers the validation error because auto is not a valid CSS length in the traditional sizes syntax.
<img
src="image.jpg"
srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1000w"
sizes="auto, 100vw"
alt="A scenic mountain landscape"
>
Fixed: Using a valid CSS length value
Replace auto with a concrete size or a set of media-conditioned sizes.
<img
src="image.jpg"
srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1000w"
sizes="(max-width: 472px) 100vw, 472px"
alt="A scenic mountain landscape"
>
In this example, when the viewport is 472 pixels wide or smaller, the image takes up the full viewport width (100vw). For wider viewports, the browser knows the image will display at 472px wide and selects the best source from srcset accordingly.
Fixed: Using auto with lazy loading
If you want the browser to determine the display size automatically, pair sizes="auto" with loading="lazy" and explicit dimensions.
<img
src="image.jpg"
srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1000w"
sizes="auto"
width="600"
height="400"
loading="lazy"
alt="A scenic mountain landscape"
>
The width and height attributes help the browser reserve the correct space in the layout, and loading="lazy" allows the browser to defer both loading and size calculation until the image is near the viewport.
Fixed: Using calc() for dynamic sizing
If your image sits inside a container with padding, you can use calc() for a precise size hint.
<img
src="image.jpg"
srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1000w"
sizes="calc(100vw - 2rem)"
alt="A scenic mountain landscape"
>
The align-items property controls how flex or grid items are aligned along the cross axis of their container. While many CSS properties accept auto as a value, align-items is not one of them. The CSS specification defines a specific set of accepted values, and using auto will cause the declaration to be ignored by browsers, potentially breaking your intended layout.
This mistake often stems from confusion with the related property align-self, which does accept auto as its default value. When align-self is set to auto, it defers to the parent container’s align-items value. However, align-items itself has no such delegation mechanism — it is the property that sets the default alignment for all items in the container.
The valid values for align-items include:
- normal — behaves as stretch in flex containers and has context-dependent behavior in other layout modes.
- stretch — items are stretched to fill the container along the cross axis (the default behavior in flexbox).
- center — items are centered along the cross axis.
- flex-start / start — items are aligned to the start of the cross axis.
- flex-end / end — items are aligned to the end of the cross axis.
- baseline / first baseline / last baseline — items are aligned based on their text baselines.
- self-start / self-end — items are aligned based on their own writing mode.
If you intended the default behavior, use stretch (for flexbox) or normal. If you were trying to reset the property, use initial, unset, or revert instead of auto.
Examples
Incorrect: using auto as a value
<div style="display: flex; align-items: auto;">
<p>Item one</p>
<p>Item two</p>
</div>
This triggers the validation error because auto is not a recognized value for align-items.
Fixed: using stretch for default flexbox behavior
<div style="display: flex; align-items: stretch;">
<p>Item one</p>
<p>Item two</p>
</div>
Fixed: using center to center items
<div style="display: flex; align-items: center;">
<p>Item one</p>
<p>Item two</p>
</div>
Fixed: using flex-start to align items to the top
<div style="display: flex; align-items: flex-start;">
<p>Item one</p>
<p>Item two</p>
</div>
Correct use of auto with align-self
If your intention was to let a specific child item defer to its parent’s alignment, use align-self: auto on the child element instead:
<div style="display: flex; align-items: center;">
<p>Centered item</p>
<p style="align-self: auto;">Also centered (defers to parent)</p>
<p style="align-self: flex-end;">Aligned to the end</p>
</div>
Here, align-self: auto is valid on individual items and tells them to inherit the align-items value from the container.
The aspect-ratio CSS property defines the preferred width-to-height ratio of an element’s box. Browsers use this ratio when calculating auto sizes and performing other layout functions, adjusting the element’s dimensions to maintain the specified proportion even as the parent container or viewport changes size.
The ratio is expressed as <width> / <height>. If the slash and height portion are omitted, height defaults to 1. So aspect-ratio: 2 is equivalent to aspect-ratio: 2 / 1. The property also accepts the auto keyword, which tells the element to use its intrinsic aspect ratio (if it has one), and a combined form like auto 3 / 4, which prefers the intrinsic ratio but falls back to the specified one.
This validation error typically occurs for several reasons:
- Using invalid separators or syntax, such as a colon (:) instead of a slash (/), e.g., aspect-ratio: 16:9.
- Providing units, such as aspect-ratio: 16px / 9px. The values must be unitless positive numbers.
- Using zero or negative numbers, which are not valid. Both parts of the ratio must be positive (> 0).
- Providing a string or unrecognized keyword, such as aspect-ratio: wide or aspect-ratio: "16/9".
- Missing spaces around the slash, though this is less common — 16/9 may work in browsers but the canonical form uses spaces: 16 / 9.
- Using the property in inline style attributes validated against an older CSS level where aspect-ratio wasn’t yet recognized by the validator.
Getting this value right matters for layout consistency across browsers. An invalid value will be ignored entirely by the browser, meaning the element won’t maintain any aspect ratio, potentially breaking your design. It’s especially important for responsive images, video containers, and card layouts where maintaining proportions is critical.
Examples
Incorrect: using a colon as the separator
<div style="aspect-ratio: 16:9; width: 100%;"></div>
The colon syntax (common in video specifications) is not valid CSS. The validator will reject 16:9 as an aspect-ratio value.
Incorrect: using units in the ratio
<div style="aspect-ratio: 16px / 9px; width: 100%;"></div>
The ratio values must be unitless numbers. Adding px or any other unit makes the value invalid.
Incorrect: using zero in the ratio
<div style="aspect-ratio: 0 / 1; width: 100%;"></div>
Both numbers in the ratio must be strictly positive. Zero is not allowed.
Correct: standard ratio with a slash
<div style="aspect-ratio: 16 / 9; width: 100%;"></div>
Correct: single number (height defaults to 1)
<div style="aspect-ratio: 2; width: 100%;"></div>
This is equivalent to aspect-ratio: 2 / 1.
Correct: square ratio
<div style="aspect-ratio: 1 / 1; width: 100%;"></div>
Correct: using the auto keyword
<img src="photo.jpg" alt="A landscape photo" style="aspect-ratio: auto; width: 100%;">
The element uses its intrinsic aspect ratio if available.
Correct: combining auto with a fallback ratio
<img src="photo.jpg" alt="A landscape photo" style="aspect-ratio: auto 4 / 3; width: 100%;">
The browser prefers the image’s intrinsic ratio, but if it hasn’t loaded yet or has no intrinsic ratio, it falls back to 4 / 3. This is useful for preventing layout shift while images load.
Correct: using global CSS values
<div style="aspect-ratio: inherit; width: 100%;"></div>
Global values like inherit, initial, unset, revert, and revert-layer are also valid.
When you write a hex color in CSS, the # symbol must be followed by exactly 3, 4, 6, or 8 hexadecimal digits (characters 0–9 and a–f). Writing background-color: #; or background-color: #; means the CSS parser encounters the statement-ending semicolon immediately after #, with no color data. The parser cannot interpret this as a valid token, so it throws a lexical error.
This commonly happens when:
- A color value is accidentally deleted or left as a placeholder during development.
- A template engine or CMS outputs an empty variable where a color value was expected (e.g., background-color: #{{ color }}; where color is empty).
- A hex value is truncated, such as #f or #zz, containing an invalid number of digits or non-hex characters.
While most browsers will silently ignore the invalid declaration and fall back to the inherited or default background color, this creates unpredictable behavior. The element may render differently than intended, and the invalid CSS clutters your codebase. Fixing it ensures consistent rendering and standards compliance.
How to fix it
- Find the error location. The validator message includes the line and column number — go to that exact spot in your HTML or CSS file.
- Look at the background-color value. You’ll likely see # followed immediately by ;, or a # with an incomplete or invalid hex string.
- Provide a valid color value. Replace the broken value with a proper hex code, a color keyword, or a functional notation like rgb() or hsl().
If the color value comes from a dynamic source (like a CMS or JavaScript variable), add a fallback so an empty value doesn’t produce invalid CSS.
Examples
❌ Incomplete hex value (triggers the error)
<div style="background-color: #;">
Hello
</div>
The # has no hex digits before the semicolon, causing the lexical error.
✅ Fixed with a valid hex color
<div style="background-color: #ffffff;">
Hello
</div>
❌ Truncated or invalid hex digits
<div style="background-color: #g3;">
Hello
</div>
The character g is not a valid hexadecimal digit, and two digits is not a valid hex color length.
✅ Fixed with a proper 3-digit shorthand hex color
<div style="background-color: #f0f;">
Hello
</div>
✅ Alternative valid color formats
Any of these are valid replacements for a broken hex value:
/* 6-digit hex */
background-color: #1a2b3c;
/* 3-digit shorthand hex */
background-color: #abc;
/* 8-digit hex with alpha */
background-color: #1a2b3cff;
/* Named color keyword */
background-color: white;
/* RGB functional notation */
background-color: rgb(255, 255, 255);
/* RGBA with transparency */
background-color: rgba(0, 0, 0, 0.5);
/* HSL functional notation */
background-color: hsl(210, 50%, 60%);
/* HSLA with transparency */
background-color: hsla(210, 50%, 60%, 0.8);
✅ Defensive approach for dynamic values
If a CMS or templating system inserts the color, consider providing a fallback so an empty value doesn’t break your CSS:
<div style="background-color: #f0f0f0;">
Content with a safe default background
</div>
In your template logic, ensure empty color values either output a sensible default or omit the style attribute entirely rather than producing background-color: #;.
The background-color property accepts a specific set of color value types defined in the CSS Color specification. When you provide something that doesn’t match any of these types — like a plain number, a misspelled keyword, or a malformed hex code — the validator flags it as an invalid value.
Common mistakes that trigger this error include:
- Bare numbers like 0 or 255 — numbers alone aren’t colors, even if you intended black or white.
- Misspelled color keywords like grren instead of green, or trasparent instead of transparent.
- Malformed hex codes like #GGG, #12345, or missing the # prefix entirely.
- Incorrect function syntax like rgb(255 0 0 0.5) when mixing legacy comma syntax with modern space syntax improperly, or using rgba with only three arguments.
- Invalid units or strings like background-color: 10px or background-color: "red" (color values should not be quoted).
While browsers are generally forgiving and will simply ignore an invalid background-color declaration, this means your intended styling silently fails. The element falls back to its inherited or default background, which can cause visual bugs, poor contrast, or accessibility issues that are hard to track down. Validating your CSS catches these problems early.
Valid color formats
The background-color property accepts these value types:
- Named keywords: red, blue, transparent, currentcolor, etc.
- Hex notation: #rgb, #rrggbb, #rgba, #rrggbbaa
- RGB/RGBA: rgb(255, 0, 0) or rgb(255 0 0 / 0.5)
- HSL/HSLA: hsl(120, 100%, 50%) or hsl(120 100% 50% / 0.5)
- The keyword inherit, initial, unset, or revert
Examples
Invalid: bare number as a color
A plain number like 0 is not a valid color value, even though black could be represented as all zeros in RGB.
<style>
.banner {
background-color: 0;
}
</style>
Invalid: misspelled keyword
<style>
.banner {
background-color: trasparent;
}
</style>
Invalid: quoted string
Color values must not be wrapped in quotes.
<style>
.banner {
background-color: "red";
}
</style>
Invalid: malformed hex code
Hex codes must be 3, 4, 6, or 8 characters after the #.
<style>
.banner {
background-color: #12345;
}
</style>
Fixed: using a named color keyword
<style>
.banner {
background-color: black;
}
</style>
Fixed: using a hex color
<style>
.banner {
background-color: #000000;
}
</style>
Fixed: using rgb() notation
<style>
.banner {
background-color: rgb(0, 0, 0);
}
</style>
Fixed: using rgba() for semi-transparency
<style>
.banner {
background-color: rgba(0, 0, 0, 0.5);
}
</style>
Fixed: using hsl() notation
<style>
.banner {
background-color: hsl(210, 50%, 40%);
}
</style>
Fixed: using transparent
<style>
.banner {
background-color: transparent;
}
</style>
When the CSS parser encounters a background-image value it cannot understand, it flags a parse error. This doesn’t necessarily mean the browser won’t render your styles — browsers are often more forgiving than validators — but it does indicate that your CSS doesn’t conform to the specification. Invalid CSS can lead to unpredictable rendering across different browsers, makes your code harder to maintain, and may cause styles to silently fail in certain environments.
Common causes of this error include:
- Missing the url() function around image paths.
- Unquoted or improperly quoted URLs containing special characters like spaces or parentheses.
- Typos in CSS function names (e.g., lnear-gradient instead of linear-gradient).
- Using vendor-prefixed values (e.g., -webkit-linear-gradient) in contexts where the validator expects standard CSS.
- Invalid gradient syntax, such as missing color stops, incorrect angle units, or malformed function arguments.
- Using CSS custom properties (variables) or newer syntax in a style attribute, which the validator’s CSS parser may not fully support.
To fix this, review the exact background-image declaration the validator is pointing to. Make sure all URLs are wrapped in url(), all gradients use correct function names and valid arguments, and all strings are properly quoted and closed.
Examples
Missing url() function
A bare file path without the url() wrapper is invalid:
<!-- ❌ Parse error: missing url() -->
<div style="background-image: /images/hero.jpg;"></div>
Wrap the path in url():
<!-- ✅ Correct -->
<div style="background-image: url('/images/hero.jpg');"></div>
Typo in gradient function name
<!-- ❌ Parse error: misspelled function -->
<div style="background-image: lnear-gradient(to right, red, blue);"></div>
<!-- ✅ Correct -->
<div style="background-image: linear-gradient(to right, red, blue);"></div>
Invalid gradient syntax
Missing color stops or using incorrect angle notation causes parse errors:
<!-- ❌ Parse error: invalid angle unit and missing second color stop -->
<div style="background-image: linear-gradient(45, red);"></div>
Angles need a unit (like deg), and gradients need at least two color stops:
<!-- ✅ Correct -->
<div style="background-image: linear-gradient(45deg, red, blue);"></div>
Unescaped special characters in URL
File paths with spaces or parentheses need to be quoted:
<!-- ❌ Parse error: unquoted URL with spaces -->
<div style="background-image: url(/images/my hero image.jpg);"></div>
<!-- ✅ Correct: quoted URL -->
<div style="background-image: url('/images/my hero image.jpg');"></div>
Vendor-prefixed values
Using non-standard prefixed syntax can trigger a parse error in the validator:
<!-- ❌ Parse error: vendor prefix not recognized by validator -->
<div style="background-image: -webkit-linear-gradient(left, red, blue);"></div>
Use the standard, unprefixed syntax instead. Modern browsers no longer need the prefix for gradients:
<!-- ✅ Correct: standard syntax -->
<div style="background-image: linear-gradient(to right, red, blue);"></div>
Multiple backgrounds with incorrect separator
Multiple background images must be separated by commas, not semicolons or spaces:
<!-- ❌ Parse error: wrong separator -->
<div style="background-image: url('a.png') url('b.png');"></div>
<!-- ✅ Correct: comma-separated -->
<div style="background-image: url('a.png'), url('b.png');"></div>
Moving styles to an external stylesheet
If the validator struggles with complex background-image values in inline style attributes, consider moving the CSS to a <style> block or external stylesheet, where the validator’s CSS parser handles them more reliably:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Background Image Example</title>
<style>
.hero {
background-image: url('hero.jpg');
background-size: cover;
}
</style>
</head>
<body>
<div class="hero"></div>
</body>
</html>
The border-color property sets the color of an element’s four borders. When the W3C validator reports that a given value “is not a border-color value,” it means the value you provided doesn’t match any recognized CSS color format. Common mistakes that trigger this error include using a bare number like 0 instead of a color, misspelling a color keyword (e.g., grren instead of green), forgetting the # prefix on a hex code, or passing an invalid argument to a color function.
This matters because browsers handle invalid CSS values unpredictably. When a browser encounters an unrecognized border-color value, it discards the entire declaration and falls back to the inherited or initial value (typically currentcolor). This can lead to inconsistent rendering across browsers and make your design behave in unexpected ways. Writing valid CSS ensures predictable, cross-browser results and keeps your stylesheets maintainable.
Valid color formats
The CSS border-color property accepts any valid <color> value, including:
- Named keywords — red, blue, transparent, currentcolor, etc.
- Hexadecimal — #rgb, #rrggbb, #rgba, #rrggbbaa
- rgb() / rgba() — rgb(255, 0, 0) or rgb(255 0 0 / 50%)
- hsl() / hsla() — hsl(0, 100%, 50%) or hsl(0 100% 50% / 0.5)
You can also specify one to four color values to target individual sides (top, right, bottom, left), following the standard CSS shorthand pattern.
Examples
Invalid: bare number instead of a color
A number like 0 is not a valid color value and triggers the error:
<style>
.box {
border: 1px solid;
border-color: 0;
}
</style>
Invalid: misspelled color keyword
Typos in color names are not recognized by CSS:
<style>
.box {
border: 1px solid;
border-color: grren;
}
</style>
Invalid: hex code missing the # prefix
Without the leading #, the value is treated as an unknown keyword:
<style>
.box {
border: 1px solid;
border-color: ff0000;
}
</style>
Fixed: using a named color keyword
<style>
.box {
border: 1px solid;
border-color: green;
}
</style>
Fixed: using a hexadecimal value
<style>
.box {
border: 1px solid;
border-color: #00ff00;
}
</style>
Fixed: using rgb() functional notation
<style>
.box {
border: 1px solid;
border-color: rgb(0, 128, 0);
}
</style>
Fixed: using hsl() functional notation
<style>
.box {
border: 1px solid;
border-color: hsl(120, 100%, 25%);
}
</style>
Fixed: setting different colors per side
You can provide up to four valid color values to control each border individually (top, right, bottom, left):
<style>
.box {
border: 1px solid;
border-color: red green blue orange;
}
</style>
Fixed: using transparent or currentcolor
The special keywords transparent and currentcolor are also valid:
<style>
.box {
border: 1px solid;
border-color: transparent;
}
.highlight {
color: navy;
border: 2px solid;
border-color: currentcolor;
}
</style>
If you’re unsure whether a value is a valid CSS color, check the MDN <color> data type reference for the complete list of accepted formats.
The border-radius property controls the rounding of an element’s corners. Its valid values include lengths (e.g., 5px, 1em), percentages (e.g., 50%), and CSS-wide keywords like inherit, initial, and unset. Unlike many other border-related properties, border-radius has no none keyword in its value syntax.
This confusion typically arises because developers associate “no effect” with the keyword none, which works for properties like border: none or text-decoration: none. However, border-radius describes a geometric measurement — the radius of the corner curve — so “zero radius” (0) is the correct way to express no rounding.
Using an invalid value means the browser will ignore the entire declaration. This can lead to unexpected results: if a parent stylesheet or an earlier rule sets a border-radius, your none declaration won’t override it, and the element will retain its rounded corners. Fixing this ensures your CSS is standards-compliant, behaves predictably across browsers, and passes W3C validation.
How to fix it
- To remove rounding, replace none with 0.
- To set a specific radius, use a valid length (5px, 0.5em), a percentage (50%), or a CSS-wide keyword (inherit, initial, unset).
- The same rule applies to the longhand properties: border-top-left-radius, border-top-right-radius, border-bottom-right-radius, and border-bottom-left-radius.
Examples
Incorrect: using none
<style>
.box {
border-radius: none; /* "none" is not a valid border-radius value */
}
</style>
<div class="box">Content</div>
Correct: removing rounded corners with 0
<style>
.box {
border-radius: 0;
}
</style>
<div class="box">Content</div>
Correct: applying a specific radius
<style>
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
}
.rounded {
border-radius: 8px;
}
.pill {
border-radius: 9999px;
}
</style>
<div class="circle">Circle</div>
<div class="rounded">Rounded</div>
<div class="pill">Pill shape</div>
Correct: resetting to the initial value
If you need to undo a border-radius set by another rule, you can use initial or unset, both of which resolve to 0:
<style>
.card {
border-radius: 12px;
}
.card.sharp {
border-radius: initial; /* Resets to 0 */
}
</style>
<div class="card">Rounded card</div>
<div class="card sharp">Sharp-cornered card</div>
The border shorthand property accepts up to three values: a width (e.g., 1px), a style (e.g., solid), and a color (e.g., black). When the validator encounters "undefined" in the color position, it rightfully rejects it because undefined is not a recognized CSS color keyword, hex value, or color function.
This issue most commonly appears in projects that use JavaScript to dynamically set inline styles. When a variable intended to hold a color value is undefined—perhaps because it wasn’t initialized, a configuration value is missing, or a function didn’t return a result—the rendered HTML ends up with a literal style="border: 1px solid undefined" in the markup. Build tools, templating engines, or server-side rendering can also produce this output if a variable isn’t properly resolved.
Beyond failing validation, this is a real problem because browsers will discard the entire border declaration when they encounter an invalid value. This means the border won’t render at all, which may break your layout or visual design in ways that are hard to debug. Ensuring valid CSS values keeps your styling predictable across all browsers.
How to fix it
- Check for dynamic values. If the color is set via JavaScript or a templating engine, ensure the variable always resolves to a valid color string. Add fallback values or default assignments.
- Replace the invalid value. Substitute undefined with a proper CSS color — a named color (red, black), a hex code (#333), an rgb() or hsl() function, or even transparent or currentcolor.
- Remove the declaration. If no border is needed, remove the border property entirely rather than leaving an invalid value in place.
Examples
Incorrect: literal undefined as a color value
<div style="border: 1px solid undefined;">Content</div>
The validator rejects undefined because it is not a valid CSS color.
Incorrect: JavaScript producing undefined in markup
<script>
const borderColor = undefined; // missing configuration
document.getElementById("box").style.border = "2px dashed " + borderColor;
</script>
This produces border: 2px dashed undefined on the element.
Correct: using a valid color value
<div style="border: 1px solid black;">Content</div>
Correct: using a hex code or rgb() function
<div style="border: 2px dashed #ff6600;">Content</div>
<div style="border: 3px dotted rgb(0, 128, 255);">Content</div>
Correct: providing a fallback in JavaScript
<div id="box">Content</div>
<script>
const borderColor = getUserColor() || "#333";
document.getElementById("box").style.border = "2px solid " + borderColor;
</script>
By using || "#333", you ensure a valid color is always applied even when getUserColor() returns undefined.
Correct: using separate border properties
If you prefer more granular control, you can define each border sub-property individually:
<div style="border-width: 1px; border-style: solid; border-color: black;">Content</div>
Valid border shorthand reference
The border shorthand follows this pattern:
selector {
border: <width> <style> <color>;
}
- Width: 1px, 2px, thin, medium, thick
- Style: solid, dashed, dotted, double, groove, ridge, inset, outset, none
- Color: any valid CSS color — named colors (red, blue), hex (#000), rgb(), hsl(), currentcolor, or transparent
All three values are optional in the shorthand, but any value you do include must be valid. The string undefined is never a valid CSS value. If your styles are generated dynamically, always validate or sanitize the output before it reaches the HTML.
The color property, along with properties like background-color, border-color, and outline-color, expects values that conform to the CSS Color specification. The validator triggers this error when it encounters something that doesn’t match any valid color syntax. Common causes include:
- Plain numbers like 0 or 123 — numbers alone aren’t colors.
- Typos in color keywords such as grean instead of green, or trasparent instead of transparent.
- Malformed hex values like #GGG (invalid hex characters) or #12345 (wrong number of digits — hex colors must be 3, 4, 6, or 8 digits).
- Incorrect function syntax such as rgb(255 255 255 / 50) missing the % on the alpha value, or using legacy commas mixed with modern space-separated syntax.
- Missing units or hash symbols like 000000 instead of #000000.
This matters because browsers handle invalid color values unpredictably. Most will simply ignore the declaration entirely, which means the element inherits its color from a parent or falls back to the browser default — potentially making text unreadable against its background. Writing valid CSS ensures consistent rendering across all browsers and improves the maintainability of your code.
Valid CSS color formats
CSS supports several color formats:
| Format | Example | Notes |
|---|---|---|
| Named colors | red, blue, transparent | 148 predefined keywords |
| Hexadecimal | #ff0000, #f00 | 3, 4, 6, or 8 digits |
| rgb() / rgba() | rgb(255, 0, 0) | Comma or space-separated |
| hsl() / hsla() | hsl(0, 100%, 50%) | Hue, saturation, lightness |
| currentcolor | currentcolor | Inherits the current color value |
Examples
Invalid: plain number as a color
A bare number is not a recognized color value:
<style>
.example {
color: 0;
}
</style>
Invalid: typo in a color keyword
<style>
.example {
background-color: trasparent;
}
</style>
Invalid: hex value missing the # prefix
<style>
.example {
color: 000000;
}
</style>
Invalid: hex value with wrong digit count
<style>
.example {
color: #12345;
}
</style>
Fixed: using a named color keyword
<style>
.example {
color: black;
}
</style>
Fixed: using a hexadecimal color
<style>
.example {
color: #000000;
}
</style>
Fixed: using rgb()
<style>
.example {
color: rgb(0, 0, 0);
}
</style>
Fixed: using hsl()
<style>
.example {
color: hsl(0, 0%, 0%);
}
</style>
Fixed: using rgba() for semi-transparent color
<style>
.example {
color: rgba(0, 0, 0, 0.5);
}
</style>
Fixed: correcting the transparent keyword typo
<style>
.example {
background-color: transparent;
}
</style>
If you’re unsure whether a value is valid, browser DevTools can help — most browsers will strike through or ignore invalid property values in the Styles panel, giving you a quick visual indicator of the problem.
Hexadecimal color values in CSS must follow a specific format: the # symbol followed by exactly 3 or 6 hexadecimal digits. Each digit can be a number from 0 to 9 or a letter from A to F (case-insensitive). A 3-digit hex code is shorthand where each digit is expanded by duplication — for example, #F00 is equivalent to #FF0000. Common mistakes that trigger this error include using the wrong number of digits (e.g., 1, 2, 4, or 5), including non-hexadecimal characters (like G, Z, or special symbols), or omitting the # prefix.
The color CSS property sets the foreground color of an element’s text and text decorations. It also establishes the currentcolor value, which acts as an indirect value for other properties like border-color. Because color cascades to many visual aspects of an element, an invalid value can cause the entire declaration to be ignored, meaning the element may inherit an unexpected color or fall back to browser defaults.
This matters for consistency across browsers. While some browsers may attempt to guess what you meant with a malformed hex code, others will discard the value entirely. This leads to unpredictable rendering. Using valid color values ensures your styles are applied reliably everywhere.
Note that CSS also supports 4-digit and 8-digit hex values (which include an alpha/transparency channel, e.g., #F00A or #FF0000AA). However, the W3C validator’s inline style checker may not recognize these newer formats depending on the CSS level being validated. If you need transparency, consider using the rgba() function for broader validation compatibility.
Examples
Invalid hex color values
These examples will trigger the validation error:
<!-- Only 1 digit -->
<p style="color: #F;">Hello</p>
<!-- Only 2 digits -->
<p style="color: #FF;">Hello</p>
<!-- 4 digits (may not pass older CSS validation) -->
<p style="color: #FF00;">Hello</p>
<!-- 5 digits -->
<p style="color: #FF000;">Hello</p>
<!-- Non-hexadecimal character "G" -->
<p style="color: #FG0000;">Hello</p>
<!-- Missing the # prefix -->
<p style="color: FF0000;">Hello</p>
Valid hex color values
Use exactly 3 or 6 hexadecimal digits after the #:
<!-- 3-digit shorthand for red -->
<p style="color: #F00;">Hello</p>
<!-- 6-digit full form for red -->
<p style="color: #FF0000;">Hello</p>
<!-- 3-digit shorthand for white -->
<p style="color: #FFF;">Hello</p>
<!-- 6-digit full form for a dark gray -->
<p style="color: #333333;">Hello</p>
<!-- Lowercase is also valid -->
<p style="color: #3a7bd5;">Hello</p>
Alternative color formats
If hex values are causing issues, CSS offers several other valid ways to specify colors:
<!-- Named color -->
<p style="color: red;">Hello</p>
<!-- RGB function -->
<p style="color: rgb(255, 0, 0);">Hello</p>
<!-- RGBA function (with transparency) -->
<p style="color: rgba(255, 0, 0, 0.5);">Hello</p>
<!-- HSL function -->
<p style="color: hsl(0, 100%, 50%);">Hello</p>
The CSS display property controls how an element generates boxes in the layout. It determines whether an element behaves as a block-level or inline-level element and defines the layout model for its children (e.g., flow, flexbox, or grid). Because display is fundamental to page layout, using an invalid value means the browser will ignore the declaration entirely, potentially causing unexpected rendering.
Common causes of this error include:
- Typos — writing dipslay: block, display: blok, or display: flx instead of the correct keywords.
- Confusing values from other properties — using values like center, hidden, absolute, or relative, which belong to properties like text-align, visibility, or position, not display.
- Invented or outdated values — using non-standard or deprecated values that browsers don’t recognize, such as display: box (an old prefixed flexbox syntax without the prefix).
- Missing vendor prefixes — some older syntaxes like -webkit-flex were valid in certain browsers but are not standard CSS values.
The valid values for display include: block, inline, inline-block, flex, inline-flex, grid, inline-grid, flow-root, none, contents, table, table-row, table-cell, table-caption, table-column, table-column-group, table-footer-group, table-header-group, table-row-group, list-item, and the multi-keyword syntax like block flow, block flex, or inline grid.
Using invalid CSS values is a problem because browsers silently discard declarations they don’t understand. This means your intended layout won’t be applied, and debugging can be difficult since no visible error appears in the browser. Validating your CSS catches these mistakes early.
Examples
Invalid: typo in the display value
<div style="display: flx;">
<p>This container was meant to be a flex container.</p>
</div>
Fixed: correct flex value
<div style="display: flex;">
<p>This container is now a flex container.</p>
</div>
Invalid: using a value from another property
<nav style="display: center;">
<a href="/">Home</a>
</nav>
The value center does not belong to display. If the goal is to center content, use a valid display value combined with appropriate alignment properties.
Fixed: using flex with centering
<nav style="display: flex; justify-content: center;">
<a href="/">Home</a>
</nav>
Invalid: using a position value instead of a display value
<div style="display: absolute;">
<p>Overlay content</p>
</div>
Fixed: using the correct property
<div style="position: absolute; display: block;">
<p>Overlay content</p>
</div>
Invalid: using a non-standard value
<ul style="display: box;">
<li>Item 1</li>
<li>Item 2</li>
</ul>
Fixed: using the standard flexbox value
<ul style="display: flex;">
<li>Item 1</li>
<li>Item 2</li>
</ul>
The CSS filter property accepts a specific set of filter functions defined in the CSS Filter Effects Module. When the validator encounters a value it doesn’t recognize — such as the legacy IE progid:DXImageTransform.Microsoft. syntax, a made-up function name, or an incorrectly formatted value — it flags it as invalid.
The standard filter functions are: blur(), brightness(), contrast(), drop-shadow(), grayscale(), hue-rotate(), invert(), opacity(), saturate(), sepia(), and url() (for referencing SVG filters). The property also accepts the keyword none. Any value outside this set will trigger the validation error.
Why this matters
Using non-standard filter values creates several problems:
- Browser compatibility: Legacy or proprietary filter syntax (such as Microsoft’s filter: alpha(opacity=50) or filter: FlipH) only works in old versions of Internet Explorer and is ignored by all modern browsers.
- Standards compliance: Invalid CSS can cause parsers to discard the entire declaration or even the surrounding rule block, potentially breaking other styles.
- Future-proofing: Non-standard values may stop working entirely as browsers drop legacy support, leaving your design broken with no fallback.
How to fix it
- Identify the invalid value in the error message.
- Determine what visual effect you’re trying to achieve.
- Replace the invalid value with the corresponding standard CSS filter function.
- If you’re using legacy IE opacity filters, switch to the standard opacity property instead.
Examples
❌ Invalid: Legacy Microsoft filter syntax
<style>
.overlay {
filter: alpha(opacity=50);
}
</style>
✅ Fixed: Use standard opacity property
<style>
.overlay {
opacity: 0.5;
}
</style>
❌ Invalid: Misspelled or non-existent filter function
<style>
.photo {
filter: gray();
}
</style>
✅ Fixed: Use the correct grayscale() function
<style>
.photo {
filter: grayscale(100%);
}
</style>
❌ Invalid: Vendor-prefixed or proprietary value
<style>
.card {
filter: progid:DXImageTransform.Microsoft.Blur(pixelradius=5);
}
</style>
✅ Fixed: Use the standard blur() function
<style>
.card {
filter: blur(5px);
}
</style>
❌ Invalid: Bare value without a function
<style>
.image {
filter: 50%;
}
</style>
✅ Fixed: Wrap the value in the appropriate function
<style>
.image {
filter: brightness(50%);
}
</style>
Combining multiple filters
You can chain multiple standard filter functions in a single declaration by separating them with spaces:
<style>
.hero-image {
filter: contrast(120%) brightness(90%) blur(1px);
}
</style>
If none of the built-in filter functions achieve the effect you need, you can reference a custom SVG filter using the url() function, which is also a valid filter value:
<svg xmlns="http://www.w3.org/2000/svg" class="visually-hidden">
<filter id="custom-effect">
<feColorMatrix type="matrix" values="0.3 0.3 0.3 0 0
0.3 0.3 0.3 0 0
0.3 0.3 0.3 0 0
0 0 0 1 0"/>
</filter>
</svg>
<style>
.filtered {
filter: url(#custom-effect);
}
</style>
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
- Remove font-display from any regular CSS rule (selectors like body, h1, .class, etc.).
- Add font-display inside the @font-face at-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=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.
The font-size property sets the size of text and expects a valid CSS value — either a keyword (like small, medium, large), a numeric value with a unit (like 16px, 1.2em, 100%), or 0 (which needs no unit). When the validator reports that "px" is not a valid font-size value, it means the property received the string px alone, without the required number preceding it.
This issue commonly arises in a few scenarios:
- Typos or accidental deletion: The number was removed during editing, leaving just the unit behind.
- Template or CMS output: A dynamic value (e.g., from a variable or database field) resolved to empty, producing something like font-size: px;.
- Preprocessor errors: A Sass, Less, or other CSS preprocessor variable was undefined or empty, resulting in a bare unit in the compiled CSS.
While most browsers will simply ignore the invalid declaration and fall back to an inherited or default font size, this creates unpredictable rendering. The text may appear at an unexpected size, and the behavior may differ across browsers. Invalid CSS also causes W3C validation failures, which can signal deeper problems in your code or build pipeline.
How to Fix It
- Check for a missing number: Look at the font-size declaration flagged by the validator and add the intended numeric value before the unit.
- Inspect dynamic values: If the value comes from a variable, template engine, or CMS field, ensure it outputs a complete value (e.g., 16 or 16px) rather than an empty string.
- Use a fallback: When generating CSS dynamically, consider providing a fallback value in case the variable is empty.
Examples
❌ Incorrect: Bare unit with no number
<p style="font-size: px;">This text has an invalid font size.</p>
The validator will report that "px" is not a valid font-size value because no number precedes the unit.
✅ Correct: Numeric value with unit
<p style="font-size: 16px;">This text has a valid font size.</p>
❌ Incorrect: Empty value from a template variable
This is a common pattern in templating systems that can produce invalid CSS:
<p style="font-size: px;">Dynamic content here.</p>
When the template variable resolves to an empty string, only px remains.
✅ Correct: Using a keyword value
If you don’t need a specific pixel size, CSS keywords are another valid option:
<p style="font-size: medium;">This uses a keyword font size.</p>
✅ Correct: Using other valid units
The font-size property accepts many unit types. All of these are valid:
<style>
.example-em { font-size: 1.2em; }
.example-rem { font-size: 1rem; }
.example-percent { font-size: 120%; }
.example-px { font-size: 14px; }
.example-keyword { font-size: large; }
</style>
✅ Correct: Full document example
<!DOCTYPE html>
<html lang="en">
<head>
<title>Font Size Example</title>
<style>
p {
font-size: 16px;
}
</style>
</head>
<body>
<p>This paragraph has a valid font size of 16px.</p>
</body>
</html>
The revert keyword is one of the CSS-wide keywords defined in the CSS Cascading and Inheritance specification (along with initial, inherit, and unset). These keywords are valid values for every CSS property. When applied, revert rolls back the cascade to the value the property would have had if no author-level styles were applied — effectively reverting to the browser’s default stylesheet (or the user stylesheet, if one exists).
Older versions of the Nu HTML Checker (the engine behind the W3C HTML Validator) did not fully recognize revert as a valid CSS-wide keyword for all properties, which caused this false positive. This has been fixed in newer versions of the validator. If you’re using a local or outdated instance of the validator, updating to the latest version should resolve the issue.
Since this is a validator bug rather than a code issue, you have a few options: ignore the warning, update your validator, or use an alternative approach if you need a clean validation report. For example, you could use unset instead, which behaves similarly in many cases (though not identically — unset reverts to the inherited or initial value, while revert reverts to the user-agent default).
Examples
Code that triggers the false positive
This inline style uses revert on font-size, which is perfectly valid CSS but may trigger the validator warning:
<p style="font-size: revert;">This paragraph uses the browser's default font size.</p>
Workaround using unset
If you need to pass validation on an older validator instance, unset can serve as a partial substitute. Note that unset behaves differently from revert — it resets to the inherited value (for inherited properties like font-size) rather than the user-agent default:
<p style="font-size: unset;">This paragraph inherits the font size from its parent.</p>
Using revert in a stylesheet
The revert keyword is especially useful when you want to undo author styles for specific elements. This is valid CSS and should not produce errors in up-to-date validators:
<style>
p {
font-size: 2rem;
}
.default-size {
font-size: revert;
}
</style>
<p>This paragraph has a 2rem font size.</p>
<p class="default-size">This paragraph reverts to the browser default font size.</p>
All CSS-wide keywords
For reference, all of these CSS-wide keywords are valid for font-size and every other CSS property:
<div style="font-size: initial;">Uses the property's initial value</div>
<div style="font-size: inherit;">Inherits from the parent element</div>
<div style="font-size: unset;">Resets to inherited or initial value</div>
<div style="font-size: revert;">Reverts to the user-agent default</div>
<div style="font-size: revert-layer;">Reverts to the previous cascade layer</div>
The font-stretch property selects a normal, condensed, or expanded face from a font family. Its valid keyword values are ultra-condensed, extra-condensed, condensed, semi-condensed, normal, semi-expanded, expanded, extra-expanded, and ultra-expanded. It also accepts percentage values (e.g., 50% to 200%). The value bold doesn’t fit into any of these categories because it describes font weight (thickness of strokes), not font width (how narrow or wide the characters are).
This error usually happens due to one of two mistakes:
- Confusing font-stretch with font-weight: You intended to make text bold but accidentally used the wrong property.
- Typo or copy-paste error in the font shorthand: When writing shorthand font declarations, the various sub-properties can easily get mixed up.
The W3C validator flags this because browsers will ignore invalid CSS values, meaning your intended styling won’t be applied. Fixing it ensures your styles work as expected across all browsers and pass validation.
How to Fix It
- If you want bold text, use font-weight: bold (or numeric values like 700).
- If you want wider or narrower characters, use font-stretch with a valid value like condensed or expanded.
- If you need both, apply each property separately or use the font shorthand correctly.
Examples
Incorrect: Using bold with font-stretch
This triggers the validation error because bold is not a valid font-stretch value:
<p style="font-stretch: bold;">This text won't render as expected.</p>
Fixed: Using font-weight for boldness
If the intent was to make the text bold, switch to font-weight:
<p style="font-weight: bold;">This text is bold.</p>
Fixed: Using font-stretch correctly for width
If the intent was to adjust the character width, use a valid font-stretch value:
<p style="font-stretch: expanded;">This text uses an expanded font face.</p>
Using both properties together
You can combine font-weight and font-stretch when you need both bold text and a different font width:
<style>
.styled-text {
font-weight: bold;
font-stretch: condensed;
font-family: Arial, sans-serif;
}
</style>
<p class="styled-text">This text is bold and condensed.</p>
Valid font-stretch values reference
Here’s a quick overview of all valid keyword values for font-stretch:
<style>
.condensed { font-stretch: condensed; }
.normal-width { font-stretch: normal; }
.expanded { font-stretch: expanded; }
.custom-width { font-stretch: 75%; }
</style>
<p class="condensed">Condensed text</p>
<p class="normal-width">Normal width text</p>
<p class="expanded">Expanded text</p>
<p class="custom-width">75% width text</p>
Note that font-stretch only works if the selected font family includes condensed or expanded faces. If the font doesn’t have these variations, the property will have no visible effect even with valid values.
The font-style and font-weight properties serve different purposes. font-style controls whether text appears in a normal, italic, or oblique style, while font-weight controls how thick or thin the characters are rendered. Writing font-style: bold is a mistake because bold is not among the accepted values for font-style. Browsers will ignore the invalid declaration entirely, meaning your text won’t become bold at all — it will simply render in the default weight.
This error typically comes from confusing the two properties or misremembering which property handles boldness. The valid values for each property are:
- font-style: normal, italic, oblique, or oblique with an angle (e.g., oblique 10deg)
- font-weight: normal, bold, bolder, lighter, or numeric values from 100 to 900
To fix this issue, replace font-style: bold with font-weight: bold. If you intended to make text both bold and italic, you’ll need to use both properties separately.
Examples
Incorrect — using bold with font-style
This triggers the validation error because bold is not a valid font-style value:
<p style="font-style: bold;">This text won't actually be bold.</p>
Correct — using font-weight for boldness
Move the bold value to the font-weight property:
<p style="font-weight: bold;">This text is bold.</p>
Correct — combining bold and italic
If you want text that is both bold and italic, use both properties:
<p style="font-weight: bold; font-style: italic;">This text is bold and italic.</p>
Correct — using font-weight in a stylesheet
You can also apply bold styling through a <style> block or external stylesheet, using either keyword or numeric values:
<style>
.emphasis {
font-weight: bold;
}
.light {
font-weight: 300;
}
.heavy {
font-weight: 900;
}
</style>
<p class="emphasis">This text is bold (weight 700).</p>
<p class="light">This text is light (weight 300).</p>
<p class="heavy">This text is extra heavy (weight 900).</p>
Note that the keyword bold is equivalent to the numeric value 700, and normal is equivalent to 400. Numeric values give you finer control over text weight, especially when using variable fonts or font families that offer multiple weight variations.
The font-style CSS property controls whether text is displayed in a normal, italic, or oblique face from its font-family. It has a limited set of accepted values, and the W3C validator will flag any value that falls outside this set.
This error commonly occurs for a few reasons:
- Confusing font-style with font-size: Since both properties start with font-, it’s easy to accidentally type font-style: 1.2em when you meant font-size: 1.2em. Numeric and length values are not valid for font-style.
- Confusing font-style with font-weight: Writing font-style: bold is invalid because bold is a font-weight value, not a font-style value.
- Typos in keyword values: Misspelling a valid keyword, such as font-style: itallic or font-style: oblque, will trigger this error.
- Using the oblique angle syntax incorrectly: While oblique can accept an optional angle (e.g., oblique 10deg), providing an angle without the oblique keyword or using an invalid unit will cause a validation error.
Using invalid CSS values can lead to unpredictable rendering across browsers. Most browsers will ignore the entire declaration when they encounter an invalid value, meaning your intended styling won’t be applied at all. Keeping your CSS valid ensures consistent behavior and makes debugging easier.
Valid font-style values
The accepted values for font-style are:
- normal — displays the normal face of the font family.
- italic — selects the italic face; falls back to oblique if unavailable.
- oblique — selects the oblique face; optionally accepts an angle value (e.g., oblique 10deg). The angle defaults to 14deg if omitted.
- Global CSS values: inherit, initial, revert, revert-layer, unset.
Examples
Incorrect: size value applied to font-style
This is the most common mistake — using a length value that belongs on font-size:
<p style="font-style: 1.2em;">This text has an invalid font-style.</p>
Correct: use font-size for size values
<p style="font-size: 1.2em;">This text has a valid font size.</p>
Incorrect: using bold with font-style
<p style="font-style: bold;">This text has an invalid font-style.</p>
Correct: use font-weight for boldness
<p style="font-weight: bold;">This text is bold.</p>
Incorrect: misspelled keyword
<p style="font-style: itallic;">This text has a typo in font-style.</p>
Correct: properly spelled keyword
<p style="font-style: italic;">This text is italic.</p>
Correct: using oblique with an angle
<p style="font-style: oblique 12deg;">This text is oblique at 12 degrees.</p>
Quick reference for commonly confused properties
If you’re unsure which property to use, here’s a quick guide:
| You want to change… | Use this property | Example value |
|---|---|---|
| Italic or oblique text | font-style | italic, oblique |
| Text size | font-size | 1.2em, 16px |
| Text boldness | font-weight | bold, 700 |
| Text decoration | text-decoration | underline, line-through |
The font-weight property controls the boldness or thickness of text characters. Unlike many other CSS properties, it does not accept length units such as px, em, or %. Instead, it uses a specific set of keywords or unitless numeric values to indicate the desired weight. Supplying an unrecognized value causes the declaration to be ignored by the browser, meaning your intended styling won’t be applied, and the text will fall back to the inherited or default weight.
The accepted values for font-weight are:
- Keywords: normal (equivalent to 400), bold (equivalent to 700), bolder (relative, one step heavier than the parent), lighter (relative, one step lighter than the parent).
- Numeric values: Any number from 1 to 1000. Historically only multiples of 100 (100 through 900) were valid, but the CSS Fonts Level 4 specification expanded this to any value in the 1–1000 range. Note that many validators and older browsers may still only recognize the 100–900 multiples.
This matters for standards compliance and predictable rendering. An invalid font-weight value is silently discarded by browsers, which can lead to confusing visual results — especially when you expect a specific weight from a variable font or a multi-weight font family.
To fix this issue, identify the invalid value in your CSS and replace it with one of the accepted values listed above. If you were using a pixel or other unit value, simply remove the unit and choose an appropriate numeric weight. If you used a misspelled keyword (e.g., bolded or heavy), replace it with the correct keyword.
Examples
Incorrect: using a length unit
p {
font-weight: 20px;
}
The validator reports this because 20px is not a valid font-weight value. The property does not accept length units.
Incorrect: using an invalid keyword
h2 {
font-weight: heavy;
}
The keyword heavy is not recognized by the CSS specification for font-weight.
Correct: using valid numeric values
p {
font-weight: 300;
}
h2 {
font-weight: 700;
}
Correct: using valid keywords
p {
font-weight: lighter;
}
h2 {
font-weight: bold;
}
Full HTML example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Font Weight Example</title>
<style>
.light {
font-weight: 300;
}
.regular {
font-weight: normal;
}
.semi-bold {
font-weight: 600;
}
.bold {
font-weight: bold;
}
</style>
</head>
<body>
<p class="light">This text uses a light font weight (300).</p>
<p class="regular">This text uses a normal font weight (400).</p>
<p class="semi-bold">This text uses a semi-bold font weight (600).</p>
<p class="bold">This text uses a bold font weight (700).</p>
</body>
</html>
Quick reference of common numeric weights
| Value | Typical name |
|---|---|
| 100 | Thin |
| 200 | Extra Light |
| 300 | Light |
| 400 | Normal / Regular |
| 500 | Medium |
| 600 | Semi Bold |
| 700 | Bold |
| 800 | Extra Bold |
| 900 | Black |
Keep in mind that the actual visual effect of a numeric weight depends on whether the loaded font family provides a matching weight. If a font only includes 400 and 700 weights, the browser will map other values to the nearest available weight.
The W3C validator checks inline styles and embedded stylesheets for valid CSS. When it encounters a height declaration with multiple values or an unrecognized value, it flags the error because height is not a shorthand property — it only accepts one value at a time. This differs from properties like margin or padding, which accept multiple values to target different sides of an element.
This error commonly occurs when you:
- Accidentally provide two values, perhaps confusing height with a shorthand property (e.g., height: 100px 50px;).
- Include a typo or invalid unit (e.g., height: 100ppx; or height: 100pixels;).
- Use a CSS function incorrectly (e.g., height: calc(100% 20px); — missing the operator).
- Copy a value meant for another property, such as pasting a grid-template-rows value into height.
Browsers may silently ignore invalid height declarations, causing your element to fall back to its default sizing (auto). This can lead to unexpected layout behavior that’s difficult to debug. Keeping your CSS valid ensures consistent rendering across browsers and helps catch mistakes early.
Valid values for height
The height property accepts exactly one of the following:
- Length values: 100px, 10em, 5rem, 20vh, etc.
- Percentage values: 50%, 100%
- Keyword values: auto, max-content, min-content, fit-content(200px)
- Global values: inherit, initial, revert, unset
- Calc expressions: calc(100% - 20px), calc(50vh + 2rem)
Examples
Incorrect: too many values
<style>
.box {
height: 100px 50px; /* Error: height only accepts one value */
}
</style>
<div class="box">Content</div>
Incorrect: unrecognized value
<style>
.box {
height: 100pixels; /* Error: "pixels" is not a valid unit */
}
</style>
<div class="box">Content</div>
Incorrect: malformed calc() expression
<style>
.box {
height: calc(100% 20px); /* Error: missing operator between values */
}
</style>
<div class="box">Content</div>
Correct: single length value
<style>
.box {
height: 100px;
}
</style>
<div class="box">Content</div>
Correct: percentage value
<style>
.box {
height: 50%;
}
</style>
<div class="box">Content</div>
Correct: calc() with proper operator
<style>
.box {
height: calc(100% - 20px);
}
</style>
<div class="box">Content</div>
Correct: keyword value
<style>
.box {
height: auto;
}
</style>
<div class="box">Content</div>
If you need to set both width and height, remember they are separate properties and must be declared individually. If you were trying to set a minimum and maximum height, use min-height and max-height as distinct declarations instead of combining values into a single height property.
The @import rule allows you to pull in styles from another CSS file. According to the CSS specification, @import rules must precede all other at-rules (except @charset) and all style rules. When a browser encounters an @import after another valid CSS statement, it silently ignores the import. This means the styles you intended to load simply won’t be applied, which can lead to broken layouts or missing designs that are difficult to debug.
The W3C validator catches this ordering problem and flags it because the misplaced @import will have no effect. Even though browsers won’t throw a visible error, the imported stylesheet is completely discarded, making this a real functional issue rather than just a cosmetic validation warning.
The correct order inside a <style> element or CSS file is:
- @charset (if needed, and only in external CSS files)
- @import rules
- All other CSS rules (@font-face, @media, style rules, etc.)
Examples
Incorrect: @import after a style rule
<style>
body {
margin: 0;
}
@import url("typography.css");
h1 {
color: navy;
}
</style>
The @import is placed after the body rule, so the browser will ignore it entirely. The styles from typography.css will never be loaded.
Incorrect: @import after another at-rule
<style>
@font-face {
font-family: "MyFont";
src: url("myfont.woff2") format("woff2");
}
@import url("reset.css");
</style>
Even though @font-face is an at-rule, it is not @charset or @import, so placing @import after it is invalid.
Correct: @import rules first
<style>
@import url("reset.css");
@import url("typography.css");
@font-face {
font-family: "MyFont";
src: url("myfont.woff2") format("woff2");
}
body {
margin: 0;
}
h1 {
color: navy;
}
</style>
All @import rules appear before any other statements, so they are valid and the imported stylesheets will be loaded correctly.
Correct: Multiple @import rules with @charset
In an external CSS file, you may also have a @charset declaration. It must come first, followed by @import rules:
@charset "UTF-8";
@import url("base.css");
@import url("components.css");
body {
font-family: sans-serif;
}
Alternatives to @import
While fixing the ordering resolves the validation error, it’s worth noting that @import in CSS can cause performance issues because imported files are loaded sequentially rather than in parallel. Consider these alternatives:
- Multiple <link> elements in your HTML <head> — these allow browsers to download stylesheets in parallel.
- CSS bundling tools — build tools like Webpack, Vite, or PostCSS can combine multiple CSS files into one at build time, eliminating the need for @import at runtime.
If you do use @import, just make sure every instance appears at the very top of your stylesheet, before any other CSS rules.
Ready to validate your sites?
Start your free trial today.