HTML Guides
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The padding-left property accepts a valid CSS length value, a percentage, or the keyword 0. A CSS length is always composed of two parts: a number and a unit (e.g., 10px, 2em, 1.5rem). Writing just px with no number is syntactically invalid — it's a bare unit with no magnitude, so the browser cannot determine what spacing to apply. This commonly occurs due to a typo, a missing variable in a template or preprocessor, or accidentally deleting the numeric portion during editing.
When the validator encounters this in a style attribute, it flags the value as invalid CSS. While most browsers will simply ignore the malformed declaration and fall back to the default padding, relying on this error-recovery behavior leads to unpredictable layouts. Fixing the issue ensures your styles are applied consistently across all browsers and that your markup passes validation.
How to fix it
- Add a numeric value before the unit: change
pxto something like10px,1em, or5%. - If you want zero padding, use
0— no unit is needed (though0pxis also valid). - Check template variables and preprocessors. If you're using a system like PHP, JavaScript templating, or a CSS preprocessor (Sass, Less), make sure the variable that should supply the number isn't empty or undefined. For example,
padding-left: <?= $indent ?>px;will producepadding-left: px;if$indentis empty.
Examples
Incorrect: bare unit with no number
<divstyle="padding-left: px;">Content</div>
The value px has no numeric component, so it is not a valid length.
Correct: numeric value before the unit
<divstyle="padding-left:10px;">Content</div>
Correct: zero padding (no unit required)
<divstyle="padding-left:0;">Content</div>
Incorrect: empty variable producing a bare unit
This is a common source of the bug in templated or dynamically generated HTML:
<!-- If the variable is empty, this renders as "padding-left: px;" -->
<divstyle="padding-left: px;">Content</div>
Correct: ensuring a fallback value
When generating styles dynamically, always provide a sensible default so the output is valid even if the variable is missing:
<divstyle="padding-left:16px;">Content</div>
Using an external stylesheet
The same rule applies in external or embedded CSS. The incorrect version:
.sidebar{
padding-left: px;
}
The corrected version with a proper numeric value:
.sidebar{
padding-left:20px;
}
Other valid padding-left values
Any valid CSS length or percentage works:
<divstyle="padding-left:2em;">Em-based padding</div>
<divstyle="padding-left:1.5rem;">Rem-based padding</div>
<divstyle="padding-left:5%;">Percentage-based padding</div>
The padding shorthand property sets the padding area on all four sides of an element. It accepts one to four values, each of which must be a <length> (e.g., 10px, 1em), a <percentage>, or 0. Unlike some other CSS properties such as border, outline, or max-width, the padding property has no none keyword in its value syntax.
This is a common mistake because several CSS properties do accept none — for example, border: none, text-decoration: none, and display: none. It's natural to assume padding: none would work the same way, but the CSS specification simply doesn't define it for padding. When a browser encounters an invalid value, it ignores the declaration entirely, which means your intended styling won't be applied and the element may retain its default or inherited padding. This can lead to unexpected layout issues that are difficult to debug.
The same rule applies to the margin property — margin: none is also invalid. Use margin: 0 instead.
How to Fix It
Replace none with 0. You don't need to include a unit when the value is zero, so padding: 0 is perfectly valid and is the idiomatic way to express "no padding." You can also use 0 for individual padding properties like padding-top, padding-right, padding-bottom, and padding-left.
If you only want to remove padding on specific sides, target those sides individually rather than using the shorthand.
Examples
❌ Incorrect: Using none with padding
.card{
padding: none;
}
The validator will report: CSS: "padding": "none" is not a "padding" value. The browser will ignore this declaration.
✅ Correct: Using 0 to remove padding
.card{
padding:0;
}
✅ Correct: Removing padding on specific sides
.card{
padding-top:0;
padding-bottom:0;
}
❌ Incorrect: Using none in inline styles
<divstyle="padding: none;">Content</div>
✅ Correct: Using 0 in inline styles
<divstyle="padding:0;">Content</div>
✅ Correct: Using valid padding values
/* Single value — applies to all four sides */
.card{
padding:16px;
}
/* Two values — vertical | horizontal */
.card{
padding:10px20px;
}
/* Four values — top | right | bottom | left */
.card{
padding:10px20px15px5px;
}
/* Zero on top/bottom, 1em on left/right */
.card{
padding:01em;
}
The padding property accepts one or more length values, percentages, or the keyword 0. A valid length value always consists of a number immediately followed by a unit identifier, such as 10px, 1.5em, or 2rem. Writing just px without a preceding number is meaningless to the CSS parser — it's like saying "pixels" without specifying how many. The browser will discard the invalid declaration entirely, which means the element will fall back to its default or inherited padding, potentially breaking your layout in unexpected ways.
This error commonly occurs due to:
- Typos or accidental deletion — the numeric part of the value was inadvertently removed during editing.
- Templating or build tool issues — a dynamic value (e.g., from a variable or CMS field) resolved to an empty string, leaving only the
pxsuffix behind. - Copy-paste mistakes — copying a snippet and forgetting to update the placeholder value.
Because the W3C validator flags this in inline style attributes, it means invalid CSS is embedded directly in your HTML. Fixing it improves standards compliance and ensures consistent rendering across browsers.
How to Fix
- Add a numeric value before the unit: change
pxto something like10px,1em, or5%. - Use
0without a unit if you want zero padding — writingpadding: 0;is valid and preferred overpadding: 0px;. - Check dynamic values — if the number comes from a variable or template expression, make sure it outputs a valid number and isn't empty.
Examples
Incorrect: Unit Without a Number
<divstyle="padding: px;">Content</div>
The validator reports that px is not a valid padding value because no number precedes the unit.
Correct: Numeric Value With Unit
<divstyle="padding:10px;">Content</div>
Correct: Zero Padding (No Unit Needed)
<divstyle="padding:0;">Content</div>
When the value is 0, no unit is required since zero pixels, zero ems, and zero percent are all identical.
Correct: Multiple Padding Values
<divstyle="padding:8px16px;">Content</div>
This sets 8px of vertical padding and 16px of horizontal padding — both are valid length values.
Incorrect in External CSS
The same problem can appear in a stylesheet linked from your HTML:
.card{
padding: px;
}
Fixed in External CSS
.card{
padding:12px;
}
Watch for Template-Generated Values
If you use a templating system, double-check that the numeric portion actually renders. For example, a template like this could produce the error if spacing is empty:
<!-- If spacing is empty, this becomes "padding: px;" -->
<divstyle="padding:{{ spacing }}px;">Content</div>
Make sure the variable always resolves to a valid number, or provide a fallback value.
The padding-right property defines the space between an element's content and its right border. According to the CSS Box Model specification, padding represents internal space within an element, and conceptually, negative internal space doesn't make sense — you can't have less than zero space between content and its border. This rule applies equally to all padding properties: padding-top, padding-right, padding-bottom, padding-left, and the padding shorthand.
Browsers will typically ignore or discard a negative padding value, meaning your intended layout adjustment won't take effect. Beyond simply being invalid CSS, this can lead to inconsistent rendering across browsers and unexpected layout behavior. Relying on invalid values makes your stylesheets fragile and harder to maintain.
If your goal is to pull an element closer to its neighbor or create an overlapping effect, margin-right is the appropriate property to use. Unlike padding, margins are explicitly allowed to have negative values. Negative margins reduce the space between elements or even cause them to overlap, which is often the actual intent behind a negative padding attempt.
How to Fix
- Set the value to
0or a positive number. If you simply want no padding, use0. If you need some spacing, use a positive value. - Use
margin-rightfor negative spacing. If you need to reduce external space or create overlap, switch to a negative margin instead. - Re-evaluate your layout approach. In some cases, using
transform: translateX(), Flexboxgap, or Grid layout may achieve the desired result more cleanly than negative values on any property.
Examples
Incorrect: negative padding value
<style>
.sidebar{
padding-right:-10px;
}
</style>
<divclass="sidebar">
<p>Sidebar content</p>
</div>
This triggers the validator error because -10px is not a valid value for padding-right.
Fixed: using zero or a positive value
<style>
.sidebar{
padding-right:0;
}
</style>
<divclass="sidebar">
<p>Sidebar content</p>
</div>
Fixed: using a negative margin instead
If the intent was to reduce external spacing on the right side, use margin-right:
<style>
.sidebar{
padding-right:0;
margin-right:-10px;
}
</style>
<divclass="sidebar">
<p>Sidebar content</p>
</div>
Fixed: using transform for visual offset
If the goal is to visually shift the element without affecting document flow, transform is another option:
<style>
.sidebar{
padding-right:0;
transform:translateX(10px);
}
</style>
<divclass="sidebar">
<p>Sidebar content</p>
</div>
Quick reference: padding vs. margin
| Property | Negative values allowed? | Purpose |
|---|---|---|
padding-right | No | Space between content and border |
margin-right | Yes | Space between the element's border and surrounding elements |
Choose the property that matches your layout intent, and remember that all four padding directions — padding-top, padding-right, padding-bottom, and padding-left — follow the same non-negative rule.
The padding-right property defines the amount of space between an element's content and its right border. Like all CSS length properties, it expects either a valid length value (a number paired with a unit like px, em, rem, %, vw, etc.), the keyword 0 (which needs no unit), or the keyword inherit/initial/unset. A bare unit such as px with no number is meaningless — it doesn't tell the browser how much padding to apply.
This error typically occurs due to a typo, a templating issue where a variable failed to render, or accidental deletion of the numeric portion of the value. For example, a template like padding-right: {{ value }}px; might produce padding-right: px; if value is empty or undefined.
When the browser encounters an invalid value like px, it discards the entire declaration and falls back to the default or inherited value for padding-right. This can lead to unexpected layout differences across browsers and makes your intentions unclear to other developers. Fixing these validation errors also helps maintain clean, predictable stylesheets.
How to Fix
- Add the missing number before the unit: change
pxto a specific value like10px. - Use
0without a unit if you want no padding:padding-right: 0;is valid and preferred overpadding-right: 0px;. - Check template variables and dynamic style generation to ensure numeric values are always output correctly.
Examples
Incorrect: bare unit with no number
<divstyle="padding-right: px;">Content</div>
The value px is not valid because it lacks a numeric component.
Correct: numeric value with unit
<divstyle="padding-right:10px;">Content</div>
Correct: zero padding (no unit needed)
<divstyle="padding-right:0;">Content</div>
Correct: using other valid units
<divstyle="padding-right:2em;">Content</div>
<divstyle="padding-right:5%;">Content</div>
Incorrect in an external stylesheet
.sidebar{
padding-right: px;
}
Fixed in an external stylesheet
.sidebar{
padding-right:16px;
}
Guarding against empty values in templates
If you generate CSS dynamically, make sure the numeric value is always present. For instance, provide a fallback:
.sidebar{
padding-right:16px;/* safe default */
}
Rather than relying on a template that might produce an empty value, consider setting defaults in your CSS and only overriding with inline styles when you're certain the value is valid.
The W3C validator reports this error when it encounters padding-top: px; — a unit with no numeric component. In CSS, length values are composed of two parts: a number and a unit identifier (e.g., px, em, rem, %, vh). The unit alone is meaningless without a number to quantify it. This typically happens due to a typo, a preprocessor variable that resolved to an empty value, or accidentally deleting the number during editing.
This matters for several reasons. Browsers will discard the invalid declaration entirely, meaning padding-top will fall back to its default or inherited value — which may not be what you intended. This can cause unpredictable layout differences across browsers. Additionally, invalid CSS can interfere with parsing of subsequent declarations in the same rule block, potentially causing other styles to be ignored as well.
To fix this issue:
- Add a numeric value before the unit: change
pxto something like10px,1.5em, or20%. - Use
0without a unit if you want zero padding:padding-top: 0;is valid and preferred overpadding-top: 0px;. - Check preprocessor variables (Sass, Less, etc.) to make sure they resolve to complete values, not just units.
- Remove the declaration entirely if padding-top doesn't need to be set.
Examples
Incorrect: unit without a number
<divstyle="padding-top: px;">Content</div>
The value px is not a valid padding-top value because it lacks a numeric component.
Correct: number with a unit
<divstyle="padding-top:10px;">Content</div>
Correct: zero padding (no unit needed)
<divstyle="padding-top:0;">Content</div>
Incorrect in an external stylesheet
.header{
padding-top: px;
}
Correct in an external stylesheet
.header{
padding-top:16px;
}
Common preprocessor pitfall
If you use a CSS preprocessor like Sass, watch out for variables that might be empty or undefined:
/* If $spacing somehow resolves to empty, this produces "padding-top: px;" */
.card{
padding-top: $spacing +px;
}
/* Safer approach — define the variable with the full value */
.card{
padding-top: $spacing;/* where $spacing: 16px; */
}
Any valid CSS length value will work for padding-top, including px, em, rem, %, vw, vh, ch, and others — as long as a number precedes the unit. The only length value that doesn't require a unit is 0.
Unlike margin properties, which accept negative values to pull elements closer together or overlap them, all padding properties (padding-top, padding-right, padding-bottom, padding-left, and the padding shorthand) are defined in the CSS specification to only accept zero or positive lengths. This is because padding represents the space inside an element between its content and its border — a negative internal space is not a meaningful concept.
When you use a negative padding value, browsers will typically ignore the declaration entirely, meaning your layout may not look the way you intended. The W3C validator catches this to help you identify code that won't behave consistently across browsers and doesn't conform to the CSS specification.
If your goal is to reduce the space between elements, negative margin values are the correct tool. If you're trying to shift content upward within a container, consider using position: relative with a negative top offset, or adjust the layout with other techniques like transform: translateY().
Examples
❌ Invalid: negative padding value
<divstyle="padding-top:-20px;">
This element has invalid negative padding.
</div>
The validator will report: CSS: "padding-top": "-20" negative values are not allowed.
✅ Fixed: using zero or positive padding
<divstyle="padding-top:0;">
This element has no top padding.
</div>
<divstyle="padding-top:10px;">
This element has valid positive top padding.
</div>
✅ Alternative: using negative margin instead
If you need to reduce the space above an element, use a negative margin-top:
<divstyle="margin-top:-20px;">
This element is pulled upward with a negative margin.
</div>
❌ Invalid: negative values in the padding shorthand
The same rule applies to the padding shorthand property. Any negative component value is invalid:
<divstyle="padding:-10px20px15px20px;">
Invalid shorthand padding.
</div>
✅ Fixed: all-positive shorthand values
<divstyle="padding:020px15px20px;">
Valid shorthand padding with zero top padding.
</div>
✅ Alternative: using transform for visual offset
If you need to visually shift an element's content upward without affecting layout flow, transform is a clean option:
<divstyle="transform:translateY(-20px);">
This element appears shifted upward.
</div>
A CSS padding property contains a value the validator does not recognize as valid for that property.
The padding shorthand and its longhand variants (padding-top, padding-right, padding-bottom, padding-left) accept only <length>, <percentage>, or the keyword auto (in some contexts). Common causes of this error include:
- Using an invalid unit or misspelling a unit, such as
10xpinstead of10px. - Omitting the unit on a non-zero value, such as
padding: 10instead ofpadding: 10px. - Passing a color, keyword, or other unrelated value, such as
padding: redorpadding: bold. - Including extra or misplaced values from a copy-paste error, such as
padding: 10px 20px 30px 40px 50px(five values instead of the maximum four). - Using CSS custom properties or newer syntax in an inline
styleattribute that the validator's CSS parser does not yet support.
The padding shorthand accepts one to four values, corresponding to the top, right, bottom, and left sides. Each value must be a non-negative length (like 0, 8px, 1em, 2rem) or a percentage.
HTML examples
Invalid padding value
<divstyle="padding:10xp;">Content</div>
Fixed padding value
<divstyle="padding:10px;">Content</div>
A CSS parse error means the validator's CSS parser encountered something unexpected and could not make sense of the code from that point forward. Unlike many HTML errors that pinpoint a specific rule violation, a parse error is more general — the parser simply gave up trying to interpret the CSS. This can sometimes cause a cascade of additional errors, since the parser may lose track of context after the initial failure.
This matters because browsers handle broken CSS unpredictably. While most browsers are forgiving and will skip invalid rules, the way they recover varies. Styles may render differently across browsers, or entire rule blocks may be silently ignored. Valid CSS ensures consistent rendering, easier debugging, and better maintainability.
Common causes of CSS parse errors include:
- Missing semicolons between declarations
- Unclosed curly braces
{or extra closing braces} - Unclosed comments (
/*without a matching*/) - Invalid or empty property values (e.g.,
color: ;) - Unexpected characters such as stray text, unsupported tokens, or HTML markup inside
<style>blocks - Typos in property names or values (e.g.,
colr: red) - Using CSS syntax that isn't valid in an attribute context, such as placing selectors inside a
styleattribute
To fix the error, go to the line indicated by the validator and carefully inspect the CSS around that point. Look for the common issues listed above. Sometimes the actual mistake is on a line before the reported one — for example, a missing semicolon on line 5 might only cause a parse error on line 6.
Examples
Missing semicolon
A missing semicolon causes the parser to misinterpret where one declaration ends and the next begins.
❌ Incorrect:
<pstyle="color:redfont-size: 16px">Hello</p>
✅ Fixed:
<pstyle="color: red;font-size: 16px">Hello</p>
Unclosed curly brace
A missing closing brace causes the parser to treat subsequent rules as part of the unclosed block.
❌ Incorrect:
<style>
.container{
margin:0 auto;
padding:20px;
.title{
font-size:24px;
}
</style>
✅ Fixed:
<style>
.container{
margin:0 auto;
padding:20px;
}
.title{
font-size:24px;
}
</style>
Unclosed comment
A comment that is never closed causes everything after it to be consumed by the parser as part of the comment.
❌ Incorrect:
<style>
/*Setthemaincolor
body{
color:#333;
}
</style>
✅ Fixed:
<style>
/* Set the main color */
body{
color:#333;
}
</style>
Empty or invalid property value
Declaring a property with no value or a clearly invalid value triggers a parse error.
❌ Incorrect:
<divstyle="background-color:;">Content</div>
✅ Fixed:
<divstyle="background-color:#f0f0f0;">Content</div>
Selectors inside an inline style attribute
The style attribute only accepts declarations (property-value pairs), not selectors or full rule blocks.
❌ Incorrect:
<divstyle="p{color: blue;}">Content</div>
✅ Fixed:
<divstyle="color: blue;">Content</div>
Stray characters or typos
Unexpected characters anywhere in CSS will cause parsing to fail.
❌ Incorrect:
<style>
.box{
width:100px;;
height: 50px
border: 1px solid #ccc;
}
</style>
While a double semicolon (;;) is technically harmless in most parsers, a missing semicolon after height: 50px merges it with the next line, producing an invalid value.
✅ Fixed:
<style>
.box{
width:100px;
height:50px;
border:1px solid #ccc;
}
</style>
If the validator points to a line but the cause isn't obvious, try isolating sections of your CSS and validating them separately using the W3C CSS Validation Service. This can help narrow down the exact location of the problem.
The CSS perspective property does not accept 0 as a valid value. It must be either none or a positive length greater than zero.
The perspective property defines the distance between the viewer and the z=0 plane, which determines the intensity of 3D effects on child elements. A value of 0 is mathematically undefined (it would place the viewer directly on the plane), so the specification rejects it. If the goal is to remove perspective entirely, use none. If the goal is a very strong perspective effect, use a small positive value like 1px.
The property applies to the element's children, not the element itself. A smaller value creates a more dramatic 3D effect, while a larger value creates a subtler one.
Invalid example
<divstyle="perspective:0;">
<divstyle="transform:rotateY(45deg);">Content</div>
</div>
Valid examples
To disable perspective:
<divstyle="perspective: none;">
<divstyle="transform:rotateY(45deg);">Content</div>
</div>
To apply a strong (but valid) perspective:
<divstyle="perspective:1px;">
<divstyle="transform:rotateY(45deg);">Content</div>
</div>
The pointer-events CSS property controls whether an element can be the target of pointer events such as clicks, taps, and hover states. Unlike many other CSS properties that accept normal as a keyword (e.g., white-space, letter-spacing), the pointer-events property does not include normal in its list of valid values. This is a common mistake since normal and auto are often used interchangeably across different CSS properties, but each property defines its own set of accepted keywords.
Using an invalid value like normal means the browser will ignore the entire declaration. In most cases this won't cause visible breakage because the default behavior already allows pointer interaction, but it can lead to unexpected results if you're relying on the property to override an inherited pointer-events: none from a parent element. The invalid declaration would simply be discarded, and the inherited none value would remain in effect, making the element unclickable.
For standard HTML elements, the two primary values you'll use are:
auto— The element behaves as it normally would regarding pointer events. This is the default.none— The element is never the target of pointer events. Clicks and hovers pass through to whatever is behind it.
Several additional values exist (visiblePainted, visibleFill, visibleStroke, visible, painted, fill, stroke, all) but these only apply to SVG elements. Global CSS keywords like inherit, initial, unset, and revert are also valid.
To fix the issue, replace normal with auto wherever it appears as a pointer-events value. If you're using pointer-events: normal to restore default interactivity after a parent set pointer-events: none, then auto is exactly what you need.
Examples
Incorrect — using normal
<divstyle="pointer-events: normal;">
<ahref="/about">About us</a>
</div>
The validator will flag normal as an invalid value for pointer-events.
Correct — using auto
<divstyle="pointer-events: auto;">
<ahref="/about">About us</a>
</div>
Practical use case: restoring pointer events on a child
A common pattern is disabling pointer events on a parent and re-enabling them on a specific child. Using normal here would silently fail, leaving the button unclickable:
<!-- Incorrect -->
<style>
.overlay{
pointer-events: none;
}
.overlay.close-btn{
pointer-events: normal;/* Invalid — button remains unclickable */
}
</style>
<divclass="overlay">
<buttonclass="close-btn">Close</button>
</div>
<!-- Correct -->
<style>
.overlay{
pointer-events: none;
}
.overlay.close-btn{
pointer-events: auto;/* Valid — button is clickable again */
}
</style>
<divclass="overlay">
<buttonclass="close-btn">Close</button>
</div>
In the incorrect version, the browser discards the invalid pointer-events: normal declaration entirely, so the .close-btn inherits none from the parent and cannot be clicked. Changing it to auto correctly restores interactivity on the button.
In CSS, a length value is composed of two parts: a number and a unit. Writing just px provides the unit but omits the number, which makes the declaration invalid. The CSS parser cannot interpret px alone as a meaningful measurement, so the property is ignored entirely. This means your intended layout won't be applied, potentially causing elements to render at unexpected sizes across different browsers.
This error commonly arises from typos, copy-paste mistakes, or templating issues where a variable that should output a number resolves to an empty string, leaving behind only the unit suffix. It can also happen when a numeric value is accidentally deleted during editing.
Beyond layout breakdowns, invalid CSS can cause inconsistent rendering across browsers. Some browsers may silently discard the invalid declaration, while others might apply unexpected fallback behavior. Keeping your CSS valid ensures predictable, cross-browser results and makes your stylesheets easier to maintain and debug.
How to Fix It
- Add the missing numeric value — Pair every unit with a number, e.g.,
300px,1.5em,50%. - Use
0without a unit for zero values — The value0is valid on its own and doesn't require a unit. - Use a valid keyword — Properties like
widthaccept keywords such asauto,min-content,max-content, andfit-content. - Check dynamic values — If a preprocessor or template engine generates the value, verify it outputs a complete length (e.g.,
${value}pxwherevalueis not empty).
Examples
Incorrect: unit without a number
<style>
.box{
width: px;
}
</style>
<divclass="box">Content</div>
The declaration width: px is invalid because px alone is not a recognized CSS value. The browser will discard this rule.
Incorrect: number without a unit
<style>
.box{
width:300;
}
</style>
<divclass="box">Content</div>
A unitless number (other than 0) is also invalid for the width property. Browsers will ignore this declaration as well.
Correct: number paired with a unit
<style>
.box{
width:300px;
}
</style>
<divclass="box">Content</div>
Correct: using different valid length units
<style>
.box-a{
width:50%;
}
.box-b{
width:20em;
}
.box-c{
width:15rem;
}
.box-d{
width:80vw;
}
</style>
Correct: zero value and keywords
<style>
.collapsed{
width:0;
}
.flexible{
width: auto;
}
.intrinsic{
width: fit-content;
}
</style>
The value 0 is the only number that doesn't require a unit in CSS. Keywords like auto, min-content, max-content, and fit-content are also valid for width and don't use numeric lengths at all.
Common CSS Length Units
| Unit | Description |
|---|---|
px | Pixels (absolute unit) |
em | Relative to the element's font size |
rem | Relative to the root element's font size |
% | Percentage of the containing block's dimension |
vw | 1% of the viewport width |
vh | 1% of the viewport height |
ch | Width of the "0" character in the element's font |
Always double-check that your CSS length values include both a number and a unit. If you're generating styles dynamically, add safeguards to ensure the numeric portion is never empty before the unit is appended.
An invalid value was assigned to the CSS right property, meaning the validator does not recognize the value you provided.
The CSS right property specifies the horizontal offset of a positioned element from the right edge of its containing block. It only accepts specific value types: a length (e.g., 10px, 2em), a percentage (e.g., 50%), auto, inherit, initial, unset, or revert. Any other value — such as a typo, a missing unit, or an unsupported keyword — will trigger this validation error.
A common mistake is forgetting the unit after a number. In CSS, 0 is the only length value that can be written without a unit. Writing something like right: 10 instead of right: 10px is invalid. Another common cause is using an unrecognized keyword or passing a value meant for a different property.
Invalid Example
<divstyle="position: absolute;right:10;">
This box has an invalid right value.
</div>
The value 10 is missing a unit, so the validator rejects it.
Fixed Example
<divstyle="position: absolute;right:10px;">
This box is correctly positioned.
</div>
Adding a valid unit like px, em, rem, or % resolves the issue. If you intended no offset, use right: 0 or right: auto.
The stroke-width property controls the thickness of the outline (stroke) drawn around shapes and text, primarily used in SVG but also applicable to HTML elements via CSS. According to both the SVG specification and the CSS standard, stroke-width accepts only non-negative values — that is, zero or any positive number, optionally with a CSS length unit like px, em, or rem. A unitless number is also valid and is interpreted in the current coordinate system's user units.
Negative values are logically meaningless for stroke width because you cannot draw an outline with negative thickness. Browsers will typically ignore or discard the invalid declaration, meaning the stroke may render with an unexpected default width or not at all. Beyond rendering issues, using invalid CSS values causes W3C validation errors, which can indicate broader quality problems in your code and may lead to unpredictable behavior across different browsers.
A common cause of this error is dynamic value generation — for example, a CSS calc() expression or a preprocessor variable that inadvertently produces a negative result. If your stroke width is computed, make sure to clamp the value so it never goes below 0.
How to fix it
- Replace negative values with
0or a positive number. If you intended no visible stroke, use0. If you wanted a visible stroke, use the appropriate positive thickness. - Guard computed values. If the value comes from a
calc()expression or CSS custom property, usemax()to ensure the result is never negative — for example,stroke-width: max(0px, calc(10px - 15px)). - Check inline styles and stylesheets. The error can appear in both inline
styleattributes and external/internal CSS. Search your codebase for anystroke-widthdeclaration with a negative number.
Examples
❌ Invalid: negative stroke-width on an HTML element
<pstyle="stroke-width: -1">Some content</p>
This triggers the validator error because -1 is not an allowed value.
✅ Fixed: non-negative stroke-width
<pstyle="stroke-width: 0">Some content</p>
Using 0 removes the stroke entirely and is valid.
❌ Invalid: negative stroke-width on an SVG element
<svgwidth="100"height="100"xmlns="http://www.w3.org/2000/svg">
<circlecx="50"cy="50"r="40"stroke="black"stroke-width="-3"fill="none"/>
</svg>
✅ Fixed: positive stroke-width on an SVG element
<svgwidth="100"height="100"xmlns="http://www.w3.org/2000/svg">
<circlecx="50"cy="50"r="40"stroke="black"stroke-width="3"fill="none"/>
</svg>
✅ Using max() to clamp a computed value
<divstyle="stroke-width:max(0px,calc(5px-10px))">Some content</div>
Here, calc(5px - 10px) would produce -5px, but max(0px, ...) ensures the final value is 0px, keeping the CSS valid.
The text-align CSS property controls horizontal alignment of inline-level content within a block element. When the W3C HTML validator encounters an inline style attribute containing a text-align value it doesn't recognize, it flags the error with a message like CSS: "text-align": X is not a "text-align" value, where X is the offending value.
This error commonly occurs for a few reasons:
- Confusing
text-alignwithvertical-align: Usingmiddle,top, orbottom— these arevertical-alignvalues, nottext-alignvalues. - Typos: Writing
cetnerinstead ofcenter, orrigthinstead ofright. - Using non-standard values: Trying values like
auto,none, or arbitrary strings that aren't part of the specification. - Confusing CSS properties: Using Flexbox or Grid alignment values like
flex-startorspace-betweenwithtext-align.
While most browsers will silently ignore an invalid text-align value and fall back to the inherited or default alignment, relying on this behavior is problematic. It makes your intent unclear, can lead to inconsistent rendering, and signals that there may be a deeper misunderstanding in your styling approach. Valid CSS ensures predictable behavior across all browsers and assistive technologies.
Valid values for text-align
| Value | Description |
|---|---|
left | Aligns content to the left edge |
right | Aligns content to the right edge |
center | Centers the content horizontally |
justify | Stretches content to fill the full width |
start | Aligns to the start edge (direction-aware) |
end | Aligns to the end edge (direction-aware) |
The start and end values are logical properties that respect the document's writing direction (dir attribute or direction CSS property), making them ideal for internationalized content.
Examples
Invalid: using middle instead of center
A common mistake is using middle, which is a valid value for vertical-align but not for text-align:
<pstyle="text-align: middle;">This text will fail validation.</p>
Fix: Replace middle with center:
<pstyle="text-align: center;">This text is properly centered.</p>
Invalid: typo in the value
<h2style="text-align: cetner;">Heading</h2>
Fix: Correct the spelling:
<h2style="text-align: center;">Heading</h2>
Invalid: using a non-existent value
<divstyle="text-align: auto;">Some content</div>
Fix: Choose a valid alignment value:
<divstyle="text-align: left;">Some content</div>
Invalid: using a vertical alignment value
<pstyle="text-align: top;">Paragraph text</p>
Fix: If you intended horizontal alignment, use a valid text-align value. If you actually need vertical positioning, use vertical-align on an inline or table-cell element instead:
<pstyle="text-align: left;">Paragraph text</p>
Valid examples showing all common values
<pstyle="text-align: left;">Left-aligned text.</p>
<pstyle="text-align: right;">Right-aligned text.</p>
<pstyle="text-align: center;">Centered text.</p>
<pstyle="text-align: justify;">Justified text stretches to fill the full width of its container.</p>
<pstyle="text-align: start;">Start-aligned (respects text direction).</p>
<pstyle="text-align: end;">End-aligned (respects text direction).</p>
When fixing this error, double-check which property you actually need. If you want to center a block-level element itself (not its text content), text-align isn't the right tool — consider using margin: 0 auto or Flexbox instead. The text-align property is specifically for the horizontal alignment of inline content within its containing block.
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.
A percentage value in your CSS exceeds the allowed range of 0 to 100.
CSS properties that accept percentage values — such as opacity, width, height, and others used in certain contexts — may be restricted to specific ranges. When you embed CSS in an HTML document (via the style attribute or a <style> element), the W3C HTML Validator checks these values and flags any that fall outside the permitted range.
A value like 100.01% is just slightly over the maximum of 100%. This is often a typo or a rounding error. While most browsers will silently clamp the value to 100%, it is still invalid and should be corrected.
HTML Examples
❌ Invalid: value out of range
<divstyle="width:100.01%;">Content</div>
✅ Fixed: value within range
<divstyle="width:100%;">Content</div>
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.
In CSS, most numeric values of 0 don't need a unit — for example, margin: 0 is perfectly valid because the specification allows unitless zero for <length> values. However, this exception does not apply to <time> values. Properties that accept <time> values, such as transition-delay, transition-duration, animation-delay, and animation-duration, always require a unit (s for seconds or ms for milliseconds), even when the value is zero.
The CSS specification explicitly states that <time> values must include a unit. The unitless 0 shorthand is only permitted for <length> and a few other value types. While some browsers may silently accept transition-delay: 0 and treat it as 0s, this behavior is non-standard and not guaranteed across all browsers or future implementations. Relying on it can lead to inconsistent rendering and will fail W3C CSS validation.
This issue commonly appears when transition-delay is set as part of the transition shorthand, or when developers assume that 0 is universally valid without a unit in CSS.
How to fix it
Add the s (seconds) or ms (milliseconds) unit to any <time> value that is currently a bare 0:
0→0sor0ms- Check both longhand properties (
transition-delay,transition-duration) and thetransitionshorthand.
Examples
Incorrect — unitless zero
<style>
.fade{
transition-delay:0;
transition-duration:0.3s;
transition-property: opacity;
}
</style>
<divclass="fade">Hello</div>
The validator reports: CSS: "transition-delay": "0" is not a "transition-delay" value.
Correct — with time unit
<style>
.fade{
transition-delay:0s;
transition-duration:0.3s;
transition-property: opacity;
}
</style>
<divclass="fade">Hello</div>
Incorrect — unitless zero in the transition shorthand
<style>
.btn{
transition: background-color 0.2s ease 0;
}
</style>
<buttonclass="btn">Click me</button>
The fourth value in the transition shorthand is the delay, and 0 without a unit is invalid.
Correct — shorthand with time unit
<style>
.btn{
transition: background-color 0.2s ease 0s;
}
</style>
<buttonclass="btn">Click me</button>
Multiple transitions
When specifying delays for multiple properties, ensure every <time> value has a unit:
<style>
.card{
transition-property: opacity, transform;
transition-duration:0.3s,0.5s;
transition-delay:0s,0.1s;
}
</style>
<divclass="card">Content</div>
The same rule applies to transition-duration and the animation-delay and animation-duration properties — always include s or ms, even for zero values.
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.
CSS distinguishes between pseudo-classes and pseudo-elements using different colon syntax. Pseudo-classes like :hover, :focus, and :active describe a temporary state of an element and use a single colon (:). Pseudo-elements like ::before, ::after, and ::first-line target a specific part of an element's rendering and use double colons (::). Writing ::hover conflates these two concepts — there is no pseudo-element called hover in any CSS specification.
This matters for several reasons. First, most browsers will silently ignore the invalid ::hover rule entirely, meaning your hover styles simply won't apply. Users will see no visual feedback when hovering over interactive elements like links and buttons, which hurts usability. Second, the lack of hover feedback can be an accessibility concern — sighted users rely on hover states to identify clickable elements. Third, invalid CSS can cause unpredictable behavior across different browsers and versions, making your site harder to maintain.
The confusion often arises because CSS2 originally allowed single colons for pseudo-elements (e.g., :before), and CSS3 introduced the double-colon syntax to clearly separate pseudo-elements from pseudo-classes. This means you might see both :before and ::before in the wild, which can make it tempting to assume that double colons work everywhere. The key rule to remember: states use one colon (:hover, :focus, :visited), and sub-element targets use two colons (::before, ::after, ::placeholder).
Examples
Incorrect: using double colons with hover
a::hover{
color: red;
}
button::hover{
background-color: blue;
}
Both rules above will trigger the validation error and will likely be ignored by browsers.
Correct: using a single colon with hover
a:hover{
color: red;
}
button:hover{
background-color: blue;
}
Correct usage of pseudo-classes vs. pseudo-elements
This example demonstrates how single-colon pseudo-classes and double-colon pseudo-elements are used together correctly:
a:hover{
color: red;
}
a:focus{
outline:2px solid blue;
}
a::before{
content:"→ ";
}
Full HTML document with valid :hover usage
<!DOCTYPE html>
<htmllang="en">
<head>
<title>Hover Example</title>
<style>
a:hover{
color: red;
text-decoration: underline;
}
</style>
</head>
<body>
<ahref="#">Hover over this link</a>
</body>
</html>
Quick Reference
| Type | Syntax | Examples |
|---|---|---|
| Pseudo-class (state) | Single colon : | :hover, :focus, :active, :visited, :first-child |
| Pseudo-element (sub-part) | Double colon :: | ::before, ::after, ::first-line, ::placeholder |
If you encounter this validation error, search your stylesheets for ::hover and replace every instance with :hover. The same fix applies if you accidentally use double colons with other pseudo-classes like ::focus or ::active.
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