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.
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: 10instead ofborder-radius: 10px. CSS requires explicit units for all non-zero length values. - Invalid keywords: Using a keyword like
border-radius: largethat isn't part of the CSS specification. - Negative values: The
border-radiusproperty does not accept negative lengths or percentages. - Unresolvable
var()references: The W3C validator performs static analysis and cannot evaluate CSS custom properties. If you usevar(--my-radius)in an inlinestyleattribute, 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 asborder-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
0as 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 flagvar()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
marginorpadding) doesn't work withborder. Unlike box-model spacing properties,borderdoes not accept per-side values in its shorthand. - Misspelled keywords — A typo like
sollidinstead ofsolid, ordotedinstead ofdotted, 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 blackinstead of1px solid blackcreates an unrecognized token. - Using
bordersyntax forborder-radiusor other properties — Accidentally placing values like5px 10px 5px 10pxonborderinstead of onborder-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, oroutset. - 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
undefinedwith a proper CSS color — a named color (red,black), a hex code (#333), anrgb()orhsl()function, or eventransparentorcurrentcolor. - Remove the declaration. If no border is needed, remove the
borderproperty 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, ortransparent
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, or0.1cm. The value must not be negative. - Keywords — exactly three are defined:
thin,medium, andthick. These map to implementation-defined sizes but are guaranteed to maintain the relationshipthin ≤ 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: 2instead ofborder-width: 2px. The only unitless length allowed in CSS is0. - Misspelled or invented keywords — using
large,small,normal, ornoneinstead ofthin,medium, orthick. - Wrong value type — accidentally using a color name, percentage, or other non-length value.
- Typos in units — writing
5xpinstead of5px.
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.
A CSS border shorthand property has been assigned a value that the validator expects to be a color, but the value provided is not a recognized color.
This error typically appears when the border shorthand is missing a required component or has its values in an unexpected order. The border shorthand accepts up to three values: a width, a style, and a color. While the CSS specification allows these in any order, some validators and parsers can misinterpret values when the style keyword (such as solid, dashed, or none) is omitted.
A common cause is writing something like border: 1px black without a border style. The validator may try to interpret black or another value as filling the wrong role. Another cause is a typo in the color value itself, such as grren instead of green, or using a syntax the validator does not recognize.
Always include all three components in the border shorthand to avoid ambiguity: width, style, and color.
HTML examples
Invalid border value
<p style="border: 1px black">Some text</p>
The missing style keyword (solid, dashed, etc.) can cause the validator to misinterpret which value maps to which component.
Valid border value
<p style="border: 1px solid black">Some text</p>
Including the width (1px), style (solid), and color (black) removes any ambiguity. If a border style is not specified, the initial value is none, which means no border is rendered, so omitting it is almost certainly a mistake anyway.
Negative values for the CSS border property (specifically border-width) are not valid and will be rejected by browsers.
The border-width property only accepts non-negative length values (like 1px, 0.5em) or keyword values (thin, medium, thick). A negative value such as -1px doesn't make sense for a border since you can't have a border with negative thickness.
This error often appears when using inline styles or embedded <style> blocks. It can result from a typo, a calculation error, or a misunderstanding of how border works.
If you're trying to remove a border, use border: none or border-width: 0 instead of a negative value.
Incorrect Example
<div style="border: -1px solid black;">
This has an invalid negative border width.
</div>
Correct Example
<!-- Using a valid positive border width -->
<div style="border: 1px solid black;">
This has a valid border.
</div>
<!-- Removing the border entirely -->
<div style="border: none;">
This has no border.
</div>
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 value0is the only length that doesn't require a unit.<blur-radius>(optional): Must be a non-negative length. Defaults to0.<spread-radius>(optional): Can be positive or negative. Defaults to0. 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 10instead of10px 10px. - Invalid or misspelled keywords — Using something like
outerboxorshadowsinstead ofinsetornone. - Too many or too few values — Providing five length values when the maximum is four.
- Vendor prefixes — Using
-webkit-box-shadowor non-standard values that the standard validator rejects. - Invalid color values — Using a malformed color like
rgb(0,0,0,0.5)(missing theainrgbafor 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.,
greyyinstead ofgrey, orbalckinstead ofblack. - Invalid hex codes — e.g.,
#GGGor#12345(hex codes must be 3, 4, 6, or 8 hex digits). - Fabricated color names — e.g.,
bananaordarkwhite, 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 ofrgba(), 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 modernrgb(0 0 0 / 50%) - HSL/HSLA:
hsl(0, 0%, 0%),hsla(0, 0%, 0%, 0.5), orhsl(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(), andpath(). 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 because50needs a unit likepx,em, or%. The value0is the only length that doesn't require a unit. - Wrong separators. In
circle()andellipse(), the position coordinates afteratmust be separated by spaces, not commas. Inpolygon(), 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 insidepath()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 inpolygon(), it must benonzeroorevenodd, 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. Theroundkeyword 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
0or123— numbers alone aren't colors. - Typos in color keywords such as
greaninstead ofgreen, ortrasparentinstead oftransparent. - 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
000000instead 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 does not accept arrow as a value. To show the standard arrow pointer, use cursor: default, which is the platform's default cursor on most systems.
The cursor property sets the mouse pointer shown when the pointer is over an element. Its keywords are spelled out in the CSS specification, and arrow is not among them. The name people reach for is intuitive, since the everyday pointer is an arrow, but the keyword that produces it is default. When the validator meets cursor: arrow, it rejects the whole declaration, so the browser ignores it and falls back to whatever cursor it would have used anyway.
This usually goes unnoticed because the default cursor already is an arrow, so nothing looks broken. The cost shows up when you set cursor: arrow to override an inherited value, for example to reset the pointer back to normal inside an element that set cursor: pointer. The invalid declaration is dropped and the inherited cursor stays in place.
Invalid example
The value arrow is not recognized and triggers a validation error:
<div style="cursor: arrow;">
Hover over me
</div>
Valid example
Use default to get the standard arrow pointer:
<div style="cursor: default;">
Hover over me
</div>
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 arrowpointer— a pointing hand, indicating a link or clickable elementtext— an I-beam, indicating selectable textmove— indicates something can be movednot-allowed— indicates an action is not permittedgrab/grabbing— indicates a draggable elementcrosshair— a precise selection cursorwait— indicates the program is busyhelp— 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-widthmax-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, ordisplay: flxinstead of the correct keywords. - Confusing values from other properties — using values like
center,hidden,absolute, orrelative, which belong to properties liketext-align,visibility, orposition, notdisplay. - 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-flexwere 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 fill property does not accept linear-gradient() as a valid value.
The fill property is used primarily with SVG elements to define the color that fills the interior of a shape. It accepts simple color values like named colors, hex codes, rgb(), hsl(), currentColor, none, or a reference to an SVG paint server using url().
CSS gradients such as linear-gradient() are classified as <image> values, not <color> values, so they cannot be used directly with fill. This is different from properties like background or background-image, which do accept gradient values.
If you need a gradient fill on an SVG element, you should define a <linearGradient> inside an SVG <defs> block and reference it with url().
How to fix it
Invalid: Using linear-gradient() with fill:
<svg width="100" height="100">
<rect width="100" height="100" style="fill: linear-gradient(to right, red, blue);" />
</svg>
Valid: Using an SVG <linearGradient> definition:
<svg width="100" height="100">
<defs>
<linearGradient id="myGradient" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="red" />
<stop offset="100%" stop-color="blue" />
</linearGradient>
</defs>
<rect width="100" height="100" fill="url(#myGradient)" />
</svg>
The x1, y1, x2, and y2 attributes on <linearGradient> control the direction of the gradient. In this example, x1="0" x2="1" creates a left-to-right gradient, equivalent to to right in CSS.
An invalid value was passed to the drop-shadow() function inside the CSS filter property.
The drop-shadow() function accepts a shadow definition similar to box-shadow, but with some restrictions. It takes two or three length values (offset-x, offset-y, and an optional blur-radius), plus an optional color. Unlike box-shadow, it does not accept a spread-radius value or the inset keyword.
The correct syntax is:
filter: drop-shadow(offset-x offset-y blur-radius color);
Each parameter has specific requirements:
offset-xandoffset-yare required length values (e.g.,2px,0.5em).blur-radiusis optional and must be a non-negative length. Negative values are not allowed.coloris optional. If omitted, the browser uses the element'scolorproperty value.
Common mistakes that trigger this error include adding a spread-radius (a fourth length value), using the inset keyword, or passing a malformed color value.
Examples
This is invalid because drop-shadow() does not support a spread-radius (the 5px fourth length value):
<div style="filter: drop-shadow(4px 4px 10px 5px red);">
Shadow content
</div>
Remove the spread-radius to fix it:
<div style="filter: drop-shadow(4px 4px 10px red);">
Shadow content
</div>
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)orfilter: 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
filterfunction. - If you're using legacy IE opacity filters, switch to the standard
opacityproperty 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>
CSS custom properties (variables) used in the flex shorthand are not recognized by the W3C CSS validator, even though they work correctly in all modern browsers. This is a known limitation of the validator, not a bug in your code.
The W3C CSS validator performs static analysis and cannot resolve var() expressions at validation time. It doesn't know that --flex-grow will eventually hold a valid value like 1 or 0, so it flags the declaration as invalid. This affects many CSS properties when custom properties are used, not just flex.
You have a few options. You can safely ignore this specific warning since the code is valid per the CSS specification. Alternatively, you can restructure your CSS to apply the variable to a more specific property like flex-grow instead of the shorthand, which sometimes avoids the validator complaint.
HTML Examples
Before: Using var() in the flex shorthand
<style>
:root {
--flex-grow: 1;
}
.item {
flex: var(--flex-grow);
}
</style>
<div style="display: flex;">
<div class="item">Content</div>
</div>
After: Using var() on individual flex properties
<style>
:root {
--flex-grow: 1;
}
.item {
flex-grow: var(--flex-grow);
flex-shrink: 1;
flex-basis: 0%;
}
</style>
<div style="display: flex;">
<div class="item">Content</div>
</div>
Both versions produce the same result in browsers. The second approach uses individual flex-grow, flex-shrink, and flex-basis properties, which may reduce validator noise. That said, this is a false positive from the validator — your original code is perfectly valid CSS.
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-displaydescriptor in your@font-facerule, you lose control over how the browser handles text rendering while custom fonts load. Usingfont-display: swap, for example, ensures text remains visible with a fallback font until the custom font is ready — a key web performance best practice. - Standards compliance: The CSS Fonts Module Level 4 specification defines
font-displayexclusively as a@font-facedescriptor. Using it elsewhere produces invalid CSS. - Silent failure: Browsers won't throw visible errors — they simply ignore the invalid property, which can make it difficult to diagnose why your font-loading behavior isn't working as expected.
How to fix it
- Remove
font-displayfrom any regular CSS rule (selectors likebody,h1,.class, etc.). - Add
font-displayinside the@font-faceat-rule where you define your custom font. - If you're loading fonts via a third-party service (like Google Fonts), you can often append a
&display=swapparameter to the font URL instead of writing your own@font-faceblock.
Examples
❌ Incorrect: font-display used as a CSS property
body {
font-family: "Open Sans", sans-serif;
font-display: swap;
}
This triggers the validator error because font-display is not a valid CSS property for element selectors.
✅ Correct: font-display used inside @font-face
@font-face {
font-family: "Open Sans";
src: url("/fonts/open-sans.woff2") format("woff2"),
url("/fonts/open-sans.woff") format("woff");
font-display: swap;
}
body {
font-family: "Open Sans", sans-serif;
}
Here, font-display: swap is correctly placed inside the @font-face rule, telling the browser to immediately render text with a fallback font and then swap in "Open Sans" once it finishes loading.
✅ Correct: Using display=swap with Google Fonts
If you use Google Fonts, you don't need to write your own @font-face block. Instead, add the display parameter to the URL:
<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.
A CSS syntax error in your font-family declaration is using an invalid character or operator where the validator expects a comma-separated list of font names.
The font-family property expects font names separated by commas. A common mistake is using operators like +, =, or / between font names, or copying malformed font names from URLs (like Google Fonts link URLs where + replaces spaces). Font names with spaces must be wrapped in quotes.
For example, font-family: Open+Sans is invalid because + is not a valid CSS operator in this context. The correct form is font-family: "Open Sans". Similarly, using font-family: Arial / Helvetica is invalid — a comma should separate fallback fonts.
Invalid Example
<p style="font-family: Open+Sans, sans-serif;">Hello</p>
Fixed Example
<p style="font-family: 'Open Sans', sans-serif;">Hello</p>
Double-check that your font names use commas as separators, quotes around names with spaces, and no stray characters like +, /, or =.
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-sizedeclaration 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.,
16or16px) 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>
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