HTML Guides for css
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The text-overflow CSS property controls how overflowed content that is not displayed is signaled to users. It applies when an element's overflow is hidden (e.g., overflow: hidden) and the content exceeds the element's box. The property accepts specific values, and using anything outside the allowed set — such as a misspelled keyword, an unquoted string, or a made-up value — will trigger this validation error.
Accepted values
The text-overflow property accepts the following values:
clip— Truncates the text at the edge of the content area. Characters may be clipped mid-glyph. This is the default.ellipsis— Displays an ellipsis character (…) to indicate clipped text.- A custom
<string>— A quoted string to display at the clipping point (e.g.," [..]"). Note that browser support for custom strings is limited. - Global CSS values —
inherit,initial,revert,revert-layer, andunset.
The property can take one or two values. If one value is given, it specifies the overflow behavior for the end of the line (the right end for left-to-right text, the left end for right-to-left text). If two values are given, the first controls the left end of the line and the second controls the right end. Two-value syntax has limited browser support.
Common mistakes that trigger this error include:
- Misspelling
ellipsis(e.g.,elipsis,ellipses). - Using a value from a different property (e.g.,
hidden,scroll,auto). - Using an unquoted custom string instead of a properly quoted one.
- Using a numeric or length value (e.g.,
10px), which is not valid for this property.
Why this matters
Invalid CSS values are ignored by browsers, which means the property will fall back to its default (clip) instead of behaving as you intended. This can lead to text being abruptly cut off without any visual indicator, harming readability and user experience. Fixing validation errors also ensures your stylesheets are clean, predictable, and maintainable.
Examples
Incorrect — misspelled keyword
/* "elipsis" is not a valid text-overflow value */
.truncated{
overflow: hidden;
white-space: nowrap;
text-overflow: elipsis;
}
Incorrect — value from another property
/* "hidden" is an overflow value, not a text-overflow value */
.truncated{
overflow: hidden;
white-space: nowrap;
text-overflow: hidden;
}
Incorrect — unquoted custom string
/* Custom strings must be quoted */
.truncated{
overflow: hidden;
white-space: nowrap;
text-overflow:[more];
}
Correct — using ellipsis
.truncated{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
Correct — using clip (the default)
.truncated{
overflow: hidden;
white-space: nowrap;
text-overflow: clip;
}
Correct — using a quoted custom string
.truncated{
overflow: hidden;
white-space: nowrap;
text-overflow:" [..]";
}
Correct — two-value syntax
/* Left end uses ellipsis, right end uses a custom string */
.truncated{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis " [..]";
}
Note that text-overflow on its own does not force overflow to occur. To make text actually truncate, you typically need overflow: hidden (or another non-visible overflow value) and white-space: nowrap on the element. The text-overflow property only controls how the clipped content is signaled visually.
The text-transform CSS property controls the capitalization of text within an element. It's commonly used to enforce consistent text casing — for example, making headings appear in all uppercase or ensuring navigation links are lowercase — without changing the actual content in the HTML. When the validator encounters a value it doesn't recognize for this property, it flags it as invalid.
This error can occur for several reasons:
- Typos — writing
upppercaseinstead ofuppercase, orCapitalizeinstead ofcapitalize(CSS values are case-sensitive in validation contexts). - Incorrect values — using values from other properties, like
bold,italic, orcenter, which don't apply totext-transform. - Non-standard values — using browser-specific or experimental values that aren't part of the CSS specification.
- Wrong property — confusing
text-transformwithtext-decoration,text-align, orfont-variant, and using their values here instead.
Fixing this matters because invalid CSS can lead to unpredictable rendering across browsers. While most browsers will simply ignore an invalid declaration, your intended styling won't be applied, potentially breaking your design. Keeping your CSS valid also improves maintainability and ensures forward compatibility.
Valid values for text-transform
| Value | Effect |
|---|---|
none | No capitalization change (default) |
capitalize | First letter of each word is uppercased |
uppercase | All characters are converted to uppercase |
lowercase | All characters are converted to lowercase |
full-width | Forces characters into a full-width form (useful for CJK typography) |
full-size-kana | Converts small kana characters to full-size equivalents |
Examples
Incorrect — invalid value
In this example, bold is not a valid text-transform value. It likely belongs on the font-weight property instead.
<pstyle="text-transform: bold;">Welcome to our site</p>
Similarly, a simple typo will trigger this error:
<pstyle="text-transform: uppercse;">Welcome to our site</p>
Correct — using valid values
<pstyle="text-transform: uppercase;">Welcome to our site</p>
<pstyle="text-transform: capitalize;">Welcome to our site</p>
Correct — separating concerns with the right properties
If you intended to make text bold and uppercase, use the appropriate property for each effect:
<pstyle="font-weight: bold;text-transform: uppercase;">Welcome to our site</p>
Correct — using text-transform in a stylesheet
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="utf-8">
<title>Text Transform Example</title>
<style>
.heading{
text-transform: uppercase;
}
.name{
text-transform: capitalize;
}
.code-snippet{
text-transform: none;
}
</style>
</head>
<body>
<h1class="heading">site navigation</h1>
<pclass="name">john doe</p>
<codeclass="code-snippet">myVariable</code>
</body>
</html>
If you're unsure which value you need, uppercase and capitalize are the most commonly used. Use none when you need to override a text-transform rule inherited from a parent element.
The @charset rule in a <style> element is not valid because @charset only applies to external CSS files, not inline styles.
When CSS is embedded inside a <style> element, the character encoding is already determined by the HTML document itself (through the <meta charset> declaration or the HTTP Content-Type header). The @charset rule has no effect in this context, and the W3C validator flags it as an error.
This error also appears when @charset is present in an external .css file but is not on the very first line, or has a space or BOM (byte order mark) before it. In external stylesheets, @charset must be the absolute first thing in the file, with no preceding whitespace or comments.
How to fix it
If the @charset rule is inside a <style> element, remove it:
<!-- Wrong: @charset inside a style element -->
<style>
@charset"UTF-8";
body{
color:#333;
}
</style>
<!-- Fixed: remove the @charset rule -->
<style>
body{
color:#333;
}
</style>
If the @charset rule is in an external stylesheet, make sure it is on the very first line with no preceding spaces, BOM characters, or comments:
@charset"UTF-8";
body{
color:#333;
}
The word-break property controls how words break when they would overflow their container. While break-word was historically used as a value for this property, the CSS Text Module Level 3 specification has deprecated it. As the spec explains:
For compatibility with legacy content, the word-break property also supports a deprecated
break-wordkeyword. When specified, this has the same effect asword-break: normalandoverflow-wrap: anywhere, regardless of the actual value of theoverflow-wrapproperty.
Browsers still support word-break: break-word for backward compatibility, but relying on deprecated values is risky. Future browser versions may remove support, and validators will flag it as an issue. The correct approach is to use the overflow-wrap property instead, which is specifically designed to control whether and how words break when they overflow their container.
There are two modern alternatives to consider:
overflow-wrap: break-word— allows the browser to break an otherwise unbreakable word at an arbitrary point to prevent overflow. The word only breaks if it cannot fit on its own line. This is the most widely supported option.overflow-wrap: anywhere— works likebreak-wordbut also allows the broken word fragments to be considered during min-content sizing calculations. This means containers usingmin-contentorfit-contentwidths can shrink further.
In most cases, overflow-wrap: break-word is the right replacement.
Examples
Deprecated usage
This triggers the W3C CSS validation warning:
<divstyle="word-break: break-word;">
Thisislongtext_thatdoesnotcontainanyspaces_andshouldbreakproperly
</div>
Fixed with overflow-wrap: break-word
This is the most common and well-supported fix:
<divstyle="word-break: normal;overflow-wrap: break-word;">
Thisislongtext_thatdoesnotcontainanyspaces_andshouldbreakproperly
</div>
Fixed with overflow-wrap: anywhere
Use this if you also want min-content sizing to account for the broken fragments:
<divstyle="word-break: normal;overflow-wrap: anywhere;">
Thisislongtext_thatdoesnotcontainanyspaces_andshouldbreakproperly
</div>
In a stylesheet
If the deprecated value appears in a CSS file or <style> block, apply the same fix:
<style>
/* Deprecated */
/* .content { word-break: break-word; } */
.content {
word-break: break-word;
}
*/
/* Correct */
.content{
word-break: normal;
overflow-wrap: break-word;
}
</style>
<divclass="content">
Thisislongtext_thatdoesnotcontainanyspaces_andshouldbreakproperly
</div>
Understanding the difference between overflow-wrap values
<style>
.container{
width: min-content;
border:1px solid black;
margin-bottom:1rem;
}
.wrap-break-word{
overflow-wrap: break-word;
}
.wrap-anywhere{
overflow-wrap: anywhere;
}
</style>
<!-- With break-word, min-content width is based on the longest word -->
<divclass="container wrap-break-word">
Short words here but_a_very_long_unbreakable_word_too
</div>
<!-- With anywhere, min-content can shrink past even long words -->
<divclass="container wrap-anywhere">
Short words here but_a_very_long_unbreakable_word_too
</div>
With overflow-wrap: break-word, the container's min-content width will be determined by the longest unbreakable string. With overflow-wrap: anywhere, even that long string can be broken, allowing the container to shrink further. For most use cases where you simply want to prevent text from overflowing a fixed-width container, overflow-wrap: break-word is the straightforward choice.
The transform CSS property lets you rotate, scale, skew, or translate an element by modifying its coordinate space. The W3C validator raises this error when the value assigned to transform doesn't conform to valid CSS syntax. This typically happens when:
- A transform function name is misspelled (e.g.,
rotateZtyped asrotatezin some contexts, orskewtyped asskeew). - Too many arguments are passed to a transform function (e.g.,
rotate(45deg, 20deg)instead ofrotate(45deg)). - Arguments are missing required units (e.g.,
rotate(45)instead ofrotate(45deg)). - Multiple transform functions are separated by commas instead of spaces.
- An invalid or non-existent function name is used (e.g.,
transform: flip()). - Vendor-prefixed values like
-webkit-transformsyntax are used in the standardtransformproperty incorrectly.
This matters for standards compliance because browsers may silently ignore an invalid transform declaration entirely, meaning none of your intended transformations will be applied. Catching these errors during validation helps prevent unexpected layout or visual issues.
Each transform function has a specific signature. For example, rotate() accepts exactly one angle value, translate() accepts one or two length/percentage values, and scale() accepts one or two numbers. Providing the wrong number or type of arguments triggers this error.
Examples
Incorrect: Comma-separated transform functions
Multiple transforms must be space-separated, not comma-separated.
<divstyle="transform:rotate(45deg),scale(1.5);">Transformed</div>
Correct: Space-separated transform functions
<divstyle="transform:rotate(45deg)scale(1.5);">Transformed</div>
Incorrect: Missing unit on rotation value
The rotate() function requires an angle unit such as deg, rad, grad, or turn.
<divstyle="transform:rotate(45);">Rotated</div>
Correct: Angle value with unit
<divstyle="transform:rotate(45deg);">Rotated</div>
Incorrect: Too many arguments in a function
The rotate() function accepts only one argument.
<divstyle="transform:rotate(45deg,20deg);">Rotated</div>
Correct: Single argument for rotate()
If you need to rotate around a specific axis, use rotateX(), rotateY(), or rotateZ() instead.
<divstyle="transform:rotateZ(45deg);">Rotated on Z axis</div>
Incorrect: Misspelled or non-existent function
<divstyle="transform:roate(30deg)scaleX(2);">Transformed</div>
Correct: Properly spelled function names
<divstyle="transform:rotate(30deg)scaleX(2);">Transformed</div>
Incorrect: Using translate without units on non-zero lengths
<divstyle="transform:translate(50,100);">Moved</div>
Correct: Length values with units
A value of 0 does not require a unit, but all other length values do.
<divstyle="transform:translate(50px,100px);">Moved</div>
Valid Transform Functions Reference
Here are the commonly used transform functions and their expected arguments:
translate(tx)ortranslate(tx, ty)— lengths or percentagestranslateX(tx),translateY(ty),translateZ(tz)— a single length/percentagescale(sx)orscale(sx, sy)— unitless numbersscaleX(sx),scaleY(sy),scaleZ(sz)— a single unitless numberrotate(angle)— a single angle value (e.g.,45deg)rotateX(angle),rotateY(angle),rotateZ(angle)— a single angleskew(ax)orskew(ax, ay)— angle valuesskewX(ax),skewY(ay)— a single anglematrix(a, b, c, d, tx, ty)— exactly six unitless numbersmatrix3d(...)— exactly sixteen unitless numbers
When combining multiple transforms, always separate them with spaces and verify each function's name and argument count against the specification.
The transform CSS property lets you rotate, scale, skew, or translate an element by modifying its coordinate space. The validator checks inline and embedded CSS for correctness, and it will flag any value it doesn't recognize as a valid transform value. Common mistakes include:
- Missing units on angles or lengths (e.g.,
rotate(45)instead ofrotate(45deg)) - Typos in function names (e.g.,
rotatee(10deg)ortranlate(10px)) - Wrong value types (e.g., using a color or a plain number where a function is expected)
- Missing commas or parentheses in function arguments
- Using non-existent functions (e.g.,
flip(180deg)is not a valid transform function) - Incorrect number of arguments (e.g.,
matrix()requires exactly 6 values)
This matters for standards compliance and predictable rendering. While browsers may silently ignore invalid transform values, the element simply won't be transformed — which can lead to subtle layout bugs that are hard to track down. Catching these errors at validation time helps you fix them before they reach users.
Examples
Invalid: missing angle unit
The rotate() function requires a value with an angle unit like deg, rad, turn, or grad.
<divstyle="transform:rotate(45);">Rotated text</div>
Fixed: adding the angle unit
<divstyle="transform:rotate(45deg);">Rotated text</div>
Invalid: typo in function name
<divstyle="transform:tranlateX(10px);">Shifted text</div>
Fixed: correcting the function name
<divstyle="transform:translateX(10px);">Shifted text</div>
Invalid: using a non-transform value
A plain number or unrelated keyword is not a valid transform value.
<divstyle="transform:200px;">Content</div>
Fixed: using a proper transform function
<divstyle="transform:translateX(200px);">Content</div>
Invalid: wrong number of arguments for matrix()
The matrix() function requires exactly six comma-separated numbers.
<divstyle="transform:matrix(1,2,3);">Content</div>
Fixed: providing all six arguments
<divstyle="transform:matrix(1,0,0,1,0,0);">Content</div>
Valid transform values reference
Here is a summary of all valid transform functions and the keyword/global values:
<style>
/* Keyword value */
.no-transform{transform: none;}
/* Translate functions */
.move-a{transform:translate(12px,50%);}
.move-b{transform:translateX(2em);}
.move-c{transform:translateY(3in);}
.move-d{transform:translateZ(2px);}
.move-e{transform:translate3d(12px,50%,3em);}
/* Rotate functions */
.spin-a{transform:rotate(0.5turn);}
.spin-b{transform:rotateX(10deg);}
.spin-c{transform:rotateY(10deg);}
.spin-d{transform:rotateZ(10deg);}
.spin-e{transform:rotate3d(1,2,3,10deg);}
/* Scale functions */
.grow-a{transform:scale(2,0.5);}
.grow-b{transform:scaleX(2);}
.grow-c{transform:scaleY(0.5);}
.grow-d{transform:scaleZ(0.3);}
.grow-e{transform:scale3d(2.5,1.2,0.3);}
/* Skew functions */
.lean-a{transform:skew(30deg,20deg);}
.lean-b{transform:skewX(30deg);}
.lean-c{transform:skewY(1.07rad);}
/* Other functions */
.depth{transform:perspective(500px);}
.matrix-2d{transform:matrix(1,0,0,1,0,0);}
.matrix-3d{transform:matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1);}
/* Multiple functions chained together */
.combo{transform:translateX(10px)rotate(10deg)translateY(5px);}
</style>
When troubleshooting this error, look at the specific value the validator reports as invalid. Compare it against the valid functions listed above, double-check spelling, ensure all arguments have correct units, and verify that parentheses and commas are properly placed.
The ::file-selector-button pseudo-element targets the button inside an <input type="file"> element — the part users click to open the file picker dialog. It is supported in all major modern browsers and is part of the CSS Pseudo-Elements Level 4 specification.
The W3C CSS Validator has not yet been updated to recognize ::file-selector-button, which causes it to flag the pseudo-element as invalid. This is a known bug that has been reported on GitHub. Because the validator's CSS grammar definitions lag behind the living standards, certain newer — but fully standardized — features trigger false positives.
Before ::file-selector-button was standardized, browsers used vendor-prefixed versions like ::-webkit-file-upload-button and ::-ms-browse. The unprefixed ::file-selector-button replaced these and is now the recommended approach.
What you should do
Since this is a validator limitation rather than an actual code issue, you can safely ignore this warning. Your CSS is standards-compliant. If you want to suppress the warning in a CI/CD pipeline or validation report, you can add a comment noting the false positive, but do not remove or change the pseudo-element — it is correct.
Browser support
::file-selector-button is supported in Chrome 89+, Firefox 82+, Safari 14.1+, and Edge 89+. For older browsers, you may include the vendor-prefixed versions as fallbacks, though these will also trigger validator warnings.
Examples
CSS that triggers the validator warning
::file-selector-button{
background-color:#4a90d9;
color: white;
border: none;
padding:8px16px;
border-radius:4px;
cursor: pointer;
}
This CSS is valid and correct despite the validator warning. It styles the file selector button with a custom background color, text color, and border radius.
Scoping to a specific input
input[type="file"]::file-selector-button{
background-color:#4a90d9;
color: white;
border: none;
padding:8px16px;
border-radius:4px;
}
input[type="file"]::file-selector-button:hover{
background-color:#357abd;
}
Including vendor-prefixed fallbacks for older browsers
input[type="file"]::-webkit-file-upload-button{
background-color:#4a90d9;
color: white;
border: none;
padding:8px16px;
}
input[type="file"]::file-selector-button{
background-color:#4a90d9;
color: white;
border: none;
padding:8px16px;
}
The vendor-prefixed version is placed first so that the standard ::file-selector-button rule takes precedence in browsers that support both. Note that the vendor-prefixed versions will also trigger validator warnings for the same reason.
Corresponding HTML
<labelfor="upload">Choose a file:</label>
<inputtype="file"id="upload"name="upload">
There is nothing to fix in your HTML or CSS. This is purely a validator false positive that will be resolved when the W3C Validator updates its CSS grammar definitions.
::ng-deep is a pseudo-class combinator specific to Angular's view encapsulation system. It tells Angular's compiler to disable style encapsulation for a particular CSS rule, allowing that rule to penetrate into child component views. Because it is not defined in any W3C or WHATWG CSS specification, the CSS validator flags it as an unknown pseudo-element or pseudo-class.
This is important to understand for several reasons:
- It's not a standard CSS feature. No browser natively understands
::ng-deep. Angular's build toolchain processes and removes it at compile time, rewriting the selector before it reaches the browser. The validator checks against CSS specifications and rightfully does not recognize it. - It's deprecated within Angular itself. The Angular team has deprecated
::ng-deepand plans to remove it in a future version. Continued use ties your codebase to a feature with no long-term support. - It can cause unintended global style leakage. When combined with
:hostimproperly or used without care,::ng-deepcan bleed styles into components where they weren't intended, making your application harder to maintain.
How to Fix It
There are several approaches depending on your situation:
1. Accept the Validation Warning
If you're working in an Angular project and need ::ng-deep temporarily, you can acknowledge this as a known framework-specific warning. The validator is technically correct — the selector isn't valid CSS — but Angular's compiler handles it before it reaches the browser.
2. Use Global Stylesheets
Move the styles that need to cross component boundaries into a global stylesheet (like styles.css). Global styles are not encapsulated and naturally apply to all components.
3. Set ViewEncapsulation to None
Disable view encapsulation on the component that needs to style its children. This makes all of that component's styles global in scope, removing the need for ::ng-deep.
4. Use CSS Custom Properties (Recommended)
The most standards-compliant approach is to use CSS custom properties (variables) to create a theming API for your components. Custom properties naturally inherit through the DOM tree, crossing shadow DOM and Angular encapsulation boundaries.
Examples
❌ Using ::ng-deep (Triggers the Validation Warning)
:host::ng-deep.child-button{
background-color: blue;
color: white;
}
The validator does not recognize ::ng-deep and reports the error.
✅ Using a Global Stylesheet Instead
In your global styles.css file, target the element with a specific class or selector:
app-parent.child-button{
background-color: blue;
color: white;
}
This avoids ::ng-deep entirely by placing the rule outside of component-scoped styles.
✅ Using CSS Custom Properties
Define customizable properties in the child component's CSS:
/* Child component styles */
.child-button{
background-color:var(--child-button-bg, gray);
color:var(--child-button-color, black);
}
Then set the values from the parent component's CSS:
/* Parent component styles */
:host{
--child-button-bg: blue;
--child-button-color: white;
}
This approach is fully standards-compliant, passes CSS validation, and creates a clean styling API between components. CSS custom properties inherit naturally through the DOM, so they work across component boundaries without breaking encapsulation.
✅ Using ::part() for Web Components
If your child components use shadow DOM (or you're migrating toward web components), the standard ::part() pseudo-element lets you expose specific elements for external styling:
/* Parent styles targeting an exposed part */
child-component::part(button){
background-color: blue;
color: white;
}
The ::part() pseudo-element is a W3C standard and fully recognized by the CSS validator.
CSS pseudo-classes (like :hover, :focus, :nth-child()) select elements based on their state or position, while pseudo-elements (like ::before, ::after, ::placeholder) target specific parts of an element. The CSS specification distinguishes between the two by using a single colon for pseudo-classes and a double colon for pseudo-elements. While browsers still support the legacy single-colon syntax for older pseudo-elements like :before and :after for backward compatibility, the validator expects the modern double-colon form ::before and ::after.
Why This Matters
Standards compliance. The double-colon syntax for pseudo-elements was introduced in CSS3 to clearly distinguish pseudo-elements from pseudo-classes. Using the correct syntax makes your code more readable and future-proof.
Catching real bugs. A misspelled pseudo-class like :foucs or :hovr will silently fail — the browser simply ignores the entire rule. The validator catches these typos before they cause mysterious styling issues in production.
Validator profile limitations. The W3C CSS validator checks your styles against a specific CSS profile. Newer selectors like :has(), :is(), or :where() may not be recognized if the validator is set to an older profile like CSS Level 2.1 or even CSS Level 3. Vendor-prefixed selectors like ::-webkit-input-placeholder or ::-moz-placeholder are never part of any standard profile and will always be flagged.
Common Causes
- Typos —
:hovr,:foucs,::plceholder, etc. - Single colon on pseudo-elements —
:before,:after,:first-line,:first-letterinstead of their double-colon equivalents. - Vendor-prefixed selectors —
::-webkit-input-placeholder,::-moz-selection,:-ms-input-placeholder. - Modern selectors on older profiles —
:has(),:is(),:where(),::marker,:focus-visiblemay not be recognized depending on the validator's CSS level setting.
How to Fix
- Check spelling of all pseudo-classes and pseudo-elements.
- Use double colons for pseudo-elements:
::before,::after,::first-line,::first-letter,::placeholder,::marker,::selection. - Replace vendor-prefixed selectors with their standard equivalents. If you still need the prefix for browser support, place the standard version alongside it and accept that the prefixed line may produce a warning.
- Update the validator profile to a newer CSS level if you're intentionally using modern selectors like
:has()or:focus-visible.
Examples
Incorrect — triggers the warning
<style>
/* Typo in pseudo-class */
a:hovr{
color: red;
}
/* Single colon on pseudo-element */
p:before{
content:"→ ";
}
/* Vendor-prefixed pseudo-element without standard version */
input::-webkit-input-placeholder{
color: gray;
}
</style>
Each of these rules will trigger an "Unknown pseudo-element or pseudo-class" warning. The first is a simple typo, the second uses outdated single-colon syntax, and the third is a non-standard vendor prefix.
Correct — valid CSS
<style>
/* Fixed typo */
a:hover{
color: red;
}
/* Double colon for pseudo-element */
p::before{
content:"→ ";
}
/* Standard pseudo-element */
input::placeholder{
color: gray;
}
</style>
Handling modern selectors
Some modern pseudo-classes like :has() and :focus-visible are well-supported in browsers but may not yet be recognized by the validator. If you need to use them, you can acknowledge the warning or structure your CSS so the modern selector enhances rather than replaces base styles:
<style>
/* Base style that always applies */
.card{
border:1px solid transparent;
}
/* Enhancement using :has() — may warn in the validator */
.card:has(img){
border-color:#ccc;
}
/* :focus-visible for keyboard-only focus rings */
button:focus-visible{
outline:2px solid blue;
}
</style>
These selectors are valid CSS and work in modern browsers. If the validator flags them, consider switching the validator's profile to the latest CSS level, or treat the warnings as informational rather than errors.
The @container at-rule enables container queries, allowing you to apply styles to elements based on the size or inline-size of a parent container rather than the viewport. It was introduced as part of the CSS Containment Module Level 3 specification and has been supported in all major browsers (Chrome, Edge, Firefox, Safari) since early 2023.
The W3C CSS validator uses its own CSS parsing engine, which sometimes lags behind the latest CSS specifications. Because @container is relatively new compared to long-established at-rules like @media or @keyframes, the validator may flag it as unrecognized. This does not mean your CSS is invalid or broken — it simply means the validator hasn't caught up with the spec yet.
Why This Warning Appears
The W3C validator checks your CSS against known grammar rules. When it encounters an at-rule it doesn't have in its internal dictionary, it reports it as unrecognized. Other modern CSS features like @layer and @property have historically triggered the same kind of false positive before being added to the validator's parser.
Since this is a validator limitation and not an actual code issue, there's no required "fix." However, you should still make sure your @container usage is syntactically correct and that you've properly set up containment on the parent element.
How Container Queries Work
For @container to function, a parent element must be designated as a containment context using the container-type property (or the container shorthand). Without this, the browser won't know which ancestor to query against.
Examples
Correct usage of @container
The parent element needs container-type set to inline-size or size so its descendants can query against it:
<divclass="card-wrapper">
<divclass="card">
<h2>Title</h2>
<p>Some content here.</p>
</div>
</div>
.card-wrapper{
container-type: inline-size;
container-name: card-container;
}
@container card-container (min-width:400px){
.card{
display: flex;
gap:1rem;
}
}
In this example, .card-wrapper is established as a containment context. When its inline size is at least 400px, the .card inside switches to a flex layout. The validator may flag the @container block, but this CSS is perfectly valid and works in all modern browsers.
Using @container without a named container
You can omit the container name, and the query will match the nearest ancestor with a container-type set:
.sidebar{
container-type: inline-size;
}
@container(max-width:300px){
.sidebar-nav{
flex-direction: column;
}
}
Common mistake: forgetting container-type
If you use @container without declaring a containment context on a parent, the query will never match and your styles won't apply. This won't cause a validator error, but it's a logical bug:
/* Missing container-type — the @container query has nothing to query against */
.wrapper{
max-width:600px;
}
@container(min-width:400px){
.content{
font-size:1.25rem;
}
}
The fix is to add container-type to the intended parent:
.wrapper{
max-width:600px;
container-type: inline-size;
}
@container(min-width:400px){
.content{
font-size:1.25rem;
}
}
What You Should Do
- Verify your syntax — make sure you're using
container-typeon a parent element and that your@containerquery follows the correct grammar. - Ignore the validator warning — this is a known limitation of the W3C CSS validator. Your CSS is valid per the specification.
- Check browser support —
@containeris supported in Chrome 105+, Edge 105+, Firefox 110+, and Safari 16+. If you need to support older browsers, consider using@containeras a progressive enhancement alongside a fallback layout.
The @media screen rule without a condition after the media type is invalid CSS syntax and will be flagged by the W3C validator.
A @media rule requires either a complete media query or a media type combined with a media feature expression. Writing @media screen alone followed by a block is actually valid CSS, so this error typically appears when the syntax inside the rule is malformed, the rule is missing curly braces, or extra characters appear between screen and the opening brace.
Common causes include:
- A missing opening or closing curly brace
{}around the media block. - Stray characters or typos between the media type and the brace.
- Placing
@mediarules inside astyleattribute (inline styles do not support at-rules). - The CSS appears inside an HTML context where the validator cannot parse it correctly, such as a malformed
<style>element.
If the intent is to target screens of a specific size, a media feature expression is required, like @media screen and (min-width: 768px). If the intent is to target all screen devices with no further conditions, @media screen is valid CSS on its own, and the real problem is likely a syntax error nearby.
Example with the issue
<style>
@media screen
.container{
width:80%;
}
</style>
The opening curly brace for the @media block is missing, so the validator cannot recognize the rule.
Fixed example
<style>
@media screen {
.container{
width:80%;
}
}
</style>
If the goal is to restrict styles to a specific viewport width, add a media feature:
<style>
@media screen and(min-width:768px){
.container{
width:80%;
}
}
</style>
Both examples use properly matched curly braces and valid @media syntax, which resolves the validator error.
The @tailwind directive is used in Tailwind CSS source files to inject Tailwind's generated styles into your stylesheet. Common usages include @tailwind base;, @tailwind components;, and @tailwind utilities;. These directives act as placeholders that Tailwind's build tool (such as the Tailwind CLI or PostCSS plugin) replaces with actual CSS rules during compilation.
The W3C CSS Validator checks stylesheets against official CSS specifications maintained by the W3C. Since @tailwind is not defined in any CSS specification — it's a framework-specific extension — the validator correctly flags it as unrecognized. This doesn't mean your CSS is broken or will cause problems in browsers; it simply means the validator doesn't know what @tailwind is.
This distinction matters because the @tailwind directives should never appear in production CSS served to browsers. If you're seeing this validation error on a live website, it could indicate one of two things: either you're linking directly to your uncompiled Tailwind source file (which is a problem), or the validator is checking your source CSS rather than the compiled output.
How to Fix It
Ensure you're serving compiled CSS
The most important step is to make sure your build pipeline is correctly processing your Tailwind source files. The compiled output should contain only standard CSS — no @tailwind directives. Verify that your <link> tags point to the compiled CSS file, not the source file.
Use the Tailwind CDN or CLI correctly
If you're using the Tailwind CLI, run the build command to generate a compiled stylesheet and reference that file in your HTML. The compiled file will contain only valid CSS.
Consider suppressing the warning
If the validator is checking your source CSS (for example, inline <style> blocks that get processed client-side), and you're confident the directives are being handled correctly, you can safely suppress or ignore this specific warning in your validation reports.
Examples
Source CSS that triggers the warning
This is a typical Tailwind CSS source file that the validator will flag:
@tailwind base;
@tailwind components;
@tailwind utilities;
.custom-button{
padding:0.5rem1rem;
border-radius:0.25rem;
}
Each @tailwind line will produce an "Unrecognized at-rule" warning from the W3C Validator.
Correct approach: serve compiled CSS
After running the Tailwind build process, the output file contains only standard CSS:
*,::before,::after{
box-sizing: border-box;
}
.custom-button{
padding:0.5rem1rem;
border-radius:0.25rem;
}
.flex{
display: flex;
}
.text-center{
text-align: center;
}
Reference this compiled file in your HTML:
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="utf-8">
<title>My Page</title>
<linkrel="stylesheet"href="css/output.css">
</head>
<body>
<pclass="text-center">Hello, world!</p>
</body>
</html>
Avoid linking to uncompiled source files
This is incorrect — it links directly to the source file containing @tailwind directives:
<!-- Don't do this -->
<linkrel="stylesheet"href="css/input.css">
Instead, always link to the build output:
<!-- Do this -->
<linkrel="stylesheet"href="css/output.css">
By ensuring your production site serves only the compiled CSS output, you eliminate the @tailwind at-rule warnings entirely and deliver valid, standards-compliant stylesheets to your users.
The CSS width property sets an element's width and accepts a single value. The W3C validator reports this error when it encounters something it cannot parse as a valid width declaration. Common causes include:
- Missing units: Writing
width: 300instead ofwidth: 300px. CSS requires explicit units for non-zero lengths. - Multiple values: Writing
width: 100px 200pxas ifwidthaccepted shorthand-style multiple values (it doesn't). - Typos or invalid keywords: Writing
width: auotinstead ofwidth: auto, or using a made-up keyword. - Invalid functions or syntax: Using incorrect function syntax like
width: calc(100% - 20px)with missing spaces around operators, or using browser-prefixed values without a standard fallback. - Unsupported values: Using newer CSS values like
fit-contentormax-contentin a context where the validator's CSS level doesn't recognize them.
This matters because invalid CSS can cause browsers to silently discard the entire declaration, meaning your intended layout won't be applied. Different browsers may handle invalid values differently, leading to inconsistent rendering. Keeping your CSS valid ensures predictable, cross-browser behavior.
Valid values for width
The width property accepts exactly one of the following:
- Length values: A number with a unit, such as
300px,25em,10rem,5vw. - Percentage values: A percentage relative to the containing block, such as
75%. - Keyword values:
auto,max-content,min-content,fit-content. - Function values:
fit-content(20em),calc(100% - 40px),min(300px, 100%),max(200px, 50%),clamp(200px, 50%, 600px). - Global values:
inherit,initial,revert,revert-layer,unset.
Note that 0 is the only numeric value that does not require a unit.
Examples
Incorrect: missing unit
<style>
.box{
width:300;
}
</style>
<divclass="box">Content</div>
A bare number (other than 0) is not valid. The browser won't know if you mean pixels, ems, or something else.
Correct: unit provided
<style>
.box{
width:300px;
}
</style>
<divclass="box">Content</div>
Incorrect: too many values
<style>
.sidebar{
width:200px400px;
}
</style>
<asideclass="sidebar">Sidebar</aside>
Unlike properties such as margin or padding, width only accepts a single value.
Correct: single value
<style>
.sidebar{
width:200px;
}
</style>
<asideclass="sidebar">Sidebar</aside>
Incorrect: typo in keyword
<style>
.container{
width: auot;
}
</style>
<divclass="container">Content</div>
Correct: proper keyword
<style>
.container{
width: auto;
}
</style>
<divclass="container">Content</div>
Incorrect: malformed calc() expression
<style>
.panel{
width:calc(100%-40px);
}
</style>
<divclass="panel">Content</div>
The calc() function requires spaces around + and - operators.
Correct: properly spaced calc() expression
<style>
.panel{
width:calc(100%-40px);
}
</style>
<divclass="panel">Content</div>
Incorrect: accidental semicolon or extra text
<style>
.card{
width:50% important;
}
</style>
<divclass="card">Content</div>
If you intended to use !important, the ! is required.
Correct: proper !important syntax
<style>
.card{
width:50%!important;
}
</style>
<divclass="card">Content</div>
This is an internal error from the W3C validator's CSS checking engine (the Jigsaw CSS validator). The message Cannot invoke "org.w3c.css.values.CssValue.getType()" because "Y" is null is a Java NullPointerException surfacing from the validator's source code. In practical terms, it means the validator tried to determine the type of a CSS value, but that value didn't exist or couldn't be computed.
There are several common causes for this error:
- Malformed or incomplete CSS values — A property is missing part of its value, such as a shorthand with too few components, or a function with missing arguments.
- Unsupported CSS features — Newer CSS features or non-standard syntax that the validator's CSS engine doesn't fully support can trigger internal failures rather than clean error messages.
- Invalid value combinations — Using values together in a way that doesn't match any known CSS grammar rule can cause the parser to fail unexpectedly.
- Syntax errors in custom properties or functions — Mistakes inside
calc(),var(), or other CSS functions can sometimes cause this kind of crash in the validator.
While this error technically originates from the validator itself (and could be considered a validator bug), it almost always points to CSS that is non-standard, malformed, or pushing the boundaries of what the validator can parse. Fixing the underlying CSS issue resolves the error.
How to Fix It
- Locate the CSS property referenced in the error — The
"X"in the error message identifies the CSS property or value that caused the failure. - Check for syntax errors — Look for missing values, unclosed parentheses, stray commas, or incomplete shorthand declarations.
- Simplify complex expressions — If you're using
calc(), nested functions, or complex shorthand values, try breaking them into simpler, longhand declarations. - Check for unsupported features — Some modern CSS (e.g., certain uses of
color-mix(), newer color syntaxes, or container query units) may not yet be supported by the validator. Consider whether validation of that specific rule is critical. - Validate CSS separately — Paste your CSS into the W3C CSS Validator directly to isolate the problematic rule.
Examples
Malformed shorthand value
A missing value in a shorthand property can trigger this internal error:
<divstyle="border:1px solid;">Content</div>
The border shorthand here has a trailing space after solid with no color specified. While browsers handle this gracefully by using a default, the validator may fail to process the incomplete value. Fix it by providing all intended values explicitly:
<divstyle="border:1px solid black;">Content</div>
Incomplete function syntax
Missing arguments inside CSS functions are another common trigger:
<style>
.box{
width:calc(100%-);
background-color:rgb(255,128);
}
</style>
The calc() expression is missing its second operand, and rgb() is missing its third argument. Fix both by providing complete values:
<style>
.box{
width:calc(100%-20px);
background-color:rgb(255,128,0);
}
</style>
Complex expressions the validator cannot parse
Sometimes valid, modern CSS triggers this error because the validator's engine doesn't fully support it:
<style>
.card{
background:color-mix(in srgb,#3498db70%, transparent);
}
</style>
If this triggers the internal error, you can provide a fallback or simplify:
<style>
.card{
background:rgba(52,152,219,0.7);
}
</style>
Accidental double values
A typo that results in two values where one is expected can also cause this:
<style>
.text{
font-size:16px14px;
}
</style>
Fix by providing only the single expected value:
<style>
.text{
font-size:16px;
}
</style>
If you believe your CSS is correct and the validator is producing this error incorrectly, it may be a genuine bug in the validator. You can report it at the W3C CSS Validator's GitHub repository. In the meantime, check that your CSS works correctly across target browsers and consider adding a /* validated */ comment near the line so you can track intentional exceptions.
CSS uses semicolons as delimiters between declarations. When you forget one, the parser tries to interpret the next property name as part of the previous declaration's value. For example, if you write z-index: auto content: "", the parser reads auto content as if it were the value of z-index, which is invalid. It then encounters the colon after what it expected to be a value, resulting in a parsing error that can cause one or more of your declarations to be silently ignored.
This is a problem for several reasons:
- Broken styles: The browser will typically discard the malformed declaration and potentially subsequent ones, leading to unexpected visual results that can be difficult to debug.
- Standards compliance: The CSS specification requires semicolons between declarations. While the last declaration in a block technically doesn't need a trailing semicolon, omitting it is a common source of bugs when new declarations are added later.
- Maintainability: Always including semicolons — even on the last declaration — is a widely recommended best practice. It prevents this exact class of errors when code is edited or rearranged in the future.
To fix this issue, locate the line referenced in the error message and check the declaration immediately before it. Add the missing semicolon at the end of that declaration.
Examples
❌ Missing semicolon between declarations
The semicolon is missing after z-index: auto, so the parser cannot recognize content as a new property:
<style>
.overlay{
z-index: auto
content: "";
display: block;
}
</style>
✅ Fixed with semicolon added
Adding the semicolon after auto properly terminates the z-index declaration:
<style>
.overlay{
z-index: auto;
content:"";
display: block;
}
</style>
❌ Missing semicolon with shorthand properties
Shorthand values with multiple parts can make it harder to spot the missing semicolon:
<style>
.card{
margin:10px20px10px20px
padding: 1em;
border:1px solid #ccc;
}
</style>
✅ Fixed shorthand example
<style>
.card{
margin:10px20px10px20px;
padding:1em;
border:1px solid #ccc;
}
</style>
❌ Missing semicolon on the last declaration causes issues when editing
While technically valid, omitting the trailing semicolon on the last declaration becomes a bug the moment a new line is added:
<style>
.button{
color: white;
background: blue
border-radius: 4px;
}
</style>
Here, background: blue was originally the last declaration (without a semicolon). When border-radius was added afterward, the missing semicolon was not noticed.
✅ Best practice: always include a trailing semicolon
<style>
.button{
color: white;
background: blue;
border-radius:4px;
}
</style>
By consistently ending every declaration with a semicolon — including the last one in each rule block — you avoid this error entirely and make your stylesheets easier to maintain.
CSS math functions like calc(), min(), max(), and clamp() follow strict rules about how operands and operators interact. The error "one operand must be a number" most commonly fires in two scenarios: either an operand is missing entirely (e.g., calc(100% - )), or both operands in a multiplication or division carry units (e.g., calc(10px * 5px)). The CSS Values and Units specification requires that for * (multiplication), at least one side must be a unitless <number>. For / (division), the right-hand side must always be a unitless <number>. You cannot multiply two lengths together or divide a length by another length within calc().
This matters for several reasons. Browsers will discard the entire property declaration if the calc() expression is invalid, which can cause layout breakage or fallback to unexpected default values. The W3C validator catches these errors in inline style attributes and embedded <style> blocks, helping you identify expressions that will silently fail in production. Fixing these issues ensures predictable rendering across all browsers.
How the rules work
- Addition and subtraction (
+,-): Both operands must have compatible types (e.g., both lengths, or both percentages, or a mix of length and percentage). Both must be present. - Multiplication (
*): At least one operand must be a plain<number>(unitless). You can writecalc(10px * 3)orcalc(3 * 10px), but notcalc(10px * 5px). - Division (
/): The right-hand operand must be a plain<number>(unitless and non-zero). You can writecalc(100px / 2), but notcalc(100px / 2px).
Examples
Missing operand
A common mistake is leaving out a value on one side of an operator:
<!-- ❌ Wrong: missing operand after the minus sign -->
<divstyle="width:calc(100%-);"></div>
<!-- ✅ Fixed: both operands are present -->
<divstyle="width:calc(100%-50px);"></div>
Multiplying two values with units
You cannot multiply two unit-bearing values together, because the result would be a meaningless type like "px²":
<!-- ❌ Wrong: both operands have units -->
<divstyle="width:calc(10px*5px);"></div>
<!-- ✅ Fixed: one operand is a unitless number -->
<divstyle="width:calc(10px*5);"></div>
Dividing by a value with units
The divisor in a / operation must be a unitless number:
<!-- ❌ Wrong: dividing by a value with units -->
<divstyle="height:calc(500px/2em);"></div>
<!-- ✅ Fixed: divisor is a unitless number -->
<divstyle="height:calc(500px/2);"></div>
Nested calc() with a missing value
Errors can hide inside nested expressions:
<!-- ❌ Wrong: inner calc has an incomplete expression -->
<pstyle="margin-top:calc(2rem+calc(100%*));"></p>
<!-- ✅ Fixed: all operands are present and valid -->
<pstyle="margin-top:calc(2rem+calc(100%*0.5));"></p>
Using variables or keywords where a number is expected
Sometimes a typo or misunderstanding leads to a non-numeric token where a number is required:
<!-- ❌ Wrong: "auto" is not a valid operand in calc() -->
<divstyle="width:calc(auto *2);"></div>
<!-- ✅ Fixed: use a numeric value or percentage -->
<divstyle="width:calc(100%*2);"></div>
To resolve this error, review every calc(), min(), max(), and clamp() expression in your inline styles and stylesheets. Confirm that all operators have valid operands on both sides, that * always has at least one unitless number, and that / always has a unitless number on the right. If you're building expressions dynamically (e.g., via JavaScript or a templating engine), double-check that variables are being interpolated correctly and not producing empty or invalid values.
When the W3C HTML Validator checks your document, it also validates any inline styles (in style attributes) and embedded stylesheets (in <style> elements). A CSS parse error occurs when the parser encounters something it cannot interpret according to CSS specifications. The "X" in the error message refers to the specific property, value, or token that triggered the failure.
Understanding CSS Parse Errors
CSS parse errors can stem from many different causes:
- Typos in property names or values — e.g.,
colrinstead ofcolor, or10xpinstead of10px. - Missing or extra punctuation — a forgotten semicolon, an extra colon, unmatched braces or parentheses.
- Invalid values for a property — using a value that doesn't belong to that property's grammar.
- Vendor-prefixed or non-standard syntax — properties like
-webkit-appearanceor-moz-osx-font-smoothingare not part of the CSS standard and will trigger parse errors in the validator. - Modern CSS features not yet recognized — some newer CSS syntax may not be supported by the validator's parser yet.
- Stray characters or encoding issues — invisible characters, smart quotes, or copy-paste artifacts from word processors.
While browsers are generally forgiving and will skip CSS they don't understand, parse errors can indicate real bugs that cause styles to silently fail. Fixing them ensures your CSS is standards-compliant and behaves predictably across all browsers.
Common Causes and Fixes
Typos and syntax mistakes
The most frequent cause is a simple typo or a missing character. Always double-check the exact line the validator points to.
Missing semicolons
A forgotten semicolon between declarations can cause the parser to misinterpret subsequent properties.
Invalid or malformed values
Using values that don't match the property's expected syntax — such as omitting units, using incorrect function syntax, or providing the wrong number of arguments — will trigger parse errors.
Vendor prefixes
The W3C validator checks against the CSS specification. Vendor-prefixed properties and values are non-standard and will produce parse errors. While you may still need them in production, be aware that these will always flag in validation.
Examples
❌ Missing semicolon between declarations
<pstyle="color: red background-color: blue;">Hello</p>
The missing semicolon after red causes the parser to try to interpret red background-color: blue as a single value, resulting in a parse error.
✅ Fixed: semicolons separating declarations
<pstyle="color: red;background-color: blue;">Hello</p>
❌ Typo in property name
<style>
.box{
widht:100px;
hieght:200px;
}
</style>
✅ Fixed: correct property names
<style>
.box{
width:100px;
height:200px;
}
</style>
❌ Missing unit on a value
<style>
.container{
margin:10;
padding:20px;
}
</style>
Numeric values (other than 0) require a unit. The value 10 without a unit like px, em, or rem is invalid.
✅ Fixed: unit included
<style>
.container{
margin:10px;
padding:20px;
}
</style>
❌ Extra or misplaced characters
<style>
.title{
font-size:: 16px;
color:#3333;
}
</style>
The double colon after font-size and the 4-digit hex color #3333 (which is valid in CSS Color Level 4 but may not be recognized by all validator parsers) can trigger errors.
✅ Fixed: correct syntax
<style>
.title{
font-size:16px;
color:#333333;
}
</style>
❌ Unmatched parentheses in a function
<style>
.overlay{
background: rgba(0,0,0,0.5;
}
</style>
✅ Fixed: closing parenthesis added
<style>
.overlay{
background:rgba(0,0,0,0.5);
}
</style>
Tips for Debugging Parse Errors
- Read the error message carefully. The validator usually points to the specific token or line that caused the failure.
- Validate CSS separately. Use the W3C CSS Validation Service for more detailed CSS-specific error messages.
- Check for invisible characters. If you copied CSS from a word processor, PDF, or website, hidden characters like zero-width spaces or smart quotes (
"instead of") may be present. Retype the line manually if in doubt. - Simplify and isolate. If you can't find the error, remove declarations one at a time until the error disappears, then inspect the last removed declaration closely.
The validator flags any declaration where the property token doesn’t match a known CSS property in its ruleset. Common causes include typos, wrong hyphenation, using values where property names should go, properties from older drafts that were renamed, or relying solely on vendor-prefixed/experimental properties without a standard equivalent. It can also show up when copy-pasting snippets that include custom, nonstandard properties.
Why this matters:
- Browser compatibility: Unknown properties are ignored, causing styles to silently fail.
- Maintainability: Typos and nonstandard syntax make CSS harder to debug.
- Standards compliance: Clean, validated CSS reduces cross-browser surprises and eases future maintenance.
How to fix it:
- Check spelling and hyphenation exactly (e.g.,
text-decoration-skip-ink, nottext-decoration-skipink). - Verify the property exists on MDN or in the CSS specifications; if it’s not documented, it’s likely invalid.
- Replace deprecated or draft names with current standardized ones.
- If using experimental features, include a standard fallback and keep vendor-prefixed versions alongside the unprefixed property when supported.
- Remove framework- or tool-specific tokens that aren’t valid CSS at runtime.
- Don’t invent properties. If you need custom data for JS, use
data-*attributes in HTML, not fake CSS properties.
Examples
Example that triggers the error (typo) and the corrected version
Invalid:
<pstyle="colr: red;">Hello</p>
Valid:
<pstyle="color: red;">Hello</p>
Example using a deprecated/draft name replaced with the current property
Invalid (older draft name):
<divstyle="gap:1rem;grid-row-gap:8px;"></div>
Valid (current, standardized property):
<divstyle="row-gap:8px;gap:1rem;"></div>
Example with vendor-prefixed property plus standard fallback
Invalid (only vendor-prefixed, missing standard property):
<divstyle="-webkit-user-select: none;"></div>
Valid (fallback plus prefix):
<divstyle="user-select: none;-webkit-user-select: none;"></div>
Example removing a nonstandard custom property name misuse
Invalid (attempting to invent a property):
<divstyle="button-style: primary;"></div>
Valid (use classes and real CSS properties):
<style>
.btn--primary{
background-color:#0b5fff;
color:#fff;
}
</style>
<buttonclass="btn--primary">Submit</button>
Example with custom properties (variables) used correctly
Valid use of CSS custom properties (won’t trigger the error because the property is standard and custom properties start with --):
<style>
:root{
--brand-color:#0b5fff;
}
.tag{
color:var(--brand-color);
}
</style>
<spanclass="tag">Tag</span>
Full document with corrected properties
<!doctype html>
<htmllang="en">
<head>
<metacharset="utf-8">
<title>CSS Property Validation Fixes</title>
<metaname="viewport"content="width=device-width, initial-scale=1">
<style>
.card{
display: grid;
gap:1rem;
row-gap:0.5rem;
user-select: none;
-webkit-user-select: none;
color:#222;
}
</style>
</head>
<body>
<divclass="card">Valid CSS properties in use</div>
</body>
</html>
Quick checklist:
- Confirm the property on MDN. If not found, it’s probably invalid.
- Fix spelling/casing; CSS properties are lowercase with hyphens.
- Prefer standardized names; keep prefixes only as supplements.
- Use CSS custom properties starting with
--if you need variables. - Remove tool-specific placeholders before validation.
Every CSS property has a defined value syntax that specifies exactly which values it accepts and how many. When the validator encounters a declaration that doesn't match this syntax, it flags the error. This can happen for several distinct reasons:
- Too many values: A property receives more values than its syntax allows. For example,
marginaccepts one to four values, so a fifth value is invalid. Thecolorproperty accepts only a single color value, so writing two colors is an error. - Unrecognized values: A keyword is misspelled (e.g.,
blockyinstead ofblock) or simply doesn't exist for that property (e.g.,color: bold). - Newer or non-standard values: A value that belongs to a draft specification, a vendor-prefixed feature, or a browser-specific extension may not be recognized by the validator.
- Missing separators or syntax errors: A missing comma in a multi-value function like
rgb()or a missing slash in shorthand likefontcan cause the parser to misinterpret the values.
This matters because browsers handle invalid CSS unpredictably — they typically discard the entire declaration, which means your intended styles silently disappear. Fixing these errors ensures your styles are applied consistently across browsers and makes your stylesheets easier to maintain and debug.
How to Fix
- Identify the property and value reported in the error message.
- Check spelling of every keyword. Common mistakes include
inheret(should beinherit),trasparent(should betransparent), andcentre(should becenter). - Count the values and compare against the property's specification. Consult MDN Web Docs for the accepted value syntax.
- Verify function syntax — ensure commas, slashes, and parentheses are correct in functions like
rgb(),calc(), andclamp(). - Check for unsupported modern syntax — if you're using newer CSS features, the validator may not recognize them yet. In that case, verify the syntax is correct per the spec and consider the warning informational.
Examples
Too many values for a property
The color property only accepts a single color value, and margin accepts at most four values:
<!-- ❌ Invalid: too many values -->
<pstyle="color: red blue;">Hello</p>
<pstyle="margin:10px20px5px0px15px;">Hello</p>
<!-- ✅ Valid: correct number of values -->
<pstyle="color: red;">Hello</p>
<pstyle="margin:10px20px5px0px;">Hello</p>
Unrecognized keyword value
A typo or non-existent keyword triggers the error:
<!-- ❌ Invalid: "blocky" is not a valid display value -->
<divstyle="display: blocky;">Content</div>
<!-- ✅ Valid: correct keyword -->
<divstyle="display: block;">Content</div>
Misspelled value in a <style> block
<!-- ❌ Invalid -->
<style>
.box{
background-color: trasparent;
text-align: centre;
}
</style>
<!-- ✅ Valid -->
<style>
.box{
background-color: transparent;
text-align: center;
}
</style>
Incorrect function syntax
Missing commas or extra arguments inside CSS functions can also trigger this error:
<!-- ❌ Invalid: missing commas in rgb() -->
<pstyle="color:rgb(255000.5);">Hello</p>
<!-- ✅ Valid: use the correct modern syntax with a slash for alpha -->
<pstyle="color:rgb(25500/0.5);">Hello</p>
Shorthand property confusion
Shorthand properties like font and background have specific value order requirements. Providing values in the wrong order or mixing incompatible values causes errors:
<!-- ❌ Invalid: incorrect font shorthand -->
<style>
p{
font: bold Arial 16px;
}
</style>
<!-- ✅ Valid: size must come before family, weight before size -->
<style>
p{
font: bold 16px Arial;
}
</style>
When in doubt, break shorthand properties into their individual longhand properties (font-weight, font-size, font-family) to isolate which value the validator is rejecting.
In CSS, a "dimension" is a number immediately followed by a unit identifier — for example, 16px, 2em, or 100vh. When the validator encounters a dimension token with a unit it doesn't recognize, it flags it as an unknown dimension. The "X" in the error message is replaced with the actual unrecognized value, such as 10quux or 5pixels.
This issue commonly arises from:
- Typos in unit names — writing
10pxlinstead of10px, or2emsinstead of2em. - Made-up or non-standard units — using units that don't exist in any CSS specification.
- Missing spaces or operators — accidentally concatenating a number with a keyword, like
100vhmaxinstead of usingmax(100vh, ...). - Using units in the wrong context — some newer or less common units may not yet be recognized by the validator, though all widely supported CSS units should be accepted.
This matters because browsers may silently ignore or misinterpret properties with invalid dimension values, leading to broken layouts. Using valid units ensures consistent rendering across browsers and compliance with CSS standards.
How to Fix
- Check the CSS value flagged in the error message.
- Verify the unit is a valid CSS unit (e.g.,
px,em,rem,%,vw,vh,vmin,vmax,ch,ex,cm,mm,in,pt,pc,s,ms,deg,rad,turn,fr). - Fix any typos, remove extra characters, or replace non-standard units with valid ones.
- If the value is meant to be unitless (like
line-height: 1.5), remove the erroneous unit entirely.
Examples
Incorrect: Misspelled unit
<divstyle="margin:10pxl;">Hello</div>
The unit pxl is not a valid CSS unit. The validator reports an unknown dimension for 10pxl.
Correct: Valid unit
<divstyle="margin:10px;">Hello</div>
Incorrect: Made-up unit
<style>
.box{
width:50pixels;
height:200hv;
}
</style>
Neither pixels nor hv are valid CSS units.
Correct: Standard CSS units
<style>
.box{
width:50px;
height:200vh;
}
</style>
Incorrect: Missing space causes concatenation
<style>
.container{
font-size:1remx;
}
</style>
The extra x turns rem into the unknown dimension remx.
Correct: Proper unit
<style>
.container{
font-size:1rem;
}
</style>
Incorrect: Unit where none is needed
<style>
p{
line-height:1.5em2;
}
</style>
Correct: Unitless value or valid unit
<style>
p{
line-height:1.5;
}
</style>
If you're confident the unit is valid and part of a newer CSS specification (such as container query units like cqi or cqb), the validator may not yet support it. In that case, the warning can be noted but may not indicate an actual problem in modern browsers. However, always double-check for typos first — the most common cause is simply a misspelled unit.
In CSS, most numeric values represent a length, time, angle, or other dimension, and the unit tells the browser how to interpret the number. Writing padding: 20 is ambiguous — does it mean 20 pixels, 20 ems, or 20 percent? Without a unit, the browser has no way to determine the author's intent, so it treats the value as invalid and discards the entire declaration. This can lead to broken layouts, missing spacing, or other visual problems that are difficult to debug.
The only exception to this rule is 0. Zero pixels is the same as zero ems, zero rems, or zero percent — it's always nothing regardless of the unit. Because of this, the CSS specification allows 0 to be written without a unit. In fact, omitting the unit on zero values is considered a best practice for cleaner, more concise CSS.
This validation error commonly appears in inline style attributes, which is where the W3C HTML Validator encounters it. However, the same rule applies to CSS written in <style> elements and external stylesheets.
Common causes of this error include:
- Accidentally forgetting to type the unit after a number.
- Copy-pasting values from design tools that don't include units.
- Confusing CSS with JavaScript's
element.style.width = "50"pattern (where some APIs accept unitless numbers). - Assuming that
pxis the default unit (it is not — there is no default unit in CSS).
Examples
Incorrect — missing units on numeric values
<divstyle="margin:10;padding:20;width:300;">
Content here
</div>
The validator will report errors for 10, 20, and 300 because none of them have units.
Correct — units specified on all non-zero values
<divstyle="margin:10px;padding:20px;width:300px;">
Content here
</div>
Correct — zero without a unit
<divstyle="margin:0;padding:0;border:0;">
No units needed for zero
</div>
Correct — mixing zero and non-zero values
<divstyle="margin:010px020px;">
Top and bottom margins are zero, sides have units
</div>
Correct — using other unit types
<pstyle="font-size:1.2em;line-height:1.5em;margin-bottom:2rem;">
Text with relative units
</p>
Note that line-height is a special case in CSS — it actually accepts a unitless number (like 1.5) as a valid value, where the number acts as a multiplier of the element's font size. This is not the same as a missing unit; it's a deliberately unitless ratio defined in the specification. Most other properties do not have this behavior.
In earlier versions of HTML, the align attribute was used directly on <td> (and other table elements like <tr> and <th>) to control horizontal alignment of cell content. Values like left, center, right, and justify were common. HTML5 made this attribute obsolete in favor of CSS, which provides a cleaner separation of content and presentation.
While most browsers still honor the align attribute for backward compatibility, relying on it is discouraged. It violates modern web standards, mixes presentational concerns into your markup, and makes styling harder to maintain. CSS offers far more flexibility — you can target cells by class, use responsive styles, or change alignment through media queries without touching your HTML.
How to fix it
- Remove the
alignattribute from the<td>element. - Apply the CSS
text-alignproperty instead, either via an inlinestyleattribute, a<style>block, or an external stylesheet.
The CSS text-align property accepts the same values the old attribute did: left, center, right, and justify.
For vertical alignment, the obsolete valign attribute should similarly be replaced with the CSS vertical-align property.
Examples
❌ Obsolete: using the align attribute
<table>
<tr>
<tdalign="center">Centered content</td>
<tdalign="right">Right-aligned content</td>
</tr>
</table>
✅ Fixed: using inline CSS
<table>
<tr>
<tdstyle="text-align: center;">Centered content</td>
<tdstyle="text-align: right;">Right-aligned content</td>
</tr>
</table>
✅ Fixed: using a stylesheet (recommended)
Using classes keeps your HTML clean and makes it easy to update styles across your entire site.
<style>
.text-center{
text-align: center;
}
.text-right{
text-align: right;
}
</style>
<table>
<tr>
<tdclass="text-center">Centered content</td>
<tdclass="text-right">Right-aligned content</td>
</tr>
</table>
✅ Fixed: applying alignment to an entire column
If every cell in a column needs the same alignment, you can target cells by position instead of adding a class to each one.
<style>
td:nth-child(2){
text-align: right;
}
</style>
<table>
<tr>
<td>Item</td>
<td>$9.99</td>
</tr>
<tr>
<td>Another item</td>
<td>$14.50</td>
</tr>
</table>
This same approach applies to <th> elements and the <tr> element, which also had an obsolete align attribute in older HTML. In all cases, replace the attribute with the CSS text-align property.
The <big> element was a purely presentational HTML element that increased the text size by one level (similar to moving from small to medium, or medium to large). HTML5 removed it from the specification because it violates the principle of separating content structure from visual presentation. HTML should describe the meaning of content, while CSS should handle how it looks.
Using obsolete elements causes several problems. First, W3C validation will fail, which can impact code quality standards and SEO audits. Second, while current browsers still support <big> for backward compatibility, there's no guarantee future browsers will continue to do so. Third, the <big> element carries no semantic meaning — it doesn't tell assistive technologies why the text is larger, only that it should be displayed differently. CSS gives you more precise control over font sizing while keeping your HTML clean and standards-compliant.
To fix this issue, replace every <big> element with a <span> (or another semantically appropriate element) and apply CSS to control the font size. You can use inline styles, a <style> block, or an external stylesheet.
If the larger text has a specific meaning — such as emphasizing importance — consider using a semantic element like <strong> or <em> instead, and style it with CSS as needed.
Examples
❌ Obsolete: using the <big> element
<p>This is <big>important text</big> in a paragraph.</p>
✅ Fixed: using a <span> with inline CSS
This is a direct replacement that mimics the original behavior of <big>, which rendered text at font-size: larger:
<p>This is <spanstyle="font-size: larger;">important text</span> in a paragraph.</p>
✅ Fixed: using a CSS class
For better maintainability, use a class instead of inline styles:
<style>
.text-big{
font-size: larger;
}
</style>
<p>This is <spanclass="text-big">important text</span> in a paragraph.</p>
✅ Fixed: using a semantic element with CSS
If the text is larger because it's important or emphasized, use a semantic element and style it:
<style>
.highlight{
font-size:1.25em;
}
</style>
<p>This is <strongclass="highlight">important text</strong> in a paragraph.</p>
Choosing a font-size value
The <big> element historically corresponded to font-size: larger, but with CSS you have full flexibility:
font-size: larger— relative increase, closest to original<big>behaviorfont-size: 1.2em— scales to 120% of the parent's font sizefont-size: 1.25rem— scales relative to the root font sizefont-size: 20px— absolute pixel value (less flexible, generally avoid)
Using relative units like em, rem, or the larger keyword is preferred because they scale well across different screen sizes and respect user font-size preferences.
In earlier versions of HTML, the border attribute on <img> was commonly used to control the border width in pixels. Its most frequent use was border="0" to suppress the default blue border browsers would render around images wrapped in <a> links. While this worked, it mixed presentation with markup — something HTML5 discourages in favor of a clean separation between structure (HTML) and styling (CSS).
The W3C HTML Validator flags this attribute as obsolete because it was removed from the HTML5 specification. Modern browsers still understand it for backward compatibility, but relying on deprecated features is bad practice. It can lead to inconsistencies across browsers, makes your code harder to maintain, and signals to validators and other developers that the markup is outdated.
The recommended approach is to handle image borders entirely in CSS. If you previously used border="0" to remove borders from linked images, most modern CSS resets and normalize stylesheets already handle this. If you're not using a reset, a single CSS rule takes care of it globally — no need to repeat the attribute on every <img> tag.
How to fix it
- Remove the
borderattribute from all<img>elements. - Add a CSS rule to achieve the same effect. For removing borders, use
img { border: 0; }in your stylesheet. For adding a visible border, use properties likeborder: 2px solid #333;.
Examples
❌ Obsolete border attribute
<ahref="/products">
<imgsrc="product.jpg"alt="Our product"border="0">
</a>
This triggers the validator warning because border is no longer a valid attribute on <img>.
✅ Fixed with CSS (external/internal stylesheet)
<style>
img{
border:0;
}
</style>
<ahref="/products">
<imgsrc="product.jpg"alt="Our product">
</a>
A single rule in your stylesheet removes borders from all images, which is cleaner and easier to maintain than repeating the attribute on every element.
✅ Fixed with inline CSS (if needed)
<ahref="/products">
<imgsrc="product.jpg"alt="Our product"style="border:0;">
</a>
Inline styles work but aren't ideal for large-scale fixes. Prefer a stylesheet rule when possible.
✅ Adding a decorative border with CSS
If your intent was to add a visible border (e.g., border="2"), replace it with a more flexible CSS equivalent:
<style>
.bordered{
border:2px solid #333;
}
</style>
<imgsrc="photo.jpg"alt="A scenic landscape"class="bordered">
CSS gives you far more control — you can specify the border style, color, individual sides, and even use border-radius for rounded corners, none of which were possible with the old border attribute.
The <center> element is a presentational HTML tag that dates back to early web development. The HTML5 specification formally made it obsolete because it violates the principle of separating content (HTML) from presentation (CSS). While most browsers still render <center> correctly for backward compatibility, relying on it is discouraged for several reasons:
- Standards compliance: Using obsolete elements means your HTML does not conform to the current HTML specification, which can cause W3C validation errors.
- Maintainability: Inline presentational elements scatter styling throughout your markup, making it harder to update the design of your site consistently. CSS allows you to control layout from a single stylesheet.
- Accessibility: Semantic HTML helps assistive technologies understand content structure. The
<center>element carries no semantic meaning and adds noise to the document. - Future-proofing: Browser support for obsolete elements is not guaranteed indefinitely. Using CSS ensures your layout will work reliably going forward.
To fix this issue, replace every <center> element with an appropriate CSS technique. The right approach depends on what you're centering.
For inline content (text, images, inline elements), apply text-align: center to the parent container.
For block-level elements (divs, sections, etc.), use margin: 0 auto along with a defined width, or use Flexbox on the parent.
Examples
❌ Obsolete: using <center>
<center>
<p>This text is centered.</p>
</center>
✅ Fixed: using text-align for inline content
<divstyle="text-align:center">
<p>This text is centered.</p>
</div>
Or better yet, use a CSS class to keep styles out of your HTML:
<divclass="centered-text">
<p>This text is centered.</p>
</div>
.centered-text{
text-align: center;
}
❌ Obsolete: centering a block element with <center>
<center>
<div>This box is centered.</div>
</center>
✅ Fixed: centering a block element with margin: auto
<divclass="centered-box">
<p>This box is centered.</p>
</div>
.centered-box{
max-width:600px;
margin:0 auto;
}
✅ Fixed: centering with Flexbox
Flexbox is a powerful and flexible way to center content both horizontally and vertically:
<divclass="flex-center">
<p>This content is centered.</p>
</div>
.flex-center{
display: flex;
justify-content: center;
}
✅ Applying the fix directly to an element
If you only need to center the text within a single element, you can apply the style directly without a wrapper:
<pclass="centered">This paragraph is centered.</p>
.centered{
text-align: center;
}
In every case, the key takeaway is the same: remove the <center> element and use CSS to achieve the desired centering effect. This keeps your HTML clean, semantic, and fully compliant with modern standards.
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