HTML Guides for background
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 background-attachment property only accepts scroll, fixed and local, so the validator reports any other value, such as static, none or auto.
static is the default of position, not of background-attachment. The default here is scroll, which ties the background to the element itself: it moves with the page, but not with content that scrolls inside the element. fixed pins the background to the viewport, and local makes it scroll along with the element's own content.
Browsers ignore the invalid declaration, so the background falls back to scroll, or to whatever an earlier rule set. If you wrote static to cancel a fixed background, the background stays fixed until you change the value to scroll.
With several background layers, the property takes a comma-separated list such as scroll, fixed. One bad keyword in the list is enough to trigger the error, and the browser then drops the whole declaration. In the background shorthand the same mistake produces a different message: “background”: “static” is not a “background-color” value.
Invalid example
.hero {
background-image: url("hero.jpg");
background-attachment: static;
}
Valid example
.hero {
background-image: url("hero.jpg");
background-attachment: scroll;
}
The background CSS property accepts a variety of value types: named colors (red, blue), hexadecimal codes (#fff, #ff0000), color functions (rgb(), hsl(), rgba()), gradient functions (linear-gradient(), radial-gradient()), image URLs, and CSS keywords like none, transparent, or inherit. The word from is not among these valid values.
Why this happens
This error most commonly appears in one of these scenarios:
Legacy WebKit gradient syntax. Older versions of Safari and Chrome used a proprietary syntax:
-webkit-gradient(linear, left top, right top, from(#fff), to(#000)). Thefrom()andto()functions are part of this deprecated, non-standard format. If this syntax is used without the-webkit-prefix—or if the validator encounters it—the wordfromgets flagged as an invalid color value.Incorrectly written gradient shorthand. Some developers unfamiliar with the CSS gradient specification write something resembling natural language, like
background: from #fff to #000, which has no meaning in CSS.CSS
fromkeyword in relative color syntax. CSS Color Level 5 introduces relative color syntax using thefromkeyword (e.g.,rgb(from red r g b / 50%)). This is a newer feature that may not yet be recognized by the W3C CSS validator, which can lag behind the latest specifications. If you're using this syntax intentionally, the error may be a false positive from the validator, but be aware that browser support may still be limited.
Why it matters
Invalid CSS values are silently ignored by browsers, meaning your intended background styling won't be applied. The element will fall back to its default or inherited background, which can result in broken layouts, missing visual cues, or poor contrast that harms readability and accessibility. Using standard, valid CSS ensures consistent rendering across all browsers.
How to fix it
- Replace legacy
-webkit-gradient()syntax with the standardlinear-gradient()orradial-gradient()functions. - Use valid color formats for solid backgrounds: hex codes, named colors, or color functions.
- If using relative color syntax (
fromkeyword in CSS Color Level 5), understand that the validator may not yet support it. Consider adding a fallback value for broader compatibility.
Examples
Incorrect: legacy WebKit gradient syntax
The from() and to() functions in -webkit-gradient() are non-standard and will trigger this error if used as a background value:
<style>
.banner {
/* Non-standard syntax; "from" is not a valid CSS value */
background: -webkit-gradient(linear, left top, right top, from(#fff), to(#000));
}
</style>
<div class="banner">Legacy gradient</div>
Incorrect: made-up gradient shorthand
Writing gradient-like syntax without a proper CSS function is invalid:
<style>
.banner {
/* "from" and "to" are not valid CSS keywords here */
background: from #fff to #000;
}
</style>
<div class="banner">Invalid gradient</div>
Correct: standard linear gradient
Use linear-gradient() with a direction and comma-separated color stops:
<style>
.banner {
background: linear-gradient(to right, #fff, #000);
}
</style>
<div class="banner">Standard gradient</div>
Correct: solid color background
For a simple solid color, use any valid CSS color value:
<style>
.banner {
background: #fff;
}
</style>
<div class="banner">White background</div>
Correct: gradient with a fallback for older browsers
When using gradients, it's good practice to provide a solid color fallback:
<style>
.banner {
background: #fff;
background: linear-gradient(to bottom, #ffffff, #cccccc);
}
</style>
<div class="banner">Gradient with fallback</div>
Correct: relative color syntax with a fallback
If you intentionally use CSS Color Level 5 relative color syntax and the validator flags from, provide a fallback and be aware of current browser support:
<style>
.banner {
background: rgb(255, 0, 0);
background: rgb(from red r g b / 50%);
}
</style>
<div class="banner">Relative color with fallback</div>
Always verify that your background values use standard CSS syntax. When in doubt, test your styles in the W3C CSS Validator and check browser support on Can I Use.
A position in the background shorthand is a plain number like 10, and CSS only accepts a number without a unit when it is 0.
In background: url(banner.png) no-repeat 10 20, the two numbers set background-position, which takes lengths such as 10px or 1.5em, percentages, or keywords like left and center. CSS has no default unit, so 10 alone is not a length. Browsers ignore the whole declaration, and the element loses its background color and image along with the position.
The bare number often comes from a template or CMS setting that prints an offset without px, or from a value copied out of a design tool. Add the unit you meant, or switch to a percentage or keyword. 0 is the one number that is valid on its own, because zero is the same length in every unit.
The validator words two close cases differently. A unitless size after the slash, as in center / 100 auto, is reported as a "unit" error instead of a "length" one. A unitless number that comes second, after a valid first position such as 10px 20, is reported as not being a background value. Adding the unit fixes both.
Invalid example
<div style="background: url(banner.png) no-repeat 10 20;">
<p>Summer sale</p>
</div>
Valid example
<div style="background: url(banner.png) no-repeat 10px 20px;">
<p>Summer sale</p>
</div>
The background-size property only accepts auto, cover, contain, or one or two lengths or percentages, so the validator reports any other value, such as default, none or fill.
default is a value of cursor, not of background-size. The default here is auto, which draws the image at its natural size. cover scales the image until it fills the whole element, cropping whatever overflows, and contain scales it until it fits entirely inside. Two values set the width and the height separately, for example 100% auto. The CSS-wide keywords initial, inherit, unset and revert are also accepted.
Browsers ignore the invalid declaration, so the image keeps the size an earlier rule gave it, or auto if no rule did. If you wrote default to undo a cover set elsewhere, the image stays scaled to cover the element until you change the value to auto.
With several background layers, the property takes a comma-separated list such as cover, auto, one size per layer. A bad keyword anywhere in the list, or in either half of a two-value pair, is enough to trigger the error, and the browser then drops the whole declaration. In the background shorthand, where the size goes after the position and a slash, the same mistake produces a different message: “background”: “default” is not a “background” value.
Invalid example
.hero {
background-image: url("hero.jpg");
background-size: cover;
}
.hero.compact {
background-size: default;
}
Valid example
.hero {
background-image: url("hero.jpg");
background-size: cover;
}
.hero.compact {
background-size: auto;
}
The linear-gradient() function went through several syntax revisions during CSS standardization. Early drafts and vendor-prefixed implementations (like -webkit-linear-gradient()) used bare direction keywords such as top, bottom left, etc., where the keyword indicated the starting point of the gradient. The final standard, defined in the CSS Images Module Level 3 and Level 4 specifications, changed this so that direction keywords use the to prefix and indicate the ending point of the gradient. For example, the old linear-gradient(top, #fff, #000) meant "start at the top and go to the bottom," while the correct modern equivalent is linear-gradient(to bottom, #fff, #000).
This matters because the old syntax without to is not valid CSS per the current specification. While some browsers may still interpret the legacy syntax for backward compatibility, relying on it is risky — behavior can vary across browsers, and it will trigger validation errors. Using standard-compliant CSS ensures consistent rendering and forward compatibility.
How to fix it
Replace the bare direction keyword with the correct to syntax. Note that the direction meaning is inverted: the old syntax specified where the gradient starts, while the new syntax specifies where it goes to.
Here's a quick mapping from old to new syntax:
| Old (invalid) | New (valid) | Angle equivalent |
|---|---|---|
top | to bottom | 180deg |
bottom | to top | 0deg |
left | to right | 90deg |
right | to left | 270deg |
top left | to bottom right | N/A (use to syntax) |
Important: Notice that top in the old syntax means "start at top, go to bottom." So the modern equivalent is to bottom, not to top. If the validator message says the argument should be to top, it means you wrote top — but be sure you understand which direction your gradient should actually go before blindly replacing it. If you truly want the gradient to go toward the top, use to top. If you want it to go from the top downward, use to bottom.
If you don't specify a direction at all, linear-gradient() defaults to to bottom (top-to-bottom), which is often what you want.
Examples
Invalid: bare direction keyword
<div style="background: linear-gradient(top, #ffffff, #000000);">
Content
</div>
The bare keyword top is not valid in the standard linear-gradient() syntax and will trigger the validator error.
Fixed: using the to keyword
<div style="background: linear-gradient(to bottom, #ffffff, #000000);">
Content
</div>
Since the old top meant "start at the top," the equivalent standard syntax is to bottom.
Fixed: using an angle
<div style="background: linear-gradient(180deg, #ffffff, #000000);">
Content
</div>
An angle of 180deg produces the same top-to-bottom gradient.
Full document example
<!DOCTYPE html>
<html lang="en">
<head>
<title>Gradient Example</title>
<style>
.box {
width: 200px;
height: 100px;
/* Valid: direction keyword with "to" */
background: linear-gradient(to top, #ffffff, #000000);
}
.box-angle {
width: 200px;
height: 100px;
/* Valid: angle equivalent of "to top" */
background: linear-gradient(0deg, #ffffff, #000000);
}
.box-default {
width: 200px;
height: 100px;
/* Valid: no direction specified, defaults to "to bottom" */
background: linear-gradient(#ffffff, #000000);
}
</style>
</head>
<body>
<div class="box"></div>
<div class="box-angle"></div>
<div class="box-default"></div>
</body>
</html>
All three approaches are valid. Choose whichever is clearest for your use case — the to keyword syntax is generally the most readable, while angles offer more precision for diagonal or non-cardinal directions.
A background value has a comma or slash where the shorthand doesn't allow one, and the usual cause is a gradient whose color stops have positions but no colors.
Each color stop in linear-gradient() or radial-gradient() is a color followed by an optional position, such as #0d47a1 0%. When a theme setting or template variable that should print the color comes out empty, the generated CSS reads linear-gradient(90deg, 0%, 100%). With no colors left, the commas don't separate color stops anymore, and the validator reports , as an incorrect operator. Browsers ignore the whole declaration, so the element gets no background from that rule.
The message can also name /. In the background shorthand, a slash only goes between a position and a size, as in center / cover. Writing url(photo.jpg) / cover or no-repeat / cover, with no position before the slash, triggers the same error.
When the CSS comes from a template, look at the output rather than the source: fill in the missing colors, or skip the gradient when no colors are set.
Invalid example
<div style="background: linear-gradient(90deg, 0%, 100%);">
<p>Banner text</p>
</div>
Valid example
<div style="background: linear-gradient(90deg, #0d47a1 0%, #42a5f5 100%);">
<p>Banner text</p>
</div>
The url() in a background value starts with a scheme the CSS validator doesn't recognize, so it can't read the value as a URL.
The validator accepts relative paths such as images/arrow.png or /images/arrow.png, and absolute URLs with common schemes such as https: and data:. It treats everything before the first colon as the scheme, and if it doesn't know that scheme, it reports the whole url() as incorrect. Quotes don't change this: url("myapp://icons/arrow.png") gets the same error.
The usual cause is a placeholder that a build tool or CMS was supposed to replace with a real path, such as url(myapp://icons/arrow.png). A browser can't resolve that scheme either, so the image never loads. Local file paths cause it too: in url(C:/images/arrow.png), the validator takes the drive letter C as the scheme, and visitors' browsers couldn't open a file on your disk anyway.
Look at the CSS the browser receives, not the template. Point url() at the file's real location with a relative path or a full https:// URL, and fix the step that should have replaced the placeholder.
Invalid example
<div style="background: #f5f5f5 url(myapp://icons/arrow.png) no-repeat right center;">
<p>Next page</p>
</div>
Valid example
<div style="background: #f5f5f5 url(/images/arrow.png) no-repeat right center;">
<p>Next page</p>
</div>
The background CSS property is a shorthand that can accept values for background-color, background-image, background-position, background-size, background-repeat, background-origin, background-clip, and background-attachment. When the validator encounters an unrecognized value, it tries to match it against individual sub-properties like background-color. If the value doesn't match any of them, you'll see this error.
Common causes include typos in color names (e.g., bleu instead of blue), malformed hex codes (e.g., #gggggg or a missing #), incorrect function syntax (e.g., rgb(255 0 0 with a missing parenthesis), or using values that simply don't exist in CSS. This error can also appear when a CSS custom property (variable) is used in inline styles and the validator can't resolve it, or when a browser-specific value is used that isn't part of the CSS specification.
Fixing this issue ensures your styles render predictably across browsers. While browsers are often forgiving and may ignore invalid declarations silently, relying on that behavior can lead to inconsistent rendering. Standards-compliant CSS is easier to maintain and debug.
How to Fix
- Check for typos in color names, hex codes, or function syntax.
- Verify the value format — hex colors need a
#prefix,rgb()andrgba()need proper comma-separated or space-separated values with closing parentheses. - Use
background-colorinstead of the shorthandbackgroundif you only intend to set a color. This makes your intent clearer and reduces the chance of conflicting shorthand values. - Remove vendor-prefixed or non-standard values that the validator doesn't recognize.
Examples
Incorrect — Typo in color name
<div style="background: aquaa;">Content</div>
aquaa is not a valid CSS color name, so the validator rejects it.
Correct — Valid color name
<div style="background: aqua;">Content</div>
Incorrect — Malformed hex code
<div style="background: #xyz123;">Content</div>
Hex color codes only allow characters 0–9 and a–f.
Correct — Valid hex code
<div style="background: #00a123;">Content</div>
Incorrect — Missing hash symbol
<div style="background: ff0000;">Content</div>
Without the #, the validator interprets ff0000 as an unknown keyword.
Correct — Hex code with hash
<div style="background: #ff0000;">Content</div>
Incorrect — Broken rgb() syntax
<div style="background: rgb(255, 0, 300);">Content</div>
RGB channel values must be between 0 and 255 (or 0% to 100%).
Correct — Valid rgb() value
<div style="background: rgb(255, 0, 128);">Content</div>
Correct — Using background-color for clarity
When you only need to set a color, prefer the specific background-color property over the shorthand:
<div style="background-color: rgba(255, 0, 0, 0.5);">Semi-transparent red</div>
Correct — Valid shorthand with image and other properties
<div style="background: url('image.jpg') no-repeat center / cover;">Content</div>
Note the / between background-position (center) and background-size (cover) — this is required syntax in the shorthand.
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.
1K Weekly
1,000 monthly checks. Cancel anytime.
Get 1K Weekly →Join teams across 40+ countries