HTML Guides
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.
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 background-image CSS property accepts a specific set of value types defined by the CSS specification. The most common are none (the default, meaning no image), the url() function pointing to an image file, and gradient functions like linear-gradient() or radial-gradient(). When the validator encounters a value that doesn’t match any of these patterns, it flags the error.
This issue often appears in inline style attributes within HTML, which is where the W3C HTML Validator checks your CSS. Common mistakes include providing a bare filename without url(), forgetting parentheses or quotes, using incorrect gradient syntax, or introducing typos in CSS function names.
Fixing this matters for several reasons. Browsers may silently ignore an invalid background-image declaration entirely, meaning your intended background simply won’t appear. This leads to broken visual designs that can be difficult to debug. Additionally, invalid CSS can cause parsing errors that may affect subsequent declarations in the same rule block.
How to fix it
- Wrap image paths in url() — A bare filename like background-image: photo.jpg is invalid. It must be background-image: url("photo.jpg").
- Use proper quoting — While quotes inside url() are technically optional for simple paths, always use them for paths containing spaces, parentheses, or special characters. Single or double quotes both work.
- Check gradient syntax — If using gradients, ensure the function name is correct (e.g., linear-gradient, not linear-gradiant) and the arguments follow valid syntax.
- Use recognized keywords — The only non-function keyword accepted is none. Values like transparent, auto, or arbitrary strings are not valid for this property.
Examples
Incorrect: bare filename without url()
<div style="background-image: hero.jpg;">
Content here
</div>
Incorrect: misspelled function name
<div style="background-image: urls('hero.jpg');">
Content here
</div>
Incorrect: missing parentheses in url
<div style="background-image: url 'hero.jpg';">
Content here
</div>
Incorrect: invalid keyword
<div style="background-image: transparent;">
Content here
</div>
Correct: using url() with a file path
<div style="background-image: url('hero.jpg');">
Content here
</div>
Correct: using none to explicitly set no background image
<div style="background-image: none;">
Content here
</div>
Correct: using a gradient function
<div style="background-image: linear-gradient(to right, #ff7e5f, #feb47b);">
Content here
</div>
Correct: multiple background images
<div style="background-image: url('overlay.png'), linear-gradient(to bottom, #000, #333);">
Content here
</div>
Correct: using a <style> block
<!DOCTYPE html>
<html lang="en">
<head>
<title>Background Image Example</title>
<style>
.banner {
background-image: url("banner.png");
background-size: cover;
background-repeat: no-repeat;
}
</style>
</head>
<body>
<div class="banner">Welcome</div>
</body>
</html>
Always wrap image paths in the url() function, double-check function names for typos, and use quotes around paths that contain special characters. When in doubt, move your styles out of inline style attributes and into a <style> block or external stylesheet, which makes debugging CSS issues much easier.
The linear-gradient() function went through several syntax revisions during CSS standardization. Early drafts and vendor-prefixed implementations (like -webkit-linear-gradient()) used bare direction keywords such as top, bottom left, etc., where the keyword indicated the starting point of the gradient. The final standard, defined in the CSS Images Module Level 3 and Level 4 specifications, changed this so that direction keywords use the to prefix and indicate the ending point of the gradient. For example, the old linear-gradient(top, #fff, #000) meant “start at the top and go to the bottom,” while the correct modern equivalent is linear-gradient(to bottom, #fff, #000).
This matters because the old syntax without to is not valid CSS per the current specification. While some browsers may still interpret the legacy syntax for backward compatibility, relying on it is risky — behavior can vary across browsers, and it will trigger validation errors. Using standard-compliant CSS ensures consistent rendering and forward compatibility.
How to fix it
Replace the bare direction keyword with the correct to syntax. Note that the direction meaning is inverted: the old syntax specified where the gradient starts, while the new syntax specifies where it goes to.
Here’s a quick mapping from old to new syntax:
| Old (invalid) | New (valid) | Angle equivalent |
|---|---|---|
| top | to bottom | 180deg |
| bottom | to top | 0deg |
| left | to right | 90deg |
| right | to left | 270deg |
| top left | to bottom right | N/A (use to syntax) |
Important: Notice that top in the old syntax means “start at top, go to bottom.” So the modern equivalent is to bottom, not to top. If the validator message says the argument should be to top, it means you wrote top — but be sure you understand which direction your gradient should actually go before blindly replacing it. If you truly want the gradient to go toward the top, use to top. If you want it to go from the top downward, use to bottom.
If you don’t specify a direction at all, linear-gradient() defaults to to bottom (top-to-bottom), which is often what you want.
Examples
Invalid: bare direction keyword
<div style="background: linear-gradient(top, #ffffff, #000000);">
Content
</div>
The bare keyword top is not valid in the standard linear-gradient() syntax and will trigger the validator error.
Fixed: using the to keyword
<div style="background: linear-gradient(to bottom, #ffffff, #000000);">
Content
</div>
Since the old top meant “start at the top,” the equivalent standard syntax is to bottom.
Fixed: using an angle
<div style="background: linear-gradient(180deg, #ffffff, #000000);">
Content
</div>
An angle of 180deg produces the same top-to-bottom gradient.
Full document example
<!DOCTYPE html>
<html lang="en">
<head>
<title>Gradient Example</title>
<style>
.box {
width: 200px;
height: 100px;
/* Valid: direction keyword with "to" */
background: linear-gradient(to top, #ffffff, #000000);
}
.box-angle {
width: 200px;
height: 100px;
/* Valid: angle equivalent of "to top" */
background: linear-gradient(0deg, #ffffff, #000000);
}
.box-default {
width: 200px;
height: 100px;
/* Valid: no direction specified, defaults to "to bottom" */
background: linear-gradient(#ffffff, #000000);
}
</style>
</head>
<body>
<div class="box"></div>
<div class="box-angle"></div>
<div class="box-default"></div>
</body>
</html>
All three approaches are valid. Choose whichever is clearest for your use case — the to keyword syntax is generally the most readable, while angles offer more precision for diagonal or non-cardinal directions.
The background CSS property is a shorthand that can accept values for background-color, background-image, background-position, background-size, background-repeat, background-origin, background-clip, and background-attachment. When the validator encounters an unrecognized value, it tries to match it against individual sub-properties like background-color. If the value doesn’t match any of them, you’ll see this error.
Common causes include typos in color names (e.g., bleu instead of blue), malformed hex codes (e.g., #gggggg or a missing #), incorrect function syntax (e.g., rgb(255 0 0 with a missing parenthesis), or using values that simply don’t exist in CSS. This error can also appear when a CSS custom property (variable) is used in inline styles and the validator can’t resolve it, or when a browser-specific value is used that isn’t part of the CSS specification.
Fixing this issue ensures your styles render predictably across browsers. While browsers are often forgiving and may ignore invalid declarations silently, relying on that behavior can lead to inconsistent rendering. Standards-compliant CSS is easier to maintain and debug.
How to Fix
- Check for typos in color names, hex codes, or function syntax.
- Verify the value format — hex colors need a # prefix, rgb() and rgba() need proper comma-separated or space-separated values with closing parentheses.
- Use background-color instead of the shorthand background if you only intend to set a color. This makes your intent clearer and reduces the chance of conflicting shorthand values.
- Remove vendor-prefixed or non-standard values that the validator doesn’t recognize.
Examples
Incorrect — Typo in color name
<div style="background: aquaa;">Content</div>
aquaa is not a valid CSS color name, so the validator rejects it.
Correct — Valid color name
<div style="background: aqua;">Content</div>
Incorrect — Malformed hex code
<div style="background: #xyz123;">Content</div>
Hex color codes only allow characters 0–9 and a–f.
Correct — Valid hex code
<div style="background: #00a123;">Content</div>
Incorrect — Missing hash symbol
<div style="background: ff0000;">Content</div>
Without the #, the validator interprets ff0000 as an unknown keyword.
Correct — Hex code with hash
<div style="background: #ff0000;">Content</div>
Incorrect — Broken rgb() syntax
<div style="background: rgb(255, 0, 300);">Content</div>
RGB channel values must be between 0 and 255 (or 0% to 100%).
Correct — Valid rgb() value
<div style="background: rgb(255, 0, 128);">Content</div>
Correct — Using background-color for clarity
When you only need to set a color, prefer the specific background-color property over the shorthand:
<div style="background-color: rgba(255, 0, 0, 0.5);">Semi-transparent red</div>
Correct — Valid shorthand with image and other properties
<div style="background: url('image.jpg') no-repeat center / cover;">Content</div>
Note the / between background-position (center) and background-size (cover) — this is required syntax in the shorthand.
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-radius property accepts one to four values, each of which must be a valid <length> or <percentage>. You can also specify elliptical corners using a / separator with up to four values on each side. Any value that falls outside this syntax — such as a bare number without a unit, a misspelled keyword, a negative value, or a var() reference the validator can’t resolve — will trigger this error.
Here are the most common reasons this error appears:
- Missing units: Writing border-radius: 10 instead of border-radius: 10px. CSS requires explicit units for all non-zero length values.
- Invalid keywords: Using a keyword like border-radius: large that isn’t part of the CSS specification.
- Negative values: The border-radius property does not accept negative lengths or percentages.
- Unresolvable var() references: The W3C validator performs static analysis and cannot evaluate CSS custom properties. If you use var(--my-radius) in an inline style attribute, the validator has no way to confirm the variable holds a valid value, so it flags it as an error.
- Malformed shorthand: Incorrect use of the / separator or too many values, such as border-radius: 10px 5px / 20px 15px 10px 5px 3px.
This matters for standards compliance and cross-browser consistency. While browsers are generally forgiving and will ignore invalid property values, this means the style silently fails — your element won’t get the rounded corners you intended. Catching these errors during validation helps prevent subtle visual bugs.
How to fix it
- Add units to any bare numeric values (except 0, which doesn’t need a unit).
- Remove negative values — use 0 as the minimum.
- Check shorthand syntax — you can provide one to four values, optionally followed by / and one to four more values for elliptical radii.
- Replace unresolvable var() references with static values for validation purposes, or move them into a <style> block where the custom property is defined (though the validator may still flag var() usage).
- Use valid units such as px, em, rem, %, vw, etc.
Examples
Invalid: missing unit on a non-zero value
<div style="border-radius: 10;"></div>
Fixed: adding the correct unit
<div style="border-radius: 10px;"></div>
Invalid: negative value
<div style="border-radius: -5px;"></div>
Fixed: using a non-negative value
<div style="border-radius: 5px;"></div>
Invalid: unrecognized keyword
<div style="border-radius: round;"></div>
Fixed: using a valid percentage for a circular shape
<div style="border-radius: 50%;"></div>
Invalid: var() in inline style that the validator cannot resolve
<div style="border-radius: var(--my-radius);"></div>
Fixed: defining the custom property in a stylesheet
<!DOCTYPE html>
<html lang="en">
<head>
<title>Border Radius Example</title>
<style>
:root {
--my-radius: 8px;
}
.rounded {
border-radius: var(--my-radius);
}
</style>
</head>
<body>
<div class="rounded">Rounded corners via custom property</div>
</body>
</html>
Note that even with the custom property properly defined, the W3C CSS validator may still flag var() usage because it performs static analysis without evaluating custom properties. This is a known limitation. If full validator compliance is important, use static values directly:
<div style="border-radius: 8px;"></div>
Valid shorthand with elliptical radii
The / syntax lets you define horizontal and vertical radii separately:
<div style="border-radius: 10px 20px / 5px 15px;"></div>
This sets horizontal radii of 10px and 20px (alternating corners) and vertical radii of 5px and 15px, creating elliptical corners. Both sides of the / follow the same one-to-four value pattern.
The border-style property controls the visual pattern of a border — whether it appears as a solid line, a series of dots, dashes, or other decorative styles. Its valid values are: none, hidden, dotted, dashed, solid, double, groove, ridge, inset, and outset.
The keyword thick is a valid value for border-width, which controls how wide or heavy the border appears. It’s one of three named width keywords: thin, medium, and thick. When thick is mistakenly used as a border-style value, the browser cannot interpret the declaration, and the border may not render at all or may fall back to unexpected defaults.
This is a common mix-up because people often think of a “thick border” as a single concept, but CSS separates the concern into two distinct properties: the style (what it looks like) and the width (how thick it is). Both must be set correctly for the border to display as intended. Without a valid border-style, most browsers default to none, meaning no border is visible regardless of other border properties.
To fix the issue, replace thick in your border-style declaration with a valid style keyword, and move thick to border-width if you want a heavier border. Alternatively, you can use the border shorthand to set width, style, and color in a single declaration.
Examples
Incorrect: using thick as a border style
<div style="border-style: thick;">This border will not render correctly.</div>
The value thick is not recognized for border-style, so the declaration is invalid.
Correct: separating style and width
<div style="border-style: solid; border-width: thick;">This has a thick solid border.</div>
Here, solid defines the border pattern and thick defines the border width — each value is used with the correct property.
Correct: using a specific pixel width
<div style="border-style: dashed; border-width: 4px;">This has a 4px dashed border.</div>
You can use any length value (like 4px or 0.25em) for border-width instead of the thick keyword for more precise control.
Correct: using the border shorthand
<div style="border: thick solid #333;">This uses the border shorthand.</div>
The border shorthand accepts width, style, and color in any order. This is often the most concise way to define a border and avoids confusion between the individual properties.
The border shorthand property lets you set the width, style, and color of an element’s border in a single declaration. The CSS specification allows up to three values, each corresponding to one of the longhand properties: border-width, border-style, and border-color. Each component may appear at most once, and the browser determines which value maps to which component based on the value’s type. When the validator encounters more values than expected or a value it can’t match to any of the three components, it raises this error.
This error commonly occurs for several reasons:
- Too many values — Providing four values (like you might with margin or padding) doesn’t work with border. Unlike box-model spacing properties, border does not accept per-side values in its shorthand.
- Misspelled keywords — A typo like sollid instead of solid, or doted instead of dotted, produces an unrecognized value.
- Invalid or unsupported values — Using values that don’t belong to any of the three components, such as border: 2px solid black inset (mixing shorthand with a style that creates a duplicate).
- Missing spaces — Writing 1pxsolid black instead of 1px solid black creates an unrecognized token.
- Using border syntax for border-radius or other properties — Accidentally placing values like 5px 10px 5px 10px on border instead of on border-radius.
Fixing the issue means ensuring your border value contains only recognized values, with no more than one from each category:
- Width: A length (e.g., 1px, 0.5em), 0, or a keyword (thin, medium, thick).
- Style: One of none, hidden, dotted, dashed, solid, double, groove, ridge, inset, or outset.
- Color: Any valid CSS color (e.g., red, #333, rgb(0, 0, 0), transparent).
If you need different borders on each side, use the side-specific properties (border-top, border-right, border-bottom, border-left) or the individual longhand properties (border-width, border-style, border-color), which do accept multiple values for each side.
Examples
Incorrect: too many values
<div style="border: 1px 2px solid black;">Content</div>
This provides two width values (1px and 2px), which the border shorthand does not allow. If you want different widths per side, use border-width separately.
Incorrect: misspelled keyword
<div style="border: 2px sollid red;">Content</div>
The value sollid is not a recognized border style, causing the validator to reject the declaration.
Incorrect: four-value syntax used on border
<div style="border: 1px 2px 1px 2px solid grey;">Content</div>
The border shorthand does not support per-side values. This syntax is valid for border-width, not for border.
Correct: standard shorthand with all three components
<div style="border: 2px solid black;">Content</div>
Correct: omitting optional components
You don’t need to provide all three values. Any omitted component resets to its initial value (medium, none, and currentcolor respectively).
<p style="border: solid;">Content</p>
Correct: two components in any order
<p style="border: dashed #00f;">Content</p>
Correct: different borders per side using longhand properties
<div style="border-width: 1px 2px 1px 2px; border-style: solid; border-color: grey;">Content</div>
Correct: using side-specific shorthand properties
<div style="border-top: 1px solid red; border-bottom: 2px dashed blue;">Content</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 border-width property controls the thickness of an element’s border. According to the CSS specification, its accepted values fall into two categories:
- Length values — any valid CSS length such as 1px, 0.25em, 2rem, 3pt, or 0.1cm. The value must not be negative.
- Keywords — exactly three are defined: thin, medium, and thick. These map to implementation-defined sizes but are guaranteed to maintain the relationship thin ≤ medium ≤ thick.
A bare number like 5 (without a unit) is not valid, even though some browsers may silently accept it. Similarly, words like large, bold, normal, or color values like red are not valid border-width values. Percentage values (e.g., 10%) are also not accepted for border-width, unlike many other CSS properties that accept lengths.
This matters for several reasons. First, invalid CSS values cause the declaration to be ignored entirely, meaning the border may not render as intended — or may fall back to the initial value of medium, producing unexpected results. Second, relying on browser error-recovery behavior leads to inconsistent rendering across different browsers and versions. Third, valid CSS ensures your stylesheets are maintainable and predictable.
Common causes of this error include:
- Missing units — writing border-width: 2 instead of border-width: 2px. The only unitless length allowed in CSS is 0.
- Misspelled or invented keywords — using large, small, normal, or none instead of thin, medium, or thick.
- Wrong value type — accidentally using a color name, percentage, or other non-length value.
- Typos in units — writing 5xp instead of 5px.
To fix the issue, locate the offending border-width declaration and replace the invalid value with a proper CSS length (including its unit) or one of the three accepted keywords.
Examples
Invalid: using a non-existent keyword
<style>
.box {
border-style: solid;
border-width: large; /* "large" is not a valid border-width value */
}
</style>
<div class="box">Content</div>
Fixed: using a valid keyword
<style>
.box {
border-style: solid;
border-width: thick;
}
</style>
<div class="box">Content</div>
Invalid: missing unit on a number
<style>
.alert {
border: solid;
border-width: 3; /* unitless number is not valid */
}
</style>
<div class="alert">Warning</div>
Fixed: adding a proper unit
<style>
.alert {
border: solid;
border-width: 3px;
}
</style>
<div class="alert">Warning</div>
Invalid: using a percentage
<style>
.panel {
border-style: solid;
border-width: 5%; /* percentages are not valid for border-width */
}
</style>
<div class="panel">Panel</div>
Fixed: using a length value instead
<style>
.panel {
border-style: solid;
border-width: 0.3em;
}
</style>
<div class="panel">Panel</div>
Using multiple values with shorthand
The border-width property accepts one to four values (for top, right, bottom, left), and each must independently be valid:
<style>
.card {
border-style: solid;
border-width: thin 2px medium 1px;
}
</style>
<div class="card">Card content</div>
Replace any invalid border-width value with a recognized CSS length (always including the unit, except for 0) or one of the keywords thin, medium, or thick to resolve the validation error.
The box-shadow property applies one or more shadow effects to an element’s box. The W3C CSS validator checks that each value in the declaration conforms to the specification. When it encounters something it doesn’t recognize — such as a unitless number (other than 0), a misspelled keyword, or values arranged in the wrong order — it reports that the value is not valid for box-shadow.
The correct syntax for a single box-shadow value is:
box-shadow: none | [inset? && <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>?]
- inset (optional): If present, the shadow is drawn inside the element’s border.
- <offset-x> and <offset-y> (required): Horizontal and vertical offsets. Must be valid CSS lengths with units (e.g., px, em, rem). The value 0 is the only length that doesn’t require a unit.
- <blur-radius> (optional): Must be a non-negative length. Defaults to 0.
- <spread-radius> (optional): Can be positive or negative. Defaults to 0. You can only include this if you also include <blur-radius>.
- <color> (optional): Any valid CSS color. Can appear at the beginning or end of the value list.
Common causes of this validation error include:
- Missing units on length values — Writing 10 10 instead of 10px 10px.
- Invalid or misspelled keywords — Using something like outerbox or shadows instead of inset or none.
- Too many or too few values — Providing five length values when the maximum is four.
- Vendor prefixes — Using -webkit-box-shadow or non-standard values that the standard validator rejects.
- Invalid color values — Using a malformed color like rgb(0,0,0,0.5) (missing the a in rgba for CSS3 validation) or a typo in a named color.
- Incorrect value order — Placing the color between the length values instead of at the start or end.
Fixing this issue ensures your CSS is standards-compliant, which improves cross-browser consistency and reduces the risk of unexpected rendering behavior.
Examples
Missing units on length values
Unitless numbers (except 0) are not valid CSS lengths. This is one of the most common triggers for this error.
<!-- ❌ Invalid: missing units on offset values -->
<div style="box-shadow: 10 10 5 rgba(0,0,0,0.5);">
Shadow text
</div>
<!-- ✅ Valid: all lengths have proper units -->
<div style="box-shadow: 10px 10px 5px rgba(0,0,0,0.5);">
Shadow text
</div>
Invalid keyword
Only none and inset are valid keywords for box-shadow. Any other keyword triggers the error.
<!-- ❌ Invalid: "outset" is not a recognized keyword -->
<div style="box-shadow: outset 4px 4px 8px #333;">
Shadow text
</div>
<!-- ✅ Valid: using the correct "inset" keyword -->
<div style="box-shadow: inset 4px 4px 8px #333;">
Shadow text
</div>
Color value in the wrong position or malformed
The color value should appear either first or last in the shadow definition. Some validators are strict about placement, and a malformed color will always fail.
<!-- ❌ Invalid: color placed between length values -->
<div style="box-shadow: 2px red 2px 5px;">
Shadow text
</div>
<!-- ✅ Valid: color at the end -->
<div style="box-shadow: 2px 2px 5px red;">
Shadow text
</div>
Using zero without units alongside other values
While 0 alone doesn’t require a unit, mixing it into the declaration is fine — just make sure other values have proper units.
<!-- ✅ Valid: 0 doesn't need a unit -->
<div style="box-shadow: 0 0 10px 2px rgba(0,0,0,0.75);">
Shadow text
</div>
Multiple shadows
Multiple shadow values are separated by commas. Each individual shadow must independently follow the correct syntax.
<!-- ✅ Valid: two properly formatted shadows -->
<div style="box-shadow: 2px 2px 5px #888, inset 0 0 10px 2px blue;">
Multiple shadows
</div>
Vendor-prefixed property
The W3C validator does not recognize vendor-prefixed properties. If you need them for legacy browser support, keep the standard property alongside.
<!-- ❌ Triggers a warning or error in the validator -->
<div style="-webkit-box-shadow: 3px 3px 6px #000;">
Shadow text
</div>
<!-- ✅ Valid: use the standard property -->
<div style="box-shadow: 3px 3px 6px #000;">
Shadow text
</div>
The box-shadow property applies one or more shadow effects to an element. Its syntax accepts several values in a flexible order:
box-shadow: <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>? inset?;
The <color> component is optional — if omitted, it defaults to currentcolor. However, when a color is provided, it must be a valid CSS color value. The validator raises this error when it encounters something in the color position that doesn’t match any recognized color format.
Common causes of this error include:
- Misspelled color names — e.g., greyy instead of grey, or balck instead of black.
- Invalid hex codes — e.g., #GGG or #12345 (hex codes must be 3, 4, 6, or 8 hex digits).
- Fabricated color names — e.g., banana or darkwhite, which are not part of the CSS named colors specification.
- Malformed function syntax — e.g., rgb(0,0,0,0.3) using the legacy comma syntax with four values instead of rgba(), or missing parentheses.
- Incorrect value order — placing values in an unexpected position can cause the validator to misinterpret a non-color value as a color attempt.
This matters for standards compliance because browsers may silently ignore an invalid box-shadow declaration entirely, meaning your intended shadow effect won’t render. Using valid CSS ensures consistent behavior across browsers and passes validation checks.
Recognized CSS color formats
The following formats are valid for the color component:
- Named colors: red, blue, transparent, currentcolor, etc.
- Hex codes: #000, #0000, #000000, #00000080
- RGB/RGBA: rgb(0, 0, 0), rgba(0, 0, 0, 0.5), or the modern rgb(0 0 0 / 50%)
- HSL/HSLA: hsl(0, 0%, 0%), hsla(0, 0%, 0%, 0.5), or hsl(0 0% 0% / 50%)
Examples
Incorrect — misspelled or invalid color values
<!-- "balck" is not a valid color name -->
<div style="box-shadow: 2px 4px 8px balck;">Typo in color</div>
<!-- "banana" is not a recognized CSS color -->
<div style="box-shadow: 2px 4px 8px banana;">Invalid color name</div>
<!-- "#12345" is not a valid hex code (5 digits) -->
<div style="box-shadow: 2px 4px 8px #12345;">Bad hex code</div>
Correct — valid color values
<!-- Named color -->
<div style="box-shadow: 2px 4px 8px black;">Named color</div>
<!-- Hex color -->
<div style="box-shadow: 2px 4px 8px #333;">Hex color</div>
<!-- RGBA for semi-transparency -->
<div style="box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.3);">Semi-transparent</div>
<!-- HSL color -->
<div style="box-shadow: 2px 4px 8px hsl(210, 50%, 40%);">HSL color</div>
Correct — omitting the color entirely
If you want the shadow to inherit the element’s text color, you can omit the color value altogether. This is valid and avoids the error:
<!-- Defaults to currentcolor -->
<div style="box-shadow: 2px 4px 8px;">Uses currentcolor</div>
Correct — multiple shadows with valid colors
<div style="box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2), inset 0 0 6px #ccc;">
Multiple shadows
</div>
To resolve this validation error, check the exact value the validator flags (the “X” in the error message), verify its spelling against the list of CSS named colors, and ensure any hex or function-based color uses correct syntax. If the color isn’t needed, simply remove it and let the browser default to currentcolor.
The clip-path property defines a clipping region that controls which parts of an element are visible. It accepts a specific set of value types, and any deviation from the expected syntax will trigger a validation error. The validator checks your CSS against the specification and flags values that don’t conform.
The accepted value types for clip-path are:
- none — No clipping (the default).
- Basic shape functions — inset(), circle(), ellipse(), polygon(), and path().
- url() reference — Points to an SVG <clipPath> element, e.g., url(#myClip).
- Geometry-box keywords — border-box, padding-box, content-box, margin-box, fill-box, stroke-box, view-box. These can be used alone or combined with a basic shape.
Here are the most common mistakes that cause this error:
- Missing units on length values. Writing circle(50 at 50% 50%) is invalid because 50 needs a unit like px, em, or %. The value 0 is the only length that doesn’t require a unit.
- Wrong separators. In circle() and ellipse(), the position coordinates after at must be separated by spaces, not commas. In polygon(), each coordinate pair uses a space between x and y, while commas separate the points from each other.
- Malformed path() data. The SVG path string inside path() must be wrapped in quotes, e.g., path("M0 0 L100 0 L100 100 Z").
- Typos or unsupported functions. Using a function name the specification doesn’t define, or misspelling one like cirlce(), will trigger the error.
- Invalid polygon() fill-rule. If you specify a fill rule in polygon(), it must be nonzero or evenodd, followed by a comma before the first point.
Getting clip-path syntax right matters for standards compliance and cross-browser consistency. Browsers may silently ignore an invalid clip-path value, meaning your intended visual effect simply won’t appear — and you may not realize why. Validating your CSS catches these issues early.
Here is a quick reference for the correct syntax of each basic shape function:
- circle(<radius> at <cx> <cy>) — Radius is a length or percentage. Position uses spaces, not commas.
- ellipse(<rx> <ry> at <cx> <cy>) — Both radii are lengths or percentages.
- inset(<top> <right> <bottom> <left> round <border-radius>) — Offsets are lengths or percentages. The round keyword and border-radius are optional.
- polygon([<fill-rule>,] <x1> <y1>, <x2> <y2>, ...) — Space between x and y within a point; comma between points.
- path("<SVG path data>") — Path data string must be quoted.
Examples
Invalid clip-path values
<style>
/* Invalid: unitless radius; comma between position coordinates */
.clip-a {
clip-path: circle(50 at 50%, 50%);
}
/* Invalid: commas between x and y within each point */
.clip-b {
clip-path: polygon(0%, 0%, 100%, 0%, 100%, 100%, 0%, 100%);
}
/* Invalid: path data not wrapped in quotes */
.clip-c {
clip-path: path(M0 0 L100 0 L100 100 Z);
}
/* Invalid: misspelled function name */
.clip-d {
clip-path: cirlce(50% at 50% 50%);
}
</style>
Valid clip-path values
<style>
/* Valid circle: radius has a unit; position uses spaces */
.clip-a {
clip-path: circle(50px at 50% 50%);
}
/* Valid polygon: space between x and y, commas between points */
.clip-b {
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
}
/* Valid path: SVG data is quoted */
.clip-c {
clip-path: path("M0 0 L100 0 L100 100 Z");
}
/* Valid inset with rounded corners */
.clip-d {
clip-path: inset(10% 20% 10% 20% round 8px);
}
/* Valid geometry-box keyword combined with a shape */
.clip-e {
clip-path: padding-box circle(50% at 50% 50%);
}
/* Valid: referencing an SVG clipPath */
.clip-f {
clip-path: url(#roundClip);
}
</style>
Full example with SVG <clipPath> reference
<!doctype html>
<html lang="en">
<head>
<title>Valid clip-path with SVG reference</title>
<style>
.clipped {
clip-path: url(#roundClip);
width: 200px;
height: 200px;
background: coral;
}
</style>
</head>
<body>
<svg width="0" height="0" aria-hidden="true">
<clipPath id="roundClip" clipPathUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.5"></circle>
</clipPath>
</svg>
<div class="clipped">Clipped element</div>
</body>
</html>
When you encounter this validation error, carefully check the value reported in the error message. Compare it against the accepted syntax for the function you’re using, paying close attention to units, separators, and quoting. Small syntax differences — a comma where a space should be, or a missing unit — are the most frequent culprits.
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 cursor property controls the appearance of the mouse pointer when it hovers over an element. The value hand was introduced by early versions of Internet Explorer (IE 5.5 and earlier) as a proprietary extension to show a pointing-hand cursor over clickable elements. However, this value was never part of any CSS specification, and no other browser adopted it. The W3C-standard equivalent is pointer, which has been supported by all browsers — including Internet Explorer 6 and later — for over two decades.
When the W3C validator encounters cursor: hand, it flags it as an invalid value because hand does not exist in the CSS specification’s list of accepted cursor values. While some legacy browsers may still interpret it, modern browsers will simply ignore the invalid declaration, meaning your clickable elements won’t display the expected hand cursor for many users.
Beyond validation, using non-standard CSS values can cause inconsistent behavior across browsers and platforms. The pointer value is universally supported and is the correct way to signal that an element is interactive, such as a link, button, or any custom clickable region.
To fix this issue, replace every instance of cursor: hand with cursor: pointer in your stylesheets. If you need to support extremely old versions of Internet Explorer (IE 5.5 or earlier), you can declare both values — the browser will use whichever it recognizes — though this is almost never necessary today.
Examples
Invalid CSS
The value hand is not recognized by the CSS specification and will trigger a validation error:
.clickable {
cursor: hand;
}
Valid CSS
Use the standard pointer value instead:
.clickable {
cursor: pointer;
}
Using it in context with HTML
<style>
.card {
padding: 16px;
border: 1px solid #ccc;
cursor: pointer;
}
</style>
<div class="card">
Click me to view details
</div>
Legacy fallback (rarely needed)
If for some reason you must support IE 5.5 or earlier alongside modern browsers, you can provide both declarations. The browser will apply the last value it understands:
.clickable {
cursor: hand;
cursor: pointer;
}
Note that this fallback pattern will still produce a validation warning for the hand value. In practice, there is virtually no reason to support browsers this old, so using cursor: pointer alone is the recommended approach.
Common cursor values
For reference, here are some of the most frequently used valid cursor values defined in the CSS specification:
- auto — the browser determines the cursor based on context (default behavior)
- default — the platform’s default cursor, typically an arrow
- pointer — a pointing hand, indicating a link or clickable element
- text — an I-beam, indicating selectable text
- move — indicates something can be moved
- not-allowed — indicates an action is not permitted
- grab / grabbing — indicates a draggable element
- crosshair — a precise selection cursor
- wait — indicates the program is busy
- help — indicates help is available
The full list of accepted values is defined in the CSS Basic User Interface Module specification.
The device-width and device-height media features (including their min- and max- prefixed versions) were originally designed to query the physical dimensions of a device’s screen. In practice, this caused significant problems. On high-DPI (Retina) displays, max-device-width could report unexpected values depending on the device pixel ratio. When users resized their browser window, these features didn’t respond because the physical screen size never changed. And with browser zoom, the layout could break because the query still referenced the fixed device dimensions rather than the actual available space.
The Media Queries Level 4 specification formally deprecated these features. Modern browsers still support them for backward compatibility, but they should not be used in new code. The W3C validator raises this warning to encourage migration to the current standard.
The viewport-based equivalents — width, min-width, and max-width — respond to the browser’s layout viewport. This means they correctly adapt when the user resizes the window, zooms the page, or views the page in a split-screen mode. They also behave consistently across devices regardless of pixel density.
If your existing code uses max-device-width or min-device-width, the fix is straightforward: drop the word device from the feature name. For example, max-device-width: 768px becomes max-width: 768px. If you were relying on device dimensions to detect high-DPI screens, use the resolution media feature instead (e.g., min-resolution: 2dppx), which is the standards-compliant replacement for vendor-prefixed features like -webkit-min-device-pixel-ratio.
When choosing breakpoint values, prefer content-driven breakpoints — values where your layout actually needs to adapt — rather than targeting specific device widths. This produces more resilient designs that work well on any screen size.
Examples
Deprecated usage triggering the warning
The max-device-width media feature in the <style> block triggers the validator warning:
<!doctype html>
<html lang="en">
<head>
<title>Deprecated Media Feature</title>
<style>
/* Deprecated: queries the physical device screen */
@media only screen and (max-device-width: 480px) {
body {
background: pink;
}
}
</style>
</head>
<body>
<p>This page uses a deprecated media feature.</p>
</body>
</html>
The same warning appears if the deprecated feature is used in a <link> element’s media attribute:
<link rel="stylesheet" href="mobile.css" media="(max-device-width: 480px)">
Fixed example using viewport-based queries
Replace max-device-width with max-width to query the viewport instead:
<!doctype html>
<html lang="en">
<head>
<title>Viewport-Based Media Query</title>
<style>
/* Correct: responds to the viewport width */
@media (max-width: 480px) {
body {
background: pink;
}
}
</style>
</head>
<body>
<p>This page uses a modern media feature.</p>
</body>
</html>
And for the <link> element:
<link rel="stylesheet" href="mobile.css" media="(max-width: 480px)">
Replacing device pixel ratio queries
If you were using device-width features alongside -webkit-min-device-pixel-ratio to target high-DPI screens, switch to the standard resolution feature:
<style>
/* Deprecated approach */
@media (-webkit-min-device-pixel-ratio: 2) {
.logo {
background-image: url("logo@2x.png");
}
}
/* Standards-compliant replacement */
@media (min-resolution: 2dppx) {
.logo {
background-image: url("logo@2x.png");
}
}
</style>
Quick reference of replacements
| Deprecated feature | Modern replacement |
|---|---|
| max-device-width | max-width |
| min-device-width | min-width |
| max-device-height | max-height |
| min-device-height | min-height |
| -webkit-min-device-pixel-ratio: 2 | min-resolution: 2dppx |
The min-device-width and max-device-width media features were originally designed to query the physical screen dimensions of a device. However, these features have been deprecated in Media Queries Level 4 and Level 5 because they are unreliable in modern browsing contexts. The physical screen size is a poor proxy for the actual available layout space — it doesn’t account for browser chrome, split-screen modes, zoom levels, or the fact that many modern devices report abstract pixel values that don’t correspond to physical hardware pixels in a straightforward way.
The viewport-based alternatives — min-width and max-width — respond to the layout viewport, which is the actual space your content is rendered into. This makes them far more useful for responsive design. When a user zooms in, the layout viewport shrinks, and min-width/max-width queries respond accordingly. With min-device-width, zooming has no effect on the query result, which can lead to layouts that don’t adapt when they should.
Beyond practical concerns, using deprecated features means your CSS may behave inconsistently across browsers in the future, as support could be removed entirely. Validators flag this to encourage migration to the modern, standards-compliant approach.
How to fix it
The fix is a straightforward replacement:
- min-device-width → min-width
- max-device-width → max-width
If your original query also included the screen keyword solely to pair with device-width targeting, you can safely drop it — min-width and max-width apply across all media types and the screen qualifier is rarely necessary in modern CSS.
If you were using min-device-width to detect high-density or Retina displays (a common pattern in older code), the correct modern approach is to use the resolution media feature instead, such as min-resolution: 2dppx.
Examples
Deprecated usage (triggers warning)
<!doctype html>
<html lang="en">
<head>
<title>Deprecated media feature</title>
<style>
@media screen and (min-device-width: 768px) {
.sidebar { display: block; }
}
@media screen and (max-device-width: 480px) {
.sidebar { display: none; }
}
</style>
</head>
<body>
<aside class="sidebar">Sidebar content</aside>
</body>
</html>
Both min-device-width and max-device-width are deprecated and will produce validation warnings.
Fixed example using viewport-based queries
<!doctype html>
<html lang="en">
<head>
<title>Viewport-based media queries</title>
<style>
@media (min-width: 768px) {
.sidebar { display: block; }
}
@media (max-width: 480px) {
.sidebar { display: none; }
}
</style>
</head>
<body>
<aside class="sidebar">Sidebar content</aside>
</body>
</html>
Replacing device-width with resolution for pixel density
Older code sometimes used min-device-width in combination with -webkit-min-device-pixel-ratio to target high-density screens. The modern equivalent uses the resolution media feature:
<!doctype html>
<html lang="en">
<head>
<title>Resolution media query</title>
<style>
/* Deprecated approach */
/*
@media screen and (min-device-width: 768px) and (-webkit-min-device-pixel-ratio: 2) {
.hero { background-image: url("hero@2x.jpg"); }
}
*/
/* Modern approach */
@media (min-width: 768px) and (min-resolution: 2dppx) {
.hero { background-image: url("hero@2x.jpg"); }
}
</style>
</head>
<body>
<div class="hero">Hero section</div>
</body>
</html>
The min-resolution: 2dppx query cleanly replaces vendor-prefixed pixel ratio queries and works alongside the standard min-width viewport query.
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>
The correct value is nowrap (without a hyphen), not no-wrap.
The flex-wrap CSS property controls whether flex items are forced onto a single line or can wrap onto multiple lines. It accepts three values: nowrap (the default), wrap, and wrap-reverse. A common mistake is writing no-wrap with a hyphen, likely because the white-space CSS property uses nowrap and no-wrap interchangeably in some contexts, or simply because it looks more natural in English. However, for flex-wrap, only the unhyphenated nowrap is valid.
HTML Example With the Issue
<div style="display: flex; flex-wrap: no-wrap;">
<p>Item 1</p>
<p>Item 2</p>
</div>
Fixed HTML Example
<div style="display: flex; flex-wrap: nowrap;">
<p>Item 1</p>
<p>Item 2</p>
</div>
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>
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