HTML Guides for css
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
A <style> element in the <body> comes after other content inside its parent, but the HTML standard only allows it there as the parent's first child.
Since October 2026, a <style> element can sit in the <body> as long as its styles can't reach anything earlier in the page. Its style rules go inside an @scope block, which limits them to the parent of the <style> and everything inside it. Putting the <style> first in that parent means the browser has the styles before it renders any of the content they apply to.
Whitespace and comments before the <style> don't count, so indenting it or adding a comment above it is fine. Any element or text before it triggers the error, including a heading, a <link>, a <script> or another <style>. A <style> at the end of a container, or at the end of the <body>, breaks the rule as well. When two <style> elements sit next to each other, the second one is reported, so merge their rules into a single element.
To fix the error, move the <style> element up so it's the first thing inside its parent. An @scope block without a selector still applies to the same parent, so the styles keep matching the same elements. If the parent has to start with something else, such as a heading, wrap the content the styles target in a new element and put the <style> at the top of it. The scope then becomes that wrapper. Styles meant for the whole page belong in the <head>.
Invalid example
<div class="card">
<p>Card content</p>
<style>
@scope {
p {
color: darkslategray;
}
}
</style>
</div>
Valid example
<div class="card">
<style>
@scope {
p {
color: darkslategray;
}
}
</style>
<p>Card content</p>
</div>
The <table> element in HTML supports a limited set of attributes — primarily global attributes like class, id, and style. The height attribute was never part of the HTML standard for tables (unlike width, which was valid in HTML 4 but has since been deprecated). Despite this, many browsers historically accepted height on <table> as a non-standard extension, which led to its widespread but incorrect use.
Because height is not a recognized attribute on <table>, using it means your markup is invalid and may behave inconsistently across browsers. Some browsers might honor it, others might ignore it entirely, and future browser versions could change their behavior at any time. Relying on non-standard attributes makes your code fragile and harder to maintain.
The fix is straightforward: remove the height attribute from the <table> element and use CSS to set the desired height. You can apply the CSS inline via the style attribute, or better yet, use an external or internal stylesheet with a class or ID selector.
Examples
❌ Invalid: height attribute on <table>
<table height="300">
<tr>
<td>Name</td>
<td>Score</td>
</tr>
<tr>
<td>Alice</td>
<td>95</td>
</tr>
</table>
This triggers the validator error: Attribute "height" not allowed on element "table" at this point.
✅ Fixed: Using inline CSS
<table style="height: 300px;">
<tr>
<td>Name</td>
<td>Score</td>
</tr>
<tr>
<td>Alice</td>
<td>95</td>
</tr>
</table>
✅ Fixed: Using a CSS class (preferred)
<style>
.tall-table {
height: 300px;
}
</style>
<table class="tall-table">
<tr>
<td>Name</td>
<td>Score</td>
</tr>
<tr>
<td>Alice</td>
<td>95</td>
</tr>
</table>
Using a class keeps your HTML clean and makes it easy to adjust the styling later without touching the markup. Note that min-height is often a better choice than height for tables, since table content can naturally grow beyond a fixed height, and min-height ensures the table is at least a certain size without clipping content.
The device-width and device-height media features (along with their min- and max- prefixed variants) originally referred to the physical dimensions of the device's entire screen, regardless of how much space was actually available to the document. In practice, this distinction caused confusion and inconsistent behavior across browsers. On most modern devices and browsers, device-width and width return the same value anyway, making the device-* variants redundant.
The device-* media features were frequently used as a proxy to detect mobile devices, but this was never a reliable approach. A narrow browser window on a desktop monitor would not trigger a max-device-width query even though the available layout space was small. Conversely, modern phones and tablets with high-resolution screens can report large device widths that don't reflect the actual CSS viewport size. The viewport-based alternatives (width, height, aspect-ratio) more accurately represent the space available for rendering your content.
Using deprecated media features causes W3C validation warnings and may eventually lose browser support entirely. Replacing them ensures your stylesheets are future-proof, standards-compliant, and behave consistently across all devices and window sizes.
How to fix it
Replace any device-width, device-height, or device-aspect-ratio media feature (including min- and max- prefixed versions) with the corresponding viewport-based equivalent:
| Deprecated feature | Replacement |
|---|---|
device-width | width |
min-device-width | min-width |
max-device-width | max-width |
device-height | height |
min-device-height | min-height |
max-device-height | max-height |
device-aspect-ratio | aspect-ratio |
The width media feature describes the width of the viewport (the targeted display area of the output device), including the size of a rendered scroll bar if any. This is the value you almost always want when writing responsive styles.
Examples
Incorrect: using deprecated max-device-width
This triggers the validation error because max-device-width is deprecated:
<link rel="stylesheet" media="only screen and (max-device-width: 768px)" href="mobile.css">
Correct: using max-width instead
Replace max-device-width with max-width to query the viewport width:
<link rel="stylesheet" media="only screen and (max-width: 768px)" href="mobile.css">
Incorrect: using deprecated min-device-width in a range
<link rel="stylesheet" media="screen and (min-device-width: 768px) and (max-device-width: 1024px)" href="tablet.css">
Correct: using viewport-based equivalents
<link rel="stylesheet" media="screen and (min-width: 768px) and (max-width: 1024px)" href="tablet.css">
Incorrect: using deprecated device-aspect-ratio
<link rel="stylesheet" media="screen and (device-aspect-ratio: 16/9)" href="widescreen.css">
Correct: using aspect-ratio
<link rel="stylesheet" media="screen and (aspect-ratio: 16/9)" href="widescreen.css">
Applying the same fix in CSS @media rules
The same deprecation applies to @media rules inside stylesheets. While the W3C validator specifically flags the media attribute on <link> elements, you should update your CSS as well:
/* Deprecated */
@media only screen and (max-device-width: 768px) {
.sidebar { display: none; }
}
/* Correct */
@media only screen and (max-width: 768px) {
.sidebar { display: none; }
}
If your site relies on a <meta name="viewport"> tag (as most responsive sites do), the viewport width already matches the device's CSS pixel width, so switching from device-width to width will produce identical results in virtually all cases.
The device-width, device-height, and device-aspect-ratio media features (including their min- and max- prefixed variants) refer to the physical dimensions of the entire screen, not the available space where your content is actually rendered. This distinction matters because the viewport size — the area your page occupies — can differ significantly from the full device screen size. For example, a browser window might not be maximized, or browser chrome might consume screen real estate. Using device-based queries means your responsive breakpoints may not match what users actually see.
These features were also commonly used as a proxy for detecting mobile devices, but this approach is unreliable. A small-screened laptop and a large tablet can have similar device widths, making device-based detection a poor heuristic. The W3C deprecated these features and recommends using viewport-based alternatives that more accurately reflect the rendering context of your document.
Beyond standards compliance, using deprecated media features can cause issues with future browser support. While current browsers still recognize them, there is no guarantee they will continue to do so. Replacing them now ensures your stylesheets remain functional and forward-compatible.
How to fix it
Replace each deprecated device-* media feature with its viewport-based equivalent:
| Deprecated feature | Replacement |
|---|---|
device-width | width |
min-device-width | min-width |
max-device-width | max-width |
device-height | height |
min-device-height | min-height |
max-device-height | max-height |
device-aspect-ratio | aspect-ratio |
min-device-aspect-ratio | min-aspect-ratio |
max-device-aspect-ratio | max-aspect-ratio |
The width media feature describes the width of the targeted display area of the output device. For continuous media, this is the width of the viewport including the size of a rendered scroll bar (if any). This is almost always the value you actually want when building responsive layouts.
Examples
Incorrect: using deprecated min-device-width
This triggers the validation error because min-device-width is deprecated:
<link rel="stylesheet" media="only screen and (min-device-width: 768px)" href="tablet.css">
Correct: using min-width instead
Replace min-device-width with min-width to query the viewport width:
<link rel="stylesheet" media="only screen and (min-width: 768px)" href="tablet.css">
Incorrect: using max-device-width for a mobile breakpoint
<link rel="stylesheet" media="screen and (max-device-width: 480px)" href="mobile.css">
Correct: using max-width
<link rel="stylesheet" media="screen and (max-width: 480px)" href="mobile.css">
Incorrect: using device-aspect-ratio
<link rel="stylesheet" media="screen and (device-aspect-ratio: 16/9)" href="widescreen.css">
Correct: using aspect-ratio
<link rel="stylesheet" media="screen and (aspect-ratio: 16/9)" href="widescreen.css">
Incorrect: combining multiple deprecated features
<link rel="stylesheet" media="screen and (min-device-width: 768px) and (max-device-width: 1024px)" href="tablet.css">
Correct: using viewport-based equivalents
<link rel="stylesheet" media="screen and (min-width: 768px) and (max-width: 1024px)" href="tablet.css">
The same replacements apply when these deprecated features appear in CSS @media rules or in the media attribute on <style> and <source> elements. Updating them across your entire codebase ensures consistent, standards-compliant responsive behavior.
The sizes attribute works together with srcset to help the browser choose the most appropriate image source for the current layout. It accepts a comma-separated list of entries, where each entry is an optional media condition followed by a CSS length value (called a "source size value"). The browser evaluates these entries to determine the intended display width of the image before it downloads it. Valid length values include viewport-relative units like 100vw, absolute units like 472px, or calc() expressions like calc(100vw - 2rem).
The value auto was not part of the original HTML specification for the sizes attribute. However, the sizes="auto" value has been added to the HTML living standard specifically for use with lazy-loaded images (loading="lazy"). When both loading="lazy" and sizes="auto" are present, the browser can defer size calculation until layout time, since the image won't be fetched immediately anyway. Some validators may not yet recognize this newer addition, or the error may appear because auto is being used without loading="lazy", or combined incorrectly with other size entries like sizes="auto, 100vw".
This validation error matters for several reasons. First, if the browser doesn't understand the sizes value, it may fall back to a default of 100vw, which could cause it to download a larger image than necessary, hurting performance. Second, malformed attribute values can lead to unpredictable behavior across different browsers. Third, standards compliance ensures your markup works reliably now and in the future.
How to Fix
You have a few options depending on your situation:
Replace
autowith a valid CSS length. If you know the intended display size of the image, specify it directly. This is the most broadly compatible approach.Use
sizes="auto"only withloading="lazy". If you want the browser to automatically determine the size, ensure you also includeloading="lazy"and awidthattribute on the image. Note that some validators may still flag this until they update their rules.Remove
autofrom a comma-separated list. If you have something likesizes="auto, (max-width: 600px) 100vw, 50vw", remove theautoentry entirely.
Examples
Incorrect: Using auto without lazy loading
This triggers the validation error because auto is not a valid CSS length in the traditional sizes syntax.
<img
src="image.jpg"
srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1000w"
sizes="auto, 100vw"
alt="A scenic mountain landscape"
>
Fixed: Using a valid CSS length value
Replace auto with a concrete size or a set of media-conditioned sizes.
<img
src="image.jpg"
srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1000w"
sizes="(max-width: 472px) 100vw, 472px"
alt="A scenic mountain landscape"
>
In this example, when the viewport is 472 pixels wide or smaller, the image takes up the full viewport width (100vw). For wider viewports, the browser knows the image will display at 472px wide and selects the best source from srcset accordingly.
Fixed: Using auto with lazy loading
If you want the browser to determine the display size automatically, pair sizes="auto" with loading="lazy" and explicit dimensions.
<img
src="image.jpg"
srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1000w"
sizes="auto"
width="600"
height="400"
loading="lazy"
alt="A scenic mountain landscape"
>
The width and height attributes help the browser reserve the correct space in the layout, and loading="lazy" allows the browser to defer both loading and size calculation until the image is near the viewport.
Fixed: Using calc() for dynamic sizing
If your image sits inside a container with padding, you can use calc() for a precise size hint.
<img
src="image.jpg"
srcset="image-small.jpg 300w, image-medium.jpg 600w, image-large.jpg 1000w"
sizes="calc(100vw - 2rem)"
alt="A scenic mountain landscape"
>
The value of the sizes attribute on an <img> starts with a literal " character, which can't begin a media condition or a CSS length.
sizes holds a comma-separated list of source sizes. Each one is an optional media condition followed by a length, as in (max-width: 600px) 100vw, and the last one is usually a plain length such as 600px. Lazy-loaded images can also start the list with auto. The quotes around an attribute value are HTML syntax, not part of the value. When an extra " ends up inside it, the validator tries to read the entry as a length, finds the quote where it expects a digit or a minus sign, and rejects the value.
The stray quote usually comes from one of two mistakes. In the first, the quotes around the value were HTML-encoded as ", often by a plugin or template that escaped markup a second time. " can't delimit an attribute, so the parser reads sizes="(max-width: as an unquoted value that stops at the first space. The rest of the list turns into stray attributes such as 600px) and 100vw,, which the validator reports separately, and the bad value in this message is only the first word, such as "(max-width: or "auto,. In the second, the value is wrapped in two sets of quotes, as in sizes='"100vw"', and the whole list is the bad value.
Browsers drop a sizes value they can't parse and fall back to 100vw. They then pick the srcset candidate meant for a full-width layout, which is often a larger file than the image slot needs.
The cause rarely affects sizes alone. If width, height or srcset on the same <img> also report a stray ", fix the code that writes the tag instead of editing each attribute.
Invalid example
<img
src="logo-600.png"
alt="Company logo"
srcset="logo-600.png 600w, logo-1200.png 1200w"
sizes="(max-width: 600px) 100vw, 600px">
Valid example
<img
src="logo-600.png"
alt="Company logo"
srcset="logo-600.png 600w, logo-1200.png 1200w"
sizes="(max-width: 600px) 100vw, 600px">
The align-items property controls how flex or grid items are aligned along the cross axis of their container. While many CSS properties accept auto as a value, align-items is not one of them. The CSS specification defines a specific set of accepted values, and using auto will cause the declaration to be ignored by browsers, potentially breaking your intended layout.
This mistake often stems from confusion with the related property align-self, which does accept auto as its default value. When align-self is set to auto, it defers to the parent container's align-items value. However, align-items itself has no such delegation mechanism — it is the property that sets the default alignment for all items in the container.
The valid values for align-items include:
normal— behaves asstretchin flex containers and has context-dependent behavior in other layout modes.stretch— items are stretched to fill the container along the cross axis (the default behavior in flexbox).center— items are centered along the cross axis.flex-start/start— items are aligned to the start of the cross axis.flex-end/end— items are aligned to the end of the cross axis.baseline/first baseline/last baseline— items are aligned based on their text baselines.self-start/self-end— items are aligned based on their own writing mode.
If you intended the default behavior, use stretch (for flexbox) or normal. If you were trying to reset the property, use initial, unset, or revert instead of auto.
Examples
Incorrect: using auto as a value
<div style="display: flex; align-items: auto;">
<p>Item one</p>
<p>Item two</p>
</div>
This triggers the validation error because auto is not a recognized value for align-items.
Fixed: using stretch for default flexbox behavior
<div style="display: flex; align-items: stretch;">
<p>Item one</p>
<p>Item two</p>
</div>
Fixed: using center to center items
<div style="display: flex; align-items: center;">
<p>Item one</p>
<p>Item two</p>
</div>
Fixed: using flex-start to align items to the top
<div style="display: flex; align-items: flex-start;">
<p>Item one</p>
<p>Item two</p>
</div>
Correct use of auto with align-self
If your intention was to let a specific child item defer to its parent's alignment, use align-self: auto on the child element instead:
<div style="display: flex; align-items: center;">
<p>Centered item</p>
<p style="align-self: auto;">Also centered (defers to parent)</p>
<p style="align-self: flex-end;">Aligned to the end</p>
</div>
Here, align-self: auto is valid on individual items and tells them to inherit the align-items value from the container.
The validator rejects any align-self value it doesn't know, which catches typos and keywords from other properties, but also the valid anchor-center keyword.
align-self overrides the container's align-items for a single item. In flexbox it aligns the item on the cross axis, and in grid it aligns it inside its grid area. The validator accepts auto, normal, stretch, center, start, end, self-start, self-end, flex-start, flex-end and the baseline keywords (baseline, first baseline, last baseline), with an optional safe or unsafe before a position. Typical mistakes are middle for center, left or right (only justify-self takes those), and space-between, which belongs to align-content. Browsers drop a declaration with an unknown value, so the item falls back to whatever align-items says.
anchor-center is a different case. The CSS Anchor Positioning module adds it to align-self so an absolutely positioned element can center on its anchor, such as a tooltip under a button. The validator doesn't know the keyword yet and flags it even inside an @supports block. On an element that isn't absolutely positioned or has no default anchor, the spec says anchor-center behaves as center, so on an ordinary flex or grid item you can swap it for center without changing the layout.
If the element is anchor positioned and needs anchor-center, keep it and mute this message for that value.
Invalid example
<div style="display: flex; height: 160px;">
<p style="align-self: middle;">Caption</p>
<p style="align-self: anchor-center;">Price</p>
</div>
Valid example
<div style="display: flex; height: 160px;">
<p style="align-self: center;">Caption</p>
<p style="align-self: center;">Price</p>
</div>
The aspect-ratio CSS property defines the preferred width-to-height ratio of an element's box. Browsers use this ratio when calculating auto sizes and performing other layout functions, adjusting the element's dimensions to maintain the specified proportion even as the parent container or viewport changes size.
The ratio is expressed as <width> / <height>. If the slash and height portion are omitted, height defaults to 1. So aspect-ratio: 2 is equivalent to aspect-ratio: 2 / 1. The property also accepts the auto keyword, which tells the element to use its intrinsic aspect ratio (if it has one), and a combined form like auto 3 / 4, which prefers the intrinsic ratio but falls back to the specified one.
This validation error typically occurs for several reasons:
- Using invalid separators or syntax, such as a colon (
:) instead of a slash (/), e.g.,aspect-ratio: 16:9. - Providing units, such as
aspect-ratio: 16px / 9px. The values must be unitless positive numbers. - Using zero or negative numbers, which are not valid. Both parts of the ratio must be positive (
> 0). - Providing a string or unrecognized keyword, such as
aspect-ratio: wideoraspect-ratio: "16/9". - Missing spaces around the slash, though this is less common —
16/9may work in browsers but the canonical form uses spaces:16 / 9. - Using the property in inline
styleattributes validated against an older CSS level whereaspect-ratiowasn't yet recognized by the validator.
Getting this value right matters for layout consistency across browsers. An invalid value will be ignored entirely by the browser, meaning the element won't maintain any aspect ratio, potentially breaking your design. It's especially important for responsive images, video containers, and card layouts where maintaining proportions is critical.
Examples
Incorrect: using a colon as the separator
<div style="aspect-ratio: 16:9; width: 100%;"></div>
The colon syntax (common in video specifications) is not valid CSS. The validator will reject 16:9 as an aspect-ratio value.
Incorrect: using units in the ratio
<div style="aspect-ratio: 16px / 9px; width: 100%;"></div>
The ratio values must be unitless numbers. Adding px or any other unit makes the value invalid.
Incorrect: using zero in the ratio
<div style="aspect-ratio: 0 / 1; width: 100%;"></div>
Both numbers in the ratio must be strictly positive. Zero is not allowed.
Correct: standard ratio with a slash
<div style="aspect-ratio: 16 / 9; width: 100%;"></div>
Correct: single number (height defaults to 1)
<div style="aspect-ratio: 2; width: 100%;"></div>
This is equivalent to aspect-ratio: 2 / 1.
Correct: square ratio
<div style="aspect-ratio: 1 / 1; width: 100%;"></div>
Correct: using the auto keyword
<img src="photo.jpg" alt="A landscape photo" style="aspect-ratio: auto; width: 100%;">
The element uses its intrinsic aspect ratio if available.
Correct: combining auto with a fallback ratio
<img src="photo.jpg" alt="A landscape photo" style="aspect-ratio: auto 4 / 3; width: 100%;">
The browser prefers the image's intrinsic ratio, but if it hasn't loaded yet or has no intrinsic ratio, it falls back to 4 / 3. This is useful for preventing layout shift while images load.
Correct: using global CSS values
<div style="aspect-ratio: inherit; width: 100%;"></div>
Global values like inherit, initial, unset, revert, and revert-layer are also valid.
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;
}
When you write a hex color in CSS, the # symbol must be followed by exactly 3, 4, 6, or 8 hexadecimal digits (characters 0–9 and a–f). Writing background-color: #; or background-color: #; means the CSS parser encounters the statement-ending semicolon immediately after #, with no color data. The parser cannot interpret this as a valid token, so it throws a lexical error.
This commonly happens when:
- A color value is accidentally deleted or left as a placeholder during development.
- A template engine or CMS outputs an empty variable where a color value was expected (e.g.,
background-color: #{{ color }};wherecoloris empty). - A hex value is truncated, such as
#for#zz, containing an invalid number of digits or non-hex characters.
While most browsers will silently ignore the invalid declaration and fall back to the inherited or default background color, this creates unpredictable behavior. The element may render differently than intended, and the invalid CSS clutters your codebase. Fixing it ensures consistent rendering and standards compliance.
How to fix it
- Find the error location. The validator message includes the line and column number — go to that exact spot in your HTML or CSS file.
- Look at the
background-colorvalue. You'll likely see#followed immediately by;, or a#with an incomplete or invalid hex string. - Provide a valid color value. Replace the broken value with a proper hex code, a color keyword, or a functional notation like
rgb()orhsl().
If the color value comes from a dynamic source (like a CMS or JavaScript variable), add a fallback so an empty value doesn't produce invalid CSS.
Examples
❌ Incomplete hex value (triggers the error)
<div style="background-color: #;">
Hello
</div>
The # has no hex digits before the semicolon, causing the lexical error.
✅ Fixed with a valid hex color
<div style="background-color: #ffffff;">
Hello
</div>
❌ Truncated or invalid hex digits
<div style="background-color: #g3;">
Hello
</div>
The character g is not a valid hexadecimal digit, and two digits is not a valid hex color length.
✅ Fixed with a proper 3-digit shorthand hex color
<div style="background-color: #f0f;">
Hello
</div>
✅ Alternative valid color formats
Any of these are valid replacements for a broken hex value:
/* 6-digit hex */
background-color: #1a2b3c;
/* 3-digit shorthand hex */
background-color: #abc;
/* 8-digit hex with alpha */
background-color: #1a2b3cff;
/* Named color keyword */
background-color: white;
/* RGB functional notation */
background-color: rgb(255, 255, 255);
/* RGBA with transparency */
background-color: rgba(0, 0, 0, 0.5);
/* HSL functional notation */
background-color: hsl(210, 50%, 60%);
/* HSLA with transparency */
background-color: hsla(210, 50%, 60%, 0.8);
✅ Defensive approach for dynamic values
If a CMS or templating system inserts the color, consider providing a fallback so an empty value doesn't break your CSS:
<div style="background-color: #f0f0f0;">
Content with a safe default background
</div>
In your template logic, ensure empty color values either output a sensible default or omit the style attribute entirely rather than producing background-color: #;.
The background-color property accepts a specific set of color value types defined in the CSS Color specification. When you provide something that doesn't match any of these types — like a plain number, a misspelled keyword, or a malformed hex code — the validator flags it as an invalid value.
Common mistakes that trigger this error include:
- Bare numbers like
0or255— numbers alone aren't colors, even if you intended black or white. - Misspelled color keywords like
grreninstead ofgreen, ortrasparentinstead oftransparent. - Malformed hex codes like
#GGG,#12345, or missing the#prefix entirely. - Incorrect function syntax like
rgb(255 0 0 0.5)when mixing legacy comma syntax with modern space syntax improperly, or usingrgbawith only three arguments. - Invalid units or strings like
background-color: 10pxorbackground-color: "red"(color values should not be quoted).
While browsers are generally forgiving and will simply ignore an invalid background-color declaration, this means your intended styling silently fails. The element falls back to its inherited or default background, which can cause visual bugs, poor contrast, or accessibility issues that are hard to track down. Validating your CSS catches these problems early.
Valid color formats
The background-color property accepts these value types:
- Named keywords:
red,blue,transparent,currentcolor, etc. - Hex notation:
#rgb,#rrggbb,#rgba,#rrggbbaa - RGB/RGBA:
rgb(255, 0, 0)orrgb(255 0 0 / 0.5) - HSL/HSLA:
hsl(120, 100%, 50%)orhsl(120 100% 50% / 0.5) - The keyword
inherit,initial,unset, orrevert
Examples
Invalid: bare number as a color
A plain number like 0 is not a valid color value, even though black could be represented as all zeros in RGB.
<style>
.banner {
background-color: 0;
}
</style>
Invalid: misspelled keyword
<style>
.banner {
background-color: trasparent;
}
</style>
Invalid: quoted string
Color values must not be wrapped in quotes.
<style>
.banner {
background-color: "red";
}
</style>
Invalid: malformed hex code
Hex codes must be 3, 4, 6, or 8 characters after the #.
<style>
.banner {
background-color: #12345;
}
</style>
Fixed: using a named color keyword
<style>
.banner {
background-color: black;
}
</style>
Fixed: using a hex color
<style>
.banner {
background-color: #000000;
}
</style>
Fixed: using rgb() notation
<style>
.banner {
background-color: rgb(0, 0, 0);
}
</style>
Fixed: using rgba() for semi-transparency
<style>
.banner {
background-color: rgba(0, 0, 0, 0.5);
}
</style>
Fixed: using hsl() notation
<style>
.banner {
background-color: hsl(210, 50%, 40%);
}
</style>
Fixed: using transparent
<style>
.banner {
background-color: transparent;
}
</style>
When the CSS parser encounters a background-image value it cannot understand, it flags a parse error. This doesn't necessarily mean the browser won't render your styles — browsers are often more forgiving than validators — but it does indicate that your CSS doesn't conform to the specification. Invalid CSS can lead to unpredictable rendering across different browsers, makes your code harder to maintain, and may cause styles to silently fail in certain environments.
Common causes of this error include:
- Missing the
url()function around image paths. - Unquoted or improperly quoted URLs containing special characters like spaces or parentheses.
- Typos in CSS function names (e.g.,
lnear-gradientinstead oflinear-gradient). - Using vendor-prefixed values (e.g.,
-webkit-linear-gradient) in contexts where the validator expects standard CSS. - Invalid gradient syntax, such as missing color stops, incorrect angle units, or malformed function arguments.
- Using CSS custom properties (variables) or newer syntax in a
styleattribute, which the validator's CSS parser may not fully support.
To fix this, review the exact background-image declaration the validator is pointing to. Make sure all URLs are wrapped in url(), all gradients use correct function names and valid arguments, and all strings are properly quoted and closed.
Examples
Missing url() function
A bare file path without the url() wrapper is invalid:
<!-- ❌ Parse error: missing url() -->
<div style="background-image: /images/hero.jpg;"></div>
Wrap the path in url():
<!-- ✅ Correct -->
<div style="background-image: url('/images/hero.jpg');"></div>
Typo in gradient function name
<!-- ❌ Parse error: misspelled function -->
<div style="background-image: lnear-gradient(to right, red, blue);"></div>
<!-- ✅ Correct -->
<div style="background-image: linear-gradient(to right, red, blue);"></div>
Invalid gradient syntax
Missing color stops or using incorrect angle notation causes parse errors:
<!-- ❌ Parse error: invalid angle unit and missing second color stop -->
<div style="background-image: linear-gradient(45, red);"></div>
Angles need a unit (like deg), and gradients need at least two color stops:
<!-- ✅ Correct -->
<div style="background-image: linear-gradient(45deg, red, blue);"></div>
Unescaped special characters in URL
File paths with spaces or parentheses need to be quoted:
<!-- ❌ Parse error: unquoted URL with spaces -->
<div style="background-image: url(/images/my hero image.jpg);"></div>
<!-- ✅ Correct: quoted URL -->
<div style="background-image: url('/images/my hero image.jpg');"></div>
Vendor-prefixed values
Using non-standard prefixed syntax can trigger a parse error in the validator:
<!-- ❌ Parse error: vendor prefix not recognized by validator -->
<div style="background-image: -webkit-linear-gradient(left, red, blue);"></div>
Use the standard, unprefixed syntax instead. Modern browsers no longer need the prefix for gradients:
<!-- ✅ Correct: standard syntax -->
<div style="background-image: linear-gradient(to right, red, blue);"></div>
Multiple backgrounds with incorrect separator
Multiple background images must be separated by commas, not semicolons or spaces:
<!-- ❌ Parse error: wrong separator -->
<div style="background-image: url('a.png') url('b.png');"></div>
<!-- ✅ Correct: comma-separated -->
<div style="background-image: url('a.png'), url('b.png');"></div>
Moving styles to an external stylesheet
If the validator struggles with complex background-image values in inline style attributes, consider moving the CSS to a <style> block or external stylesheet, where the validator's CSS parser handles them more reliably:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Background Image Example</title>
<style>
.hero {
background-image: url('hero.jpg');
background-size: cover;
}
</style>
</head>
<body>
<div class="hero"></div>
</body>
</html>
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;
}
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 border-color property sets the color of an element's four borders. When the W3C validator reports that a given value "is not a border-color value," it means the value you provided doesn't match any recognized CSS color format. Common mistakes that trigger this error include using a bare number like 0 instead of a color, misspelling a color keyword (e.g., grren instead of green), forgetting the # prefix on a hex code, or passing an invalid argument to a color function.
This matters because browsers handle invalid CSS values unpredictably. When a browser encounters an unrecognized border-color value, it discards the entire declaration and falls back to the inherited or initial value (typically currentcolor). This can lead to inconsistent rendering across browsers and make your design behave in unexpected ways. Writing valid CSS ensures predictable, cross-browser results and keeps your stylesheets maintainable.
Valid color formats
The CSS border-color property accepts any valid <color> value, including:
- Named keywords —
red,blue,transparent,currentcolor, etc. - Hexadecimal —
#rgb,#rrggbb,#rgba,#rrggbbaa rgb()/rgba()—rgb(255, 0, 0)orrgb(255 0 0 / 50%)hsl()/hsla()—hsl(0, 100%, 50%)orhsl(0 100% 50% / 0.5)
You can also specify one to four color values to target individual sides (top, right, bottom, left), following the standard CSS shorthand pattern.
Examples
Invalid: bare number instead of a color
A number like 0 is not a valid color value and triggers the error:
<style>
.box {
border: 1px solid;
border-color: 0;
}
</style>
Invalid: misspelled color keyword
Typos in color names are not recognized by CSS:
<style>
.box {
border: 1px solid;
border-color: grren;
}
</style>
Invalid: hex code missing the # prefix
Without the leading #, the value is treated as an unknown keyword:
<style>
.box {
border: 1px solid;
border-color: ff0000;
}
</style>
Fixed: using a named color keyword
<style>
.box {
border: 1px solid;
border-color: green;
}
</style>
Fixed: using a hexadecimal value
<style>
.box {
border: 1px solid;
border-color: #00ff00;
}
</style>
Fixed: using rgb() functional notation
<style>
.box {
border: 1px solid;
border-color: rgb(0, 128, 0);
}
</style>
Fixed: using hsl() functional notation
<style>
.box {
border: 1px solid;
border-color: hsl(120, 100%, 25%);
}
</style>
Fixed: setting different colors per side
You can provide up to four valid color values to control each border individually (top, right, bottom, left):
<style>
.box {
border: 1px solid;
border-color: red green blue orange;
}
</style>
Fixed: using transparent or currentcolor
The special keywords transparent and currentcolor are also valid:
<style>
.box {
border: 1px solid;
border-color: transparent;
}
.highlight {
color: navy;
border: 2px solid;
border-color: currentcolor;
}
</style>
If you're unsure whether a value is a valid CSS color, check the MDN <color> data type reference for the complete list of accepted formats.
The border-radius property controls the rounding of an element's corners. Its valid values include lengths (e.g., 5px, 1em), percentages (e.g., 50%), and CSS-wide keywords like inherit, initial, and unset. Unlike many other border-related properties, border-radius has no none keyword in its value syntax.
This confusion typically arises because developers associate "no effect" with the keyword none, which works for properties like border: none or text-decoration: none. However, border-radius describes a geometric measurement — the radius of the corner curve — so "zero radius" (0) is the correct way to express no rounding.
Using an invalid value means the browser will ignore the entire declaration. This can lead to unexpected results: if a parent stylesheet or an earlier rule sets a border-radius, your none declaration won't override it, and the element will retain its rounded corners. Fixing this ensures your CSS is standards-compliant, behaves predictably across browsers, and passes W3C validation.
How to fix it
- To remove rounding, replace
nonewith0. - To set a specific radius, use a valid length (
5px,0.5em), a percentage (50%), or a CSS-wide keyword (inherit,initial,unset). - The same rule applies to the longhand properties:
border-top-left-radius,border-top-right-radius,border-bottom-right-radius, andborder-bottom-left-radius.
Examples
Incorrect: using none
<style>
.box {
border-radius: none; /* "none" is not a valid border-radius value */
}
</style>
<div class="box">Content</div>
Correct: removing rounded corners with 0
<style>
.box {
border-radius: 0;
}
</style>
<div class="box">Content</div>
Correct: applying a specific radius
<style>
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
}
.rounded {
border-radius: 8px;
}
.pill {
border-radius: 9999px;
}
</style>
<div class="circle">Circle</div>
<div class="rounded">Rounded</div>
<div class="pill">Pill shape</div>
Correct: resetting to the initial value
If you need to undo a border-radius set by another rule, you can use initial or unset, both of which resolve to 0:
<style>
.card {
border-radius: 12px;
}
.card.sharp {
border-radius: initial; /* Resets to 0 */
}
</style>
<div class="card">Rounded card</div>
<div class="card sharp">Sharp-cornered card</div>
A border-top, border-right, border-bottom or border-left declaration, or one of their -color longhands, has the word undefined where CSS expects a color.
CSS has no undefined keyword. It's the text JavaScript produces when a variable that was never set is joined into a string, so "1px solid " + color becomes 1px solid undefined when color has no value. It usually turns up in inline styles that a template or a server-rendered component builds from a color setting someone left empty.
The wording depends on the property. For a side shorthand such as border-bottom, the validator says undefined is not a "color" value, because the color is the part it can't read. For a longhand such as border-top-color, it names the property itself. Browsers ignore the whole declaration in both cases. With a shorthand, the width and style go with it, and that side of the box ends up with no border.
Fix the code that builds the style string. Leave the declaration out when there's no color, or fall back to a default such as currentcolor or a fixed hex value.
Invalid example
<div style="border-top: 1px solid undefined; border-bottom-color: undefined;">
Order summary
</div>
Valid example
<div style="border-top: 1px solid #d0d7de; border-bottom-color: #0055aa;">
Order summary
</div>
In the code that builds the style, check for a value before you write the declaration:
<script>
function sideBorder(side, color) {
if (!color) return "";
return `border-${side}: 1px solid ${color};`;
}
</script>
The CSS border-style property only accepts line style keywords, and the quoted value isn't one of them, so browsers ignore the declaration.
border-style takes one to four values, one per side of the box, and each must be one of none, hidden, dotted, dashed, solid, double, groove, ridge, inset or outset. The global keywords inherit, initial, revert and unset work as a single value. A made-up word such as disable or off, a width such as thick or 2px, or a color such as red all produce this message, and the validator quotes the first value it doesn't recognize.
When the browser drops the declaration, the element keeps whatever border style it would have had without it. If another rule already gives it a solid border, that border stays visible. This catches people who try to switch a border off with a word like disable: CSS has no such keyword, so the border remains.
To remove a border, use border-style: none or the shorthand border: none. Thickness and color belong in border-width and border-color, or in the border shorthand, which takes width, style and color in any order.
Invalid example
<style>
.card {
border-style: solid;
}
.card.flat {
border-style: disable;
}
</style>
Valid example
<style>
.card {
border-style: solid;
}
.card.flat {
border-style: none;
}
</style>
A border-top-width declaration has a negative value, and a border can't be thinner than zero.
border-top-width sets the thickness of an element's top border. It accepts 0, a positive length such as 2px or 0.1em, or one of the keywords thin, medium and thick. A browser drops a border-top-width declaration with a negative value, and the element keeps whatever top border width it gets from other rules. Adding !important doesn't change that: the declaration is still invalid, and the validator still reports it.
To remove the top border, set border-top-width to 0. If the negative width was meant to pull the element up over the content above it, use a negative margin-top, which CSS allows. The border-top and border-width shorthands follow the same rule, and each one has its own message.
Invalid example
<p>The previous paragraph ends here.</p>
<div class="banner" style="border-top-width: -20px;">
Banner content
</div>
Valid example
<p>The previous paragraph ends here.</p>
<div class="banner" style="border-top-width: 0; margin-top: -20px;">
Banner content
</div>
The border shorthand property accepts up to three values: a width (e.g., 1px), a style (e.g., solid), and a color (e.g., black). When the validator encounters "undefined" in the color position, it rightfully rejects it because undefined is not a recognized CSS color keyword, hex value, or color function.
This issue most commonly appears in projects that use JavaScript to dynamically set inline styles. When a variable intended to hold a color value is undefined—perhaps because it wasn't initialized, a configuration value is missing, or a function didn't return a result—the rendered HTML ends up with a literal style="border: 1px solid undefined" in the markup. Build tools, templating engines, or server-side rendering can also produce this output if a variable isn't properly resolved.
Beyond failing validation, this is a real problem because browsers will discard the entire border declaration when they encounter an invalid value. This means the border won't render at all, which may break your layout or visual design in ways that are hard to debug. Ensuring valid CSS values keeps your styling predictable across all browsers.
How to fix it
- Check for dynamic values. If the color is set via JavaScript or a templating engine, ensure the variable always resolves to a valid color string. Add fallback values or default assignments.
- Replace the invalid value. Substitute
undefinedwith a proper CSS color — a named color (red,black), a hex code (#333), anrgb()orhsl()function, or eventransparentorcurrentcolor. - Remove the declaration. If no border is needed, remove the
borderproperty entirely rather than leaving an invalid value in place.
Examples
Incorrect: literal undefined as a color value
<div style="border: 1px solid undefined;">Content</div>
The validator rejects undefined because it is not a valid CSS color.
Incorrect: JavaScript producing undefined in markup
<script>
const borderColor = undefined; // missing configuration
document.getElementById("box").style.border = "2px dashed " + borderColor;
</script>
This produces border: 2px dashed undefined on the element.
Correct: using a valid color value
<div style="border: 1px solid black;">Content</div>
Correct: using a hex code or rgb() function
<div style="border: 2px dashed #ff6600;">Content</div>
<div style="border: 3px dotted rgb(0, 128, 255);">Content</div>
Correct: providing a fallback in JavaScript
<div id="box">Content</div>
<script>
const borderColor = getUserColor() || "#333";
document.getElementById("box").style.border = "2px solid " + borderColor;
</script>
By using || "#333", you ensure a valid color is always applied even when getUserColor() returns undefined.
Correct: using separate border properties
If you prefer more granular control, you can define each border sub-property individually:
<div style="border-width: 1px; border-style: solid; border-color: black;">Content</div>
Valid border shorthand reference
The border shorthand follows this pattern:
selector {
border: <width> <style> <color>;
}
- Width:
1px,2px,thin,medium,thick - Style:
solid,dashed,dotted,double,groove,ridge,inset,outset,none - Color: any valid CSS color — named colors (
red,blue), hex (#000),rgb(),hsl(),currentcolor, ortransparent
All three values are optional in the shorthand, but any value you do include must be valid. The string undefined is never a valid CSS value. If your styles are generated dynamically, always validate or sanitize the output before it reaches the HTML.
The color property, along with properties like background-color, border-color, and outline-color, expects values that conform to the CSS Color specification. The validator triggers this error when it encounters something that doesn't match any valid color syntax. Common causes include:
- Plain numbers like
0or123— numbers alone aren't colors. - Typos in color keywords such as
greaninstead ofgreen, ortrasparentinstead oftransparent. - Malformed hex values like
#GGG(invalid hex characters) or#12345(wrong number of digits — hex colors must be 3, 4, 6, or 8 digits). - Incorrect function syntax such as
rgb(255 255 255 / 50)missing the%on the alpha value, or using legacy commas mixed with modern space-separated syntax. - Missing units or hash symbols like
000000instead of#000000.
This matters because browsers handle invalid color values unpredictably. Most will simply ignore the declaration entirely, which means the element inherits its color from a parent or falls back to the browser default — potentially making text unreadable against its background. Writing valid CSS ensures consistent rendering across all browsers and improves the maintainability of your code.
Valid CSS color formats
CSS supports several color formats:
| Format | Example | Notes |
|---|---|---|
| Named colors | red, blue, transparent | 148 predefined keywords |
| Hexadecimal | #ff0000, #f00 | 3, 4, 6, or 8 digits |
rgb() / rgba() | rgb(255, 0, 0) | Comma or space-separated |
hsl() / hsla() | hsl(0, 100%, 50%) | Hue, saturation, lightness |
currentcolor | currentcolor | Inherits the current color value |
Examples
Invalid: plain number as a color
A bare number is not a recognized color value:
<style>
.example {
color: 0;
}
</style>
Invalid: typo in a color keyword
<style>
.example {
background-color: trasparent;
}
</style>
Invalid: hex value missing the # prefix
<style>
.example {
color: 000000;
}
</style>
Invalid: hex value with wrong digit count
<style>
.example {
color: #12345;
}
</style>
Fixed: using a named color keyword
<style>
.example {
color: black;
}
</style>
Fixed: using a hexadecimal color
<style>
.example {
color: #000000;
}
</style>
Fixed: using rgb()
<style>
.example {
color: rgb(0, 0, 0);
}
</style>
Fixed: using hsl()
<style>
.example {
color: hsl(0, 0%, 0%);
}
</style>
Fixed: using rgba() for semi-transparent color
<style>
.example {
color: rgba(0, 0, 0, 0.5);
}
</style>
Fixed: correcting the transparent keyword typo
<style>
.example {
background-color: transparent;
}
</style>
If you're unsure whether a value is valid, browser DevTools can help — most browsers will strike through or ignore invalid property values in the Styles panel, giving you a quick visual indicator of the problem.
Hexadecimal color values in CSS must follow a specific format: the # symbol followed by exactly 3 or 6 hexadecimal digits. Each digit can be a number from 0 to 9 or a letter from A to F (case-insensitive). A 3-digit hex code is shorthand where each digit is expanded by duplication — for example, #F00 is equivalent to #FF0000. Common mistakes that trigger this error include using the wrong number of digits (e.g., 1, 2, 4, or 5), including non-hexadecimal characters (like G, Z, or special symbols), or omitting the # prefix.
The color CSS property sets the foreground color of an element's text and text decorations. It also establishes the currentcolor value, which acts as an indirect value for other properties like border-color. Because color cascades to many visual aspects of an element, an invalid value can cause the entire declaration to be ignored, meaning the element may inherit an unexpected color or fall back to browser defaults.
This matters for consistency across browsers. While some browsers may attempt to guess what you meant with a malformed hex code, others will discard the value entirely. This leads to unpredictable rendering. Using valid color values ensures your styles are applied reliably everywhere.
Note that CSS also supports 4-digit and 8-digit hex values (which include an alpha/transparency channel, e.g., #F00A or #FF0000AA). However, the W3C validator's inline style checker may not recognize these newer formats depending on the CSS level being validated. If you need transparency, consider using the rgba() function for broader validation compatibility.
Examples
Invalid hex color values
These examples will trigger the validation error:
<!-- Only 1 digit -->
<p style="color: #F;">Hello</p>
<!-- Only 2 digits -->
<p style="color: #FF;">Hello</p>
<!-- 4 digits (may not pass older CSS validation) -->
<p style="color: #FF00;">Hello</p>
<!-- 5 digits -->
<p style="color: #FF000;">Hello</p>
<!-- Non-hexadecimal character "G" -->
<p style="color: #FG0000;">Hello</p>
<!-- Missing the # prefix -->
<p style="color: FF0000;">Hello</p>
Valid hex color values
Use exactly 3 or 6 hexadecimal digits after the #:
<!-- 3-digit shorthand for red -->
<p style="color: #F00;">Hello</p>
<!-- 6-digit full form for red -->
<p style="color: #FF0000;">Hello</p>
<!-- 3-digit shorthand for white -->
<p style="color: #FFF;">Hello</p>
<!-- 6-digit full form for a dark gray -->
<p style="color: #333333;">Hello</p>
<!-- Lowercase is also valid -->
<p style="color: #3a7bd5;">Hello</p>
Alternative color formats
If hex values are causing issues, CSS offers several other valid ways to specify colors:
<!-- Named color -->
<p style="color: red;">Hello</p>
<!-- RGB function -->
<p style="color: rgb(255, 0, 0);">Hello</p>
<!-- RGBA function (with transparency) -->
<p style="color: rgba(255, 0, 0, 0.5);">Hello</p>
<!-- HSL function -->
<p style="color: hsl(0, 100%, 50%);">Hello</p>
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