Guias HTML para CSS
Aprenda como identificar e corrigir erros comuns de validação HTML sinalizados pelo W3C Validator — para que as suas páginas cumpram os padrões e sejam renderizadas corretamente em todos os navegadores. Consulte também o nosso Guias de acessibilidade.
A lexical error is a low-level parsing failure. Unlike a syntax error where the structure is wrong but the characters are individually valid, a lexical error means the parser cannot even form valid tokens from the input. The CSS specification defines a precise set of characters and sequences that are meaningful — property names, values, punctuation like ;, :, {, }, and so on. When the parser encounters something outside these expectations, such as @ where a ; should be, a curly (“smart”) quote instead of a straight quote, or a stray Unicode character, it raises a lexical error.
This matters for several reasons. First, browsers handle invalid CSS unpredictably — some may skip the entire rule block, others may ignore only the broken declaration, and the behavior can vary across browser versions. This leads to inconsistent rendering for your users. Second, a single lexical error can cascade, causing the parser to misinterpret subsequent valid CSS as well, potentially breaking styles well beyond the offending line. Third, clean, valid CSS is easier to maintain, debug, and collaborate on.
Common causes of this error include:
- Invalid characters used in place of punctuation — e.g., @, !, or # where a semicolon or colon should be.
- Smart (curly) quotes — pasting CSS from word processors or CMS editors that convert "straight quotes" to "curly quotes" or 'curly apostrophes'.
- Missing semicolons — while not always a lexical error, a missing ; can cause the next line’s property name to be read as part of the previous value, producing unexpected character sequences.
- Non-ASCII invisible characters — byte order marks (BOM), zero-width spaces, or non-breaking spaces that are invisible in most editors but invalid in CSS tokens.
- Copy-paste artifacts — copying code from PDFs, websites, or chat applications that insert hidden formatting characters.
To fix the issue, go to the exact line and column the error references. Look at the character it reports as “Encountered” and determine what the correct character should be. If you can’t see anything wrong, try deleting the characters around the reported position and retyping them manually — this eliminates invisible character problems.
Examples
Invalid character instead of semicolon
The @ symbol after blue is not valid CSS punctuation in this context:
<style>
h1 {
color: blue@
font-size: 24px;
}
</style>
Replace @ with a proper semicolon:
<style>
h1 {
color: blue;
font-size: 24px;
}
</style>
Smart quotes in font-family
Curly quotes copied from a word processor cause a lexical error:
<style>
body {
font-family: \u201CHelvetica Neue\u201D, sans-serif;
}
</style>
Use straight double quotes instead:
<style>
body {
font-family: "Helvetica Neue", sans-serif;
}
</style>
Stray character in an inline style
An accidental backtick in a style attribute triggers the error:
<p style="color: red`; margin: 0;">Hello</p>
Remove the invalid character:
<p style="color: red; margin: 0;">Hello</p>
Invisible non-breaking space
Sometimes the error points to what looks like empty space. A non-breaking space (\u00A0) pasted from another source can hide between tokens:
<style>
.box {
display:\u00A0flex;
}
</style>
Delete the space and retype it as a normal ASCII space:
<style>
.box {
display: flex;
}
</style>
If you suspect invisible characters, use your text editor’s “show whitespace” or “show invisible characters” feature, or paste the CSS into a hex editor to inspect the raw bytes. Configuring your editor to save files in UTF-8 without BOM also helps prevent encoding-related lexical errors.
The line-height CSS property controls the spacing between lines of text within an element. When the validator reports that a value “is not a line-height value,” it means the value you provided doesn’t match any of the accepted formats defined in the CSS specification.
Common mistakes that trigger this error include:
- Misspelled keywords — writing norml or Normal instead of normal (CSS keywords are case-insensitive in browsers, but some validators may flag inconsistencies; the real issue is outright misspellings).
- Invalid or missing units — using a unit the spec doesn’t support (e.g., line-height: 1.5x;) or accidentally adding a unit to what should be a unitless value (e.g., confusing 1.5 with 1.5 em with a space).
- Malformed numbers — typos like 1..5 or 24ppx.
- Using unsupported keywords — values like auto, thin, or large are not valid for line-height.
- Negative values — line-height does not accept negative numbers.
This matters for standards compliance and predictable rendering. While browsers may silently ignore an invalid line-height value and fall back to a default, this means your intended styling won’t be applied — potentially causing overlapping text, poor readability, or inconsistent layouts across browsers. Fixing validation errors ensures your styles work as intended everywhere.
Valid line-height values
| Format | Example | Description |
|---|---|---|
| Keyword | normal | Browser default (typically around 1.2) |
| Unitless number | 1.5 | Multiplied by the element’s font size — recommended |
| Length | 24px, 1.5em, 2rem | An absolute or relative length |
| Percentage | 150% | Relative to the element’s font size |
The unitless number format is generally preferred because it scales properly with inherited font sizes, avoiding unexpected results in nested elements.
Examples
❌ Incorrect: invalid values that trigger the error
<!-- Misspelled keyword -->
<p style="line-height: norml;">Text with an invalid line-height.</p>
<!-- Invalid unit -->
<p style="line-height: 1.5x;">Text with an unrecognized unit.</p>
<!-- Malformed number -->
<p style="line-height: 1..5;">Text with a typo in the number.</p>
<!-- Unsupported keyword -->
<p style="line-height: auto;">Auto is not valid for line-height.</p>
<!-- Negative value -->
<p style="line-height: -1.5;">Negative values are not allowed.</p>
✅ Correct: valid line-height values
<!-- Keyword -->
<p style="line-height: normal;">Browser default line height.</p>
<!-- Unitless number (recommended) -->
<p style="line-height: 1.5;">1.5 times the font size.</p>
<!-- Length with px -->
<p style="line-height: 24px;">Fixed 24px line height.</p>
<!-- Length with em -->
<p style="line-height: 1.5em;">1.5em line height.</p>
<!-- Percentage -->
<p style="line-height: 150%;">150% of the font size.</p>
Full document example
<!DOCTYPE html>
<html lang="en">
<head>
<title>Valid line-height Example</title>
</head>
<body>
<h1 style="line-height: 1.2;">A Heading with Tight Spacing</h1>
<p style="line-height: 1.6;">This paragraph uses a unitless line-height of 1.6,
which is a common choice for body text readability. It scales correctly even
if child elements have different font sizes.</p>
</body>
</html>
Tip: unitless vs. percentage/length
A unitless line-height and a percentage line-height may look equivalent, but they behave differently with inherited styles. A unitless value is recalculated for each child element based on its own font size, while a percentage or length is computed once on the parent and that fixed value is inherited. For most cases, unitless numbers are the safest choice.
The mask-image CSS property sets one or more mask layers for an element, controlling which parts are visible based on the mask’s alpha channel or luminance. According to the CSS Masking specification, the property accepts a comma-separated list of mask references, where each individual value must be one of:
- none — No mask layer is applied.
- A <image> value — This includes url() references to image files (PNG, SVG, etc.) and CSS image functions like image().
- A CSS gradient — Functions like linear-gradient(), radial-gradient(), conic-gradient(), and their repeating variants (repeating-linear-gradient(), etc.).
When the validator encounters a value that doesn’t match any of these accepted forms, it flags the error. This matters because browsers will silently discard invalid mask-image declarations, meaning your intended masking effect won’t apply, and the element will render as if no mask were set.
Common causes
Typos in gradient or function names are a frequent trigger. For example, writing linear-gradiant() instead of linear-gradient(), or radial-grad() instead of radial-gradient().
Bare image paths without url() will also cause this error. The value mask.png is not valid on its own — it must be wrapped as url('mask.png').
Unsupported keywords or arbitrary strings like mask-image: circle or mask-image: overlay are not valid. The only keyword mask-image accepts is none.
Malformed gradient syntax such as missing parentheses, invalid color stops, or incorrect direction keywords can also produce this error. For instance, linear-gradient(right, red, blue) is invalid because directional keywords require the to prefix.
Vendor-prefixed values used without the matching prefix on the property can trigger issues as well. Using -webkit-gradient() as a value for the standard mask-image property may not validate.
Examples
Incorrect: bare image path without url()
<div style="mask-image: mask.png;">
Content here
</div>
Correct: image path wrapped in url()
<div style="mask-image: url('mask.png');">
Content here
</div>
Incorrect: typo in gradient function name
<div style="mask-image: linear-gradiant(to right, transparent, black);">
Content here
</div>
Correct: properly spelled gradient function
<div style="mask-image: linear-gradient(to right, transparent, black);">
Content here
</div>
Incorrect: missing to keyword in gradient direction
<div style="mask-image: linear-gradient(right, transparent, black);">
Content here
</div>
Correct: direction uses the to keyword
<div style="mask-image: linear-gradient(to right, transparent, black);">
Content here
</div>
Incorrect: unsupported keyword
<div style="mask-image: overlay;">
Content here
</div>
Correct: using none to explicitly disable masking
<div style="mask-image: none;">
Content here
</div>
Correct: multiple mask layers
<div style="mask-image: url('star.svg'), linear-gradient(to bottom, black, transparent);">
Content here
</div>
Correct: radial gradient as a mask
<div style="mask-image: radial-gradient(circle, black 50%, transparent 100%);">
Content here
</div>
Note that browser support for the unprefixed mask-image property has improved significantly, but some older browsers may still require the -webkit-mask-image prefix. When using the prefixed version, make sure to also include the standard property for forward compatibility. The W3C validator checks against the standard syntax, so always ensure your standard mask-image declaration uses valid values even if you also include prefixed versions.
The mask CSS shorthand property allows you to partially or fully hide portions of an element by applying a graphical mask. It is a shorthand for several sub-properties including mask-image, mask-mode, mask-repeat, mask-position, mask-clip, mask-origin, mask-size, and mask-composite. Because it’s a shorthand, each value you provide must correspond to one of these sub-properties’ accepted values. The validator triggers this error when it encounters a value that doesn’t fit any of them — for example, an arbitrary keyword, a misspelled function name, or an unsupported syntax.
Common causes of this error include:
- Arbitrary keywords — Using made-up names like star-shape or circle-mask that aren’t valid CSS values.
- Misspelled functions or keywords — Typos such as lnear-gradient() instead of linear-gradient(), or noen instead of none.
- Browser-prefixed values without the standard value — Using -webkit-mask syntax or values that don’t align with the standard mask property.
- Invalid shorthand combinations — Providing sub-property values in an order or combination the shorthand doesn’t accept.
- Missing url() wrapper — Referencing an image file path directly without wrapping it in the url() function.
This matters for standards compliance because browsers may silently ignore invalid mask values, resulting in the mask not being applied at all. Your design could look completely different than intended, and the failure may be hard to debug without validation.
Valid mask values
The mask property accepts one or more comma-separated mask layers. Each layer can include:
- none — No mask is applied.
- url() — A reference to an SVG mask element or an image file (e.g., url(mask.svg), url(mask.png)).
- CSS image functions — Such as linear-gradient(), radial-gradient(), conic-gradient(), image(), etc.
- Geometry box keywords (for mask-clip / mask-origin) — Such as content-box, padding-box, border-box, fill-box, stroke-box, view-box.
- Compositing keywords (for mask-composite) — Such as add, subtract, intersect, exclude.
Examples
Incorrect: arbitrary keyword as a mask value
<div style="mask: star-shape;">
Masked Content
</div>
The value star-shape is not a recognized mask value and will be rejected by the validator.
Incorrect: missing url() function
<div style="mask: star.svg;">
Masked Content
</div>
A bare file path is not valid. Image references must be wrapped in the url() function.
Correct: using url() to reference a mask image
<div style="mask: url(star.svg);">
Masked Content
</div>
Correct: using none to explicitly disable masking
<div style="mask: none;">
No Mask Applied
</div>
Correct: using a gradient as a mask
<div style="mask: linear-gradient(to right, transparent, black);">
Fading Content
</div>
Correct: combining multiple shorthand values
<div style="mask: url(mask.png) no-repeat center / contain;">
Masked Content
</div>
This sets the mask image, repeat behavior, position, and size in a single shorthand declaration.
Correct: multiple mask layers
<div style="mask: url(shape.svg) no-repeat, linear-gradient(to bottom, black, transparent);">
Multi-layer Mask
</div>
When fixing this error, double-check your value against the CSS Masking specification on MDN. If you’re using vendor-prefixed versions like -webkit-mask, also ensure the standard mask property is present with valid values for forward compatibility.
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 0 or a positive number. If you simply want no padding, use 0. If you need some spacing, use a positive value.
- Use margin-right for 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(), Flexbox gap, 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>
<div class="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>
<div class="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>
<div class="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>
<div class="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.
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
<div style="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
<div style="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 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-align with vertical-align: Using middle, top, or bottom — these are vertical-align values, not text-align values.
- Typos: Writing cetner instead of center, or rigth instead of right.
- 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-start or space-between with text-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:
<p style="text-align: middle;">This text will fail validation.</p>
Fix: Replace middle with center:
<p style="text-align: center;">This text is properly centered.</p>
Invalid: typo in the value
<h2 style="text-align: cetner;">Heading</h2>
Fix: Correct the spelling:
<h2 style="text-align: center;">Heading</h2>
Invalid: using a non-existent value
<div style="text-align: auto;">Some content</div>
Fix: Choose a valid alignment value:
<div style="text-align: left;">Some content</div>
Invalid: using a vertical alignment value
<p style="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:
<p style="text-align: left;">Paragraph text</p>
Valid examples showing all common values
<p style="text-align: left;">Left-aligned text.</p>
<p style="text-align: right;">Right-aligned text.</p>
<p style="text-align: center;">Centered text.</p>
<p style="text-align: justify;">Justified text stretches to fill the full width of its container.</p>
<p style="text-align: start;">Start-aligned (respects text direction).</p>
<p style="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.
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 → 0s or 0ms
- Check both longhand properties (transition-delay, transition-duration) and the transition shorthand.
Examples
Incorrect — unitless zero
<style>
.fade {
transition-delay: 0;
transition-duration: 0.3s;
transition-property: opacity;
}
</style>
<div class="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>
<div class="fade">Hello</div>
Incorrect — unitless zero in the transition shorthand
<style>
.btn {
transition: background-color 0.2s ease 0;
}
</style>
<button class="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>
<button class="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>
<div class="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.
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>
<html lang="en">
<head>
<title>Hover Example</title>
<style>
a:hover {
color: red;
text-decoration: underline;
}
</style>
</head>
<body>
<a href="#">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.
The @font-feature-values at-rule lets you define human-readable names for OpenType font feature indexes, which you can then reference using properties like font-variant-alternates. For example, instead of remembering that swash index 1 maps to a “fancy” style, you can define a named value and use it semantically throughout your CSS. This is a legitimate and useful feature defined in the CSS Fonts Module Level 4 specification.
The validation error occurs because the W3C CSS validator does not always keep pace with newer CSS specifications. The @font-feature-values rule, along with its associated feature type blocks like @swash, @styleset, @character-variant, @ornaments, @annotation, and @stylistic, may simply not be in the validator’s recognized grammar yet. This does not mean your CSS is broken or invalid — it means the validator has a gap in its coverage.
That said, there are practical reasons to consider alternatives. If you need to pass strict W3C validation (for example, as a project requirement or contractual obligation), or if you need to support older browsers that lack @font-feature-values support, the font-feature-settings property offers a more widely recognized way to activate OpenType features. The tradeoff is that font-feature-settings uses raw four-character OpenType feature tags instead of friendly names, making it less readable but more portable.
How to Fix
You have several options:
- Ignore the warning. If your target browsers support @font-feature-values, the CSS is valid per the spec. The validator error is a false positive.
- Move the at-rule to an external stylesheet. If you’re validating HTML and the CSS is in a <style> block, moving it to an external .css file may help you separate concerns and skip CSS validation during HTML checks.
- Replace with font-feature-settings. Use the lower-level property to activate OpenType features directly by their tag codes.
Examples
Code that triggers the validation error
@font-feature-values "MyFamily" {
@swash {
fancy: 1;
}
}
p {
font-family: "MyFamily", serif;
font-variant-alternates: swash(fancy);
}
The validator does not recognize @font-feature-values and flags it as an error, even though this is spec-compliant CSS.
Fixed: Using font-feature-settings instead
<!DOCTYPE html>
<html lang="en">
<head>
<title>Font Feature Example</title>
<style>
p {
font-family: "MyFamily", serif;
font-feature-settings: "swsh" 1;
}
</style>
</head>
<body>
<p>This text uses OpenType swash glyphs via font-feature-settings.</p>
</body>
</html>
The font-feature-settings property accepts OpenType feature tags directly. Common tags include "swsh" for swashes, "smcp" for small caps, "liga" for standard ligatures, and "onum" for oldstyle numerals. This approach avoids the unrecognized at-rule error entirely.
Fixed: Keeping @font-feature-values with a fallback
If you want to use the more readable @font-feature-values syntax while also providing fallback support, you can combine both approaches:
p {
font-family: "MyFamily", serif;
font-feature-settings: "swsh" 1;
font-variant-alternates: swash(fancy);
}
@font-feature-values "MyFamily" {
@swash {
fancy: 1;
}
}
Browsers that understand font-variant-alternates and @font-feature-values will use the named value. Others will fall back to font-feature-settings. The validation error will persist with this approach, but your CSS will be robust and spec-compliant regardless.
The vertical-align property controls the vertical positioning of inline-level elements (like <span>, <img>, and <a>) and table-cell elements (<td>, <th>) relative to their surrounding content or cell. Unlike some other CSS properties (such as float or border), vertical-align has no none keyword. Attempting to use none results in an invalid declaration that browsers will ignore, meaning the element will fall back to the default value of baseline.
This mistake often happens when a developer wants to “reset” or “remove” vertical alignment. Since there is no none value, the correct approach is to either set vertical-align: baseline (the initial value) or remove the vertical-align declaration altogether.
The valid keyword values for vertical-align are:
- baseline — aligns the element’s baseline with the parent’s baseline (default)
- sub — aligns as a subscript
- super — aligns as a superscript
- text-top — aligns with the top of the parent’s font
- text-bottom — aligns with the bottom of the parent’s font
- middle — aligns the middle of the element with the baseline plus half the x-height of the parent
- top — aligns the top of the element with the top of the tallest element on the line
- bottom — aligns the bottom of the element with the bottom of the lowest element on the line
In addition to keywords, vertical-align also accepts length values (e.g., 5px, 0.5em) and percentage values (e.g., 50%), which offset the element relative to the baseline.
Using an invalid value like none causes a W3C validation error and means your intended styling is silently ignored by the browser. This can lead to unexpected layout results that are difficult to debug, especially in table layouts or inline formatting contexts where vertical alignment significantly affects appearance.
Examples
❌ Invalid: using none
<p>
Text with an <img src="icon.png" alt="icon" style="vertical-align: none;"> inline image.
</p>
The validator will report that none is not a valid vertical-align value. The browser ignores the declaration and defaults to baseline.
✅ Fixed: using a valid keyword
If you want the image vertically centered with the text, use middle:
<p>
Text with an <img src="icon.png" alt="icon" style="vertical-align: middle;"> inline image.
</p>
✅ Fixed: resetting to the default
If your intent was to “remove” any vertical alignment, use baseline (the initial value) or simply remove the property:
<p>
Text with an <img src="icon.png" alt="icon" style="vertical-align: baseline;"> inline image.
</p>
❌ Invalid: none in a stylesheet for table cells
<style>
td.reset {
vertical-align: none;
}
</style>
<table>
<tr>
<td class="reset">Cell content</td>
</tr>
</table>
✅ Fixed: valid value for table cells
For table cells, the default vertical-align value is middle in most browsers. To explicitly reset it or set a specific alignment:
<style>
td.top-aligned {
vertical-align: top;
}
</style>
<table>
<tr>
<td class="top-aligned">Cell content</td>
</tr>
</table>
✅ Fixed: using a length value
You can also use a specific length to offset the element from the baseline:
<p>
Text with a <span style="vertical-align: 4px;">slightly raised</span> word.
</p>
Choose the value that matches your design intent — baseline to reset, middle or top for common alignment needs, or a specific length or percentage for precise control.
The white-space property is a shorthand that combines the behavior of white-space-collapse and text-wrap-mode. When you use a value that doesn’t match any of the accepted keywords — whether due to a typo, a made-up value, or a value that belongs to a different CSS property — the W3C validator flags it as invalid. This commonly happens when authors confuse values from related properties (like using break-spaces where it isn’t supported in inline styles being validated, or misspelling nowrap as no-wrap).
Using invalid CSS values means browsers will ignore the declaration entirely, falling back to the default behavior (white-space: normal). This can cause unexpected text wrapping or whitespace collapsing that breaks your layout. Keeping your CSS valid ensures consistent rendering across browsers and makes your stylesheets easier to maintain and debug.
The accepted values for white-space are:
- normal — Collapses whitespace sequences, wraps text as needed (default).
- nowrap — Collapses whitespace but suppresses line breaks; text won’t wrap.
- pre — Preserves whitespace and line breaks exactly as written, like the <pre> element.
- pre-wrap — Preserves whitespace and line breaks, but also allows text to wrap when necessary.
- pre-line — Collapses whitespace sequences into a single space, but preserves explicit line breaks and allows wrapping.
- break-spaces — Similar to pre-wrap, but trailing spaces and spaces at the end of lines don’t hang and do affect box sizing.
Additionally, CSS Text Level 4 introduced shorthand combinations using white-space-collapse and text-wrap-mode keywords, such as collapse, preserve, wrap, and preserve nowrap. However, support for these newer shorthand forms varies, and older validators or browsers may not recognize them.
Global CSS values (inherit, initial, revert, revert-layer, unset) are also valid.
Examples
Incorrect: invalid value triggers the error
A common mistake is using no-wrap (with a hyphen) instead of the correct nowrap:
<p style="white-space: no-wrap;">This text should not wrap.</p>
Another common mistake is using a value from a different property entirely:
<p style="white-space: hidden;">This text has an invalid white-space value.</p>
Correct: using valid white-space values
<p style="white-space: nowrap;">This text will not wrap to a new line.</p>
<p style="white-space: pre-wrap;">This text preserves whitespace
and line breaks, but also wraps when needed.</p>
<p style="white-space: pre-line;">This collapses extra spaces
but preserves explicit line breaks.</p>
Correct: using the property in a <style> block
<!DOCTYPE html>
<html lang="en">
<head>
<title>White-space example</title>
<style>
.no-wrap {
white-space: nowrap;
}
.preserve {
white-space: pre-wrap;
}
</style>
</head>
<body>
<p class="no-wrap">This long paragraph will stay on a single line without wrapping.</p>
<p class="preserve">This preserves multiple spaces
and line breaks exactly as written.</p>
</body>
</html>
If you encounter this validation error, double-check your white-space value for typos and confirm it matches one of the recognized keywords listed above.
This error originates from CSS validation, not HTML element validation. It typically appears when the validator encounters a width value in a style attribute or <style> block that doesn’t conform to the CSS specification for the width property. The CSS width property accepts <length>, <percentage>, auto, min-content, max-content, fit-content, or fit-content(<length-percentage>) values. Anything outside these types—or an expression that produces an incompatible type—will trigger this error.
Common causes include:
- Missing units on a numeric value. In CSS, width: 400 is invalid (unlike the HTML width attribute on elements like <img>, which expects a unitless integer). CSS requires a unit such as px, em, rem, %, vw, etc., unless the value is 0.
- Invalid calc() expressions. For example, calc(100% - 20) is invalid because 100% is a percentage and 20 has no unit—you cannot subtract a unitless number from a percentage. It should be calc(100% - 20px).
- Typos or unrecognized values. Things like width: 50 px (space between number and unit), width: autopx, or width: 100pixels are not valid CSS.
- Using HTML attribute syntax in CSS. Writing width: 400 in a stylesheet because you’re used to writing <img width="400"> in HTML.
This matters for standards compliance and cross-browser reliability. While some browsers may attempt to interpret invalid values, the behavior is undefined and inconsistent. Relying on invalid CSS can lead to broken layouts in certain browsers or future browser versions.
How to Fix It
- Add proper units to any bare numeric width value in your CSS. Use px, em, rem, %, vw, or another valid CSS length unit.
- Check calc() expressions to ensure both sides of addition or subtraction are compatible types (e.g., length with length, or percentage with length—both are valid in calc()). Unitless numbers (other than 0) cannot be mixed with lengths or percentages in addition/subtraction.
- Remove spaces between numbers and their units. 50px is valid; 50 px is not.
- Use valid keywords only: auto, min-content, max-content, fit-content.
Examples
Incorrect: Missing unit in inline style
<div style="width: 400;">Content</div>
Correct: Adding a proper unit
<div style="width: 400px;">Content</div>
Incorrect: Incompatible types in calc()
<div style="width: calc(100% - 20);">Content</div>
The value 20 has no unit, so it cannot be subtracted from a percentage.
Correct: Compatible types in calc()
<div style="width: calc(100% - 20px);">Content</div>
Incorrect: Space between number and unit
<p style="width: 50 %;">Some text</p>
Correct: No space between number and unit
<p style="width: 50%;">Some text</p>
Incorrect: Unitless number in a <style> block
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
<style>
.sidebar {
width: 300;
}
</style>
</head>
<body>
<aside class="sidebar">Sidebar content</aside>
</body>
</html>
Correct: Valid length value in a <style> block
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
<style>
.sidebar {
width: 300px;
}
</style>
</head>
<body>
<aside class="sidebar">Sidebar content</aside>
</body>
</html>
Note on the HTML width attribute
Don’t confuse CSS width with the HTML width attribute. The HTML width attribute on elements like <img>, <video>, and <canvas> expects a unitless integer:
<img src="photo.jpg" width="400" alt="A sample photo">
Writing width="400px" in an HTML attribute is a separate validation error. The CSS error discussed in this guide specifically concerns width values in stylesheets or style attributes where a valid CSS length is required.
Pronto para validar os seus sites?
Comece o seu teste gratuito hoje.