Guías HTML para css
Aprende a identificar y corregir errores comunes de validación HTML marcados por el W3C Validator, para que tus páginas cumplan con los estándares y se muestren correctamente en todos los navegadores. También consulta nuestras Guías de accesibilidad.
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-word keyword. When specified, this has the same effect as word-break: normal and overflow-wrap: anywhere, regardless of the actual value of the overflow-wrap property.
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 like break-word but also allows the broken word fragments to be considered during min-content sizing calculations. This means containers using min-content or fit-content widths can shrink further.
In most cases, overflow-wrap: break-word is the right replacement.
Examples
Deprecated usage
This triggers the W3C CSS validation warning:
<div style="word-break: break-word;">
Thisislongtext_thatdoesnotcontainanyspaces_andshouldbreakproperly
</div>
Fixed with overflow-wrap: break-word
This is the most common and well-supported fix:
<div style="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:
<div style="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;
}
*/
/* Correct */
.content {
word-break: normal;
overflow-wrap: break-word;
}
</style>
<div class="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 -->
<div class="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 -->
<div class="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., rotateZ typed as rotatez in some contexts, or skew typed as skeew).
- Too many arguments are passed to a transform function (e.g., rotate(45deg, 20deg) instead of rotate(45deg)).
- Arguments are missing required units (e.g., rotate(45) instead of rotate(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-transform syntax are used in the standard transform property 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.
<div style="transform: rotate(45deg), scale(1.5);">Transformed</div>
Correct: Space-separated transform functions
<div style="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.
<div style="transform: rotate(45);">Rotated</div>
Correct: Angle value with unit
<div style="transform: rotate(45deg);">Rotated</div>
Incorrect: Too many arguments in a function
The rotate() function accepts only one argument.
<div style="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.
<div style="transform: rotateZ(45deg);">Rotated on Z axis</div>
Incorrect: Misspelled or non-existent function
<div style="transform: roate(30deg) scaleX(2);">Transformed</div>
Correct: Properly spelled function names
<div style="transform: rotate(30deg) scaleX(2);">Transformed</div>
Incorrect: Using translate without units on non-zero lengths
<div style="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.
<div style="transform: translate(50px, 100px);">Moved</div>
Valid Transform Functions Reference
Here are the commonly used transform functions and their expected arguments:
- translate(tx) or translate(tx, ty) — lengths or percentages
- translateX(tx), translateY(ty), translateZ(tz) — a single length/percentage
- scale(sx) or scale(sx, sy) — unitless numbers
- scaleX(sx), scaleY(sy), scaleZ(sz) — a single unitless number
- rotate(angle) — a single angle value (e.g., 45deg)
- rotateX(angle), rotateY(angle), rotateZ(angle) — a single angle
- skew(ax) or skew(ax, ay) — angle values
- skewX(ax), skewY(ay) — a single angle
- matrix(a, b, c, d, tx, ty) — exactly six unitless numbers
- matrix3d(...) — 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 of rotate(45deg))
- Typos in function names (e.g., rotatee(10deg) or tranlate(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.
<div style="transform: rotate(45);">Rotated text</div>
Fixed: adding the angle unit
<div style="transform: rotate(45deg);">Rotated text</div>
Invalid: typo in function name
<div style="transform: tranlateX(10px);">Shifted text</div>
Fixed: correcting the function name
<div style="transform: translateX(10px);">Shifted text</div>
Invalid: using a non-transform value
A plain number or unrelated keyword is not a valid transform value.
<div style="transform: 200px;">Content</div>
Fixed: using a proper transform function
<div style="transform: translateX(200px);">Content</div>
Invalid: wrong number of arguments for matrix()
The matrix() function requires exactly six comma-separated numbers.
<div style="transform: matrix(1, 2, 3);">Content</div>
Fixed: providing all six arguments
<div style="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: 8px 16px;
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: 8px 16px;
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: 8px 16px;
}
input[type="file"]::file-selector-button {
background-color: #4a90d9;
color: white;
border: none;
padding: 8px 16px;
}
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
<label for="upload">Choose a file:</label>
<input type="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-deep and 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 :host improperly or used without care, ::ng-deep can 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-letter instead 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-visible may 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:
<div class="card-wrapper">
<div class="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-type on a parent element and that your @container query 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 — @container is supported in Chrome 105+, Edge 105+, Firefox 110+, and Safari 16+. If you need to support older browsers, consider using @container as a progressive enhancement alongside a fallback layout.
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.5rem 1rem;
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.5rem 1rem;
border-radius: 0.25rem;
}
.flex {
display: flex;
}
.text-center {
text-align: center;
}
Reference this compiled file in your HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Page</title>
<link rel="stylesheet" href="css/output.css">
</head>
<body>
<p class="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 -->
<link rel="stylesheet" href="css/input.css">
Instead, always link to the build output:
<!-- Do this -->
<link rel="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: 300 instead of width: 300px. CSS requires explicit units for non-zero lengths.
- Multiple values: Writing width: 100px 200px as if width accepted shorthand-style multiple values (it doesn’t).
- Typos or invalid keywords: Writing width: auot instead of width: 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-content or max-content in 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>
<div class="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>
<div class="box">Content</div>
Incorrect: too many values
<style>
.sidebar {
width: 200px 400px;
}
</style>
<aside class="sidebar">Sidebar</aside>
Unlike properties such as margin or padding, width only accepts a single value.
Correct: single value
<style>
.sidebar {
width: 200px;
}
</style>
<aside class="sidebar">Sidebar</aside>
Incorrect: typo in keyword
<style>
.container {
width: auot;
}
</style>
<div class="container">Content</div>
Correct: proper keyword
<style>
.container {
width: auto;
}
</style>
<div class="container">Content</div>
Incorrect: malformed calc() expression
<style>
.panel {
width: calc(100%-40px);
}
</style>
<div class="panel">Content</div>
The calc() function requires spaces around + and - operators.
Correct: properly spaced calc() expression
<style>
.panel {
width: calc(100% - 40px);
}
</style>
<div class="panel">Content</div>
Incorrect: accidental semicolon or extra text
<style>
.card {
width: 50% important;
}
</style>
<div class="card">Content</div>
If you intended to use !important, the ! is required.
Correct: proper !important syntax
<style>
.card {
width: 50% !important;
}
</style>
<div class="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:
<div style="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:
<div style="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, #3498db 70%, 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: 16px 14px;
}
</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: 10px 20px 10px 20px
padding: 1em;
border: 1px solid #ccc;
}
</style>
✅ Fixed shorthand example
<style>
.card {
margin: 10px 20px 10px 20px;
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 write calc(10px * 3) or calc(3 * 10px), but not calc(10px * 5px).
- Division (/): The right-hand operand must be a plain <number> (unitless and non-zero). You can write calc(100px / 2), but not calc(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 -->
<div style="width: calc(100% - );"></div>
<!-- ✅ Fixed: both operands are present -->
<div style="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 -->
<div style="width: calc(10px * 5px);"></div>
<!-- ✅ Fixed: one operand is a unitless number -->
<div style="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 -->
<div style="height: calc(500px / 2em);"></div>
<!-- ✅ Fixed: divisor is a unitless number -->
<div style="height: calc(500px / 2);"></div>
Nested calc() with a missing value
Errors can hide inside nested expressions:
<!-- ❌ Wrong: inner calc has an incomplete expression -->
<p style="margin-top: calc(2rem + calc(100% * ));"></p>
<!-- ✅ Fixed: all operands are present and valid -->
<p style="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() -->
<div style="width: calc(auto * 2);"></div>
<!-- ✅ Fixed: use a numeric value or percentage -->
<div style="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., colr instead of color, or 10xp instead of 10px.
- 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-appearance or -moz-osx-font-smoothing are 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
<p style="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
<p style="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, not text-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:
<p style="colr: red;">Hello</p>
Valid:
<p style="color: red;">Hello</p>
Example using a deprecated/draft name replaced with the current property
Invalid (older draft name):
<div style="gap: 1rem; grid-row-gap: 8px;"></div>
Valid (current, standardized property):
<div style="row-gap: 8px; gap: 1rem;"></div>
Example with vendor-prefixed property plus standard fallback
Invalid (only vendor-prefixed, missing standard property):
<div style="-webkit-user-select: none;"></div>
Valid (fallback plus prefix):
<div style="user-select: none; -webkit-user-select: none;"></div>
Example removing a nonstandard custom property name misuse
Invalid (attempting to invent a property):
<div style="button-style: primary;"></div>
Valid (use classes and real CSS properties):
<style>
.btn--primary {
background-color: #0b5fff;
color: #fff;
}
</style>
<button class="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>
<span class="tag">Tag</span>
Full document with corrected properties
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CSS Property Validation Fixes</title>
<meta name="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>
<div class="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, margin accepts one to four values, so a fifth value is invalid. The color property accepts only a single color value, so writing two colors is an error.
- Unrecognized values: A keyword is misspelled (e.g., blocky instead of block) 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 like font can 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 be inherit), trasparent (should be transparent), and centre (should be center).
- 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(), and clamp().
- 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 -->
<p style="color: red blue;">Hello</p>
<p style="margin: 10px 20px 5px 0px 15px;">Hello</p>
<!-- ✅ Valid: correct number of values -->
<p style="color: red;">Hello</p>
<p style="margin: 10px 20px 5px 0px;">Hello</p>
Unrecognized keyword value
A typo or non-existent keyword triggers the error:
<!-- ❌ Invalid: "blocky" is not a valid display value -->
<div style="display: blocky;">Content</div>
<!-- ✅ Valid: correct keyword -->
<div style="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() -->
<p style="color: rgb(255 0 0 0.5);">Hello</p>
<!-- ✅ Valid: use the correct modern syntax with a slash for alpha -->
<p style="color: rgb(255 0 0 / 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 10pxl instead of 10px, or 2ems instead of 2em.
- 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 100vhmax instead of using max(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
<div style="margin: 10pxl;">Hello</div>
The unit pxl is not a valid CSS unit. The validator reports an unknown dimension for 10pxl.
Correct: Valid unit
<div style="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 px is the default unit (it is not — there is no default unit in CSS).
Examples
Incorrect — missing units on numeric values
<div style="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
<div style="margin: 10px; padding: 20px; width: 300px;">
Content here
</div>
Correct — zero without a unit
<div style="margin: 0; padding: 0; border: 0;">
No units needed for zero
</div>
Correct — mixing zero and non-zero values
<div style="margin: 0 10px 0 20px;">
Top and bottom margins are zero, sides have units
</div>
Correct — using other unit types
<p style="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 align attribute from the <td> element.
- Apply the CSS text-align property instead, either via an inline style attribute, 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>
<td align="center">Centered content</td>
<td align="right">Right-aligned content</td>
</tr>
</table>
✅ Fixed: using inline CSS
<table>
<tr>
<td style="text-align: center;">Centered content</td>
<td style="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>
<td class="text-center">Centered content</td>
<td class="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 <span style="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 <span class="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 <strong class="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> behavior
- font-size: 1.2em — scales to 120% of the parent’s font size
- font-size: 1.25rem — scales relative to the root font size
- font-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 border attribute 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 like border: 2px solid #333;.
Examples
❌ Obsolete border attribute
<a href="/products">
<img src="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>
<a href="/products">
<img src="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)
<a href="/products">
<img src="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>
<img src="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
<div style="text-align: center">
<p>This text is centered.</p>
</div>
Or better yet, use a CSS class to keep styles out of your HTML:
<div class="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
<div class="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:
<div class="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:
<p class="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.
The <font> element was originally introduced to give authors control over text rendering directly in markup. A typical usage looked like <font face="Arial" size="3" color="red">. While browsers still render this element for backward compatibility, it has been obsolete since HTML5 and will trigger a validation error. The W3C validator flags it because it violates the principle of separation of concerns: HTML should define the structure and meaning of content, while CSS should handle its visual presentation.
Using <font> causes several practical problems:
- Maintainability: Styling scattered across <font> tags throughout your HTML is extremely difficult to update. Changing a color scheme could mean editing hundreds of elements instead of a single CSS rule.
- Accessibility: The <font> element carries no semantic meaning. Screen readers and other assistive technologies gain nothing from it, and its presence can clutter the document structure.
- Consistency: CSS enables you to define styles in one place and apply them uniformly across your entire site using classes, selectors, or external stylesheets.
- Standards compliance: Using obsolete elements means your HTML does not conform to the current specification, which can lead to unexpected rendering in future browser versions.
To fix this issue, remove every <font> element and replace its visual effects with equivalent CSS properties. The three attributes of <font> map directly to CSS:
| <font> attribute | CSS equivalent |
|---|---|
| color | color |
| size | font-size |
| face | font-family |
You can apply CSS as inline styles for quick fixes, but using a <style> block or an external stylesheet with classes is the preferred approach for any real project.
Examples
Incorrect: using the obsolete <font> element
<p>
<font face="Arial" size="4" color="blue">Welcome to my website</font>
</p>
This triggers the validator error: The “font” element is obsolete. Use CSS instead.
Fix with inline styles
If you need a quick, direct replacement:
<p style="font-family: Arial, sans-serif; font-size: 18px; color: blue;">
Welcome to my website
</p>
Fix with a CSS class (recommended)
Using a class keeps your HTML clean and makes styles reusable:
<style>
.welcome-text {
font-family: Arial, sans-serif;
font-size: 18px;
color: blue;
}
</style>
<p class="welcome-text">Welcome to my website</p>
Nested <font> elements replaced with CSS
Old markup sometimes used multiple nested <font> tags:
<!-- Obsolete -->
<p>
<font color="red" size="5">
Important:
<font face="Courier">code goes here</font>
</font>
</p>
The correct approach uses <span> elements or semantic tags with CSS classes:
<style>
.alert-heading {
color: red;
font-size: 24px;
}
.code-snippet {
font-family: Courier, monospace;
}
</style>
<p>
<span class="alert-heading">
Important:
<span class="code-snippet">code goes here</span>
</span>
</p>
If the text carries a specific meaning — such as marking something as important or representing code — consider using semantic HTML elements like <strong>, <em>, or <code> alongside your CSS:
<style>
.alert-heading {
color: red;
font-size: 24px;
}
</style>
<p class="alert-heading">
<strong>Important:</strong>
<code>code goes here</code>
</p>
This approach gives you full control over appearance through CSS while keeping your HTML meaningful, accessible, and standards-compliant.
The <tt> element was a purely presentational element — it described how text should look (monospaced) rather than what the text meant. HTML5 removed it as part of a broader effort to separate content from presentation. Browsers still render <tt> for backward compatibility, but validators will flag it as obsolete, and its use is discouraged in all new code.
The key issue is that <tt> was used for many different purposes — displaying code snippets, keyboard input, sample output, variables, filenames, and more — yet it conveyed none of that meaning to assistive technologies or search engines. HTML5 provides dedicated semantic elements for most of these use cases, making your content more meaningful and accessible.
Choosing the Right Replacement
Before reaching for a generic <span>, consider what the monospaced text actually represents:
- Code: Use <code> for inline code fragments (e.g., variable names, short statements).
- Keyboard input: Use <kbd> for text the user should type.
- Sample output: Use <samp> for output from a program or system.
- Variables: Use <var> for mathematical or programming variables.
- No semantic meaning: Use a <span> with CSS when the monospaced styling is purely visual and none of the above elements apply.
All of these elements render in a monospaced font by default in most browsers (except <var>, which is typically italic). You can further style them with CSS as needed.
Examples
❌ Obsolete usage with <tt>
<p>Run the command <tt>npm install</tt> to install dependencies.</p>
<p>The variable <tt>x</tt> holds the result.</p>
<p>The output was <tt>Hello, world!</tt></p>
These all trigger the validator error: The “tt” element is obsolete. Use CSS instead.
✅ Fixed with semantic elements
<p>Run the command <kbd>npm install</kbd> to install dependencies.</p>
<p>The variable <var>x</var> holds the result.</p>
<p>The output was <samp>Hello, world!</samp></p>
Each replacement conveys the meaning of the text. <kbd> tells assistive technologies this is something the user types, <var> marks a variable, and <samp> indicates program output.
✅ Fixed with <code> for inline code
<p>Use the <code>Array.prototype.map()</code> method to transform each element.</p>
✅ Fixed with a <span> and CSS when no semantic element fits
If the monospaced text doesn’t represent code, input, output, or a variable — for example, a stylistic choice for a filename or an arbitrary design decision — use a <span> with CSS:
<p>Edit the file <span class="mono">config.yaml</span> to change the settings.</p>
.mono {
font-family: monospace;
}
This keeps your HTML valid and your styling in the CSS layer where it belongs.
✅ Block-level code with <pre> and <code>
If you previously used <tt> inside a <pre> block for multi-line code, the standard approach is to combine <pre> with <code>:
<pre><code>function greet(name) {
return "Hello, " + name;
}</code></pre>
Summary
Replace every <tt> element with the semantic HTML element that best describes its content — <code>, <kbd>, <samp>, or <var>. If none of these fit, use a <span> styled with font-family: monospace in CSS. This keeps your markup valid, meaningful, and accessible.
In earlier versions of HTML (HTML 4 and XHTML), the type attribute was required on the <style> element to declare the MIME type of the styling language being used. The value was almost always text/css, as CSS has been the dominant stylesheet language for the web since its inception.
With HTML5, the specification changed. The type attribute on <style> now defaults to text/css, and since no browser supports any other styling language, the attribute serves no practical purpose. The WHATWG HTML Living Standard explicitly notes that the attribute is unnecessary and can be omitted. The W3C validator flags its presence as a warning to encourage cleaner, more modern markup.
Why This Matters
- Cleaner code: Removing unnecessary attributes reduces file size (even if marginally) and improves readability. Every attribute should earn its place in your markup.
- Standards compliance: Modern HTML encourages omitting default values when they add no information. Including type="text/css" signals outdated coding practices.
- Consistency: The same principle applies to <script> elements, where type="text/javascript" is also unnecessary. Keeping your markup consistent by omitting both makes your codebase easier to maintain.
How to Fix It
The fix is straightforward: find every <style> element in your HTML that includes a type attribute and remove it. No other changes are needed — the browser behavior will be identical.
If you’re working on a large codebase, a simple search for <style type= across your files will help you find all instances.
Examples
❌ Incorrect: Redundant type attribute
<style type="text/css">
p {
color: red;
}
</style>
<p>This text will be red.</p>
The type="text/css" attribute is unnecessary and triggers the W3C validator warning.
✅ Correct: type attribute omitted
<style>
p {
color: red;
}
</style>
<p>This text will be red.</p>
Without the type attribute, the browser still interprets the contents as CSS — the behavior is exactly the same.
❌ Incorrect: Other variations that also trigger the warning
The warning is triggered regardless of how the type value is formatted:
<style type="text/css" media="screen">
body {
font-family: sans-serif;
}
</style>
✅ Correct: Other attributes are fine, just remove type
<style media="screen">
body {
font-family: sans-serif;
}
</style>
Note that other valid attributes like media or nonce should be kept — only the type attribute needs to be removed.
The valign attribute was part of earlier HTML specifications (HTML 4.01 and XHTML 1.0) and accepted values like top, middle, bottom, and baseline to control how content was vertically positioned within a table cell. In HTML5, this attribute is obsolete because the specification separates content structure from presentation. All visual styling should be handled through CSS.
This matters for several reasons. First, using obsolete attributes triggers W3C validation errors, which can indicate broader code quality issues. Second, browsers may eventually drop support for legacy presentational attributes, potentially breaking your layout. Third, CSS provides far more flexibility and maintainability — you can style entire tables or groups of cells with a single rule instead of repeating valign on every <td>.
The valign attribute was also valid on <th>, <tr>, <thead>, <tbody>, and <tfoot> elements, and it is obsolete on all of them. The fix is the same: use the CSS vertical-align property.
To fix this issue, remove the valign attribute from your <td> elements and apply the equivalent CSS vertical-align property. The CSS property accepts the same familiar values: top, middle, bottom, and baseline.
Examples
❌ Incorrect: using the obsolete valign attribute
<table>
<tr>
<td valign="top">Top-aligned content</td>
<td valign="middle">Middle-aligned content</td>
<td valign="bottom">Bottom-aligned content</td>
</tr>
</table>
✅ Fixed: using inline CSS
<table>
<tr>
<td style="vertical-align: top;">Top-aligned content</td>
<td style="vertical-align: middle;">Middle-aligned content</td>
<td style="vertical-align: bottom;">Bottom-aligned content</td>
</tr>
</table>
✅ Fixed: using a class-based approach (recommended)
For better maintainability, define reusable CSS classes instead of repeating inline styles:
<style>
.valign-top { vertical-align: top; }
.valign-middle { vertical-align: middle; }
.valign-bottom { vertical-align: bottom; }
</style>
<table>
<tr>
<td class="valign-top">Top-aligned content</td>
<td class="valign-middle">Middle-aligned content</td>
<td class="valign-bottom">Bottom-aligned content</td>
</tr>
</table>
✅ Fixed: applying a default to all cells in a table
If every cell in a table should share the same vertical alignment, target them with a single CSS rule:
<style>
.data-table td,
.data-table th {
vertical-align: top;
}
</style>
<table class="data-table">
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<tr>
<td>Item A</td>
<td>A longer description that may<br>span multiple lines</td>
</tr>
</table>
This approach is the most maintainable — you set the alignment once and it applies consistently to every cell, without needing to modify individual <td> or <th> elements.
¿Listo para validar tus sitios?
Comienza tu prueba gratuita hoy.