Why CSS errors are hard to spot
Browsers recover from bad CSS by skipping what they cannot parse, and they do it silently. A missing } inside a media query swallows the rest of the file into that query; a missing colon throws away one declaration; an unclosed comment hides everything after it. DevTools rarely tells you why a rule “does nothing”. A syntax check that names the exact line is faster than bisecting the stylesheet by hand.
The validator parses your CSS with PostCSS (through Prettier, which also formats it) and reports the first structural error it meets:
- Unclosed block: a rule or at-rule opened with
{that never closes. - Unexpected }: one closing brace too many, often after deleting a nested rule.
- Unknown word: a declaration without a colon, such as
color #fff, or a stray token where a property should start. - Missed semicolon: two declarations on consecutive lines with no
;between them, as incolor: redfollowed bybackground: blue;. Browsers would read both as one invalid value and drop them together. - Unclosed string, unclosed comment and unclosed bracket, as in
calc(100% - 10px;orurl("logo.svg;.
A semicolon after the last declaration in a block is optional, and a doubled ;; is harmless, so neither is reported.
How the result is shown
PostCSS errors come through with their own names, prefixed with CssSyntaxError, and a line and column that the editor highlights. For an unclosed block the position is the selector that opened it, which is usually where the fix belongs. While the stylesheet is broken, the last formatted version remains in the output pane in a muted style. Fix the first error and re-check: one missing brace can cause several later errors to appear, and they disappear together.
If a minified stylesheet fails, every error lands on line 1. Format a working copy first, or search for the reported column, to see which rule it belongs to.
Stylesheets are processed locally. Paste production CSS, including internal hostnames in url() references, without anything being sent to a server.
Syntax only, not properties or values
The check confirms that the CSS can be parsed. It does not compare properties and values with the CSS specifications, so colr: red, margin: 10 px and display: flexbox all pass even though browsers ignore them. It also does not check selector support, vendor prefixes, @import order or browser compatibility. For property-level linting, run Stylelint with a standard config; for browser support, check the property on MDN or caniuse.
Preprocessor syntax is a different language. Nesting with &, $variables and @mixin belong on the SCSS formatter or Less formatter pages, which use the matching parser. Plain CSS nesting, now supported natively by browsers, parses here as well.
Examples
Card component with a missing brace
Invalid: the nested .card__title rule closes but .card never does, so the error points at the opening of the block.
.card {
padding: 1rem;
border-radius: 8px;
.card__title {
font-weight: 600;
}
.card--featured { border-color: #2563eb; }Line 1, column 7: '{' is never closedDeclaration without a colon
Invalid: color #fff has no colon, which PostCSS reports as an unknown word on line 3.
.btn-primary {
background: #2563eb;
color #fff;
padding: 0.5rem 1rem;
}Line 3, column 3: CssSyntaxError: Unknown word colorUnclosed calc() bracket
Invalid: the bracket opened by calc( is never closed.
.sidebar {
width: calc(100% - 240px;
position: sticky;
}Line 4, column 1: Expected ')' to close '(' opened at line 2, column 14, but found '}'Valid syntax with a typo the validator does not catch
Passes: colr is syntactically a declaration, so only a linter such as Stylelint would flag the misspelled property.
.badge {
colr: #b91c1c;
margin: 0 4px;
}.badge {
colr: #b91c1c;
margin: 0 4px;
}
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
CssSyntaxError: Unclosed blockExplained | A rule, media query or nested rule opened with { has no matching }. | Add the missing } at the end of the block that starts at the reported line. |
CssSyntaxError: Unexpected } | There is one closing brace more than there are opening braces. | Delete the extra brace, or restore the selector whose opening brace was removed. |
CssSyntaxError: Unknown word color | A declaration is missing its colon, or a stray word sits between declarations. | Write the declaration as property: value; and check the previous line for a missing semicolon. |
CssSyntaxError: Missed semicolon | A declaration is not terminated before the next one starts on the following line. | Add ; at the end of the line the error points to. |
CssSyntaxError: Unclosed comment | A /* comment has no closing */, so the rest of the stylesheet is treated as a comment. | Close the comment with */. |
Frequently asked questions
Is this the same as the W3C CSS validator?
No. The W3C service checks properties and values against the specifications. This page checks syntax: braces, colons, strings, comments and brackets.
Why does a misspelled property pass?
A misspelled property is still well-formed CSS, and browsers simply ignore it. Use Stylelint if you want unknown properties reported.
Does it support modern CSS like nesting, @layer and container queries?
Yes, as far as syntax goes. The parser handles nested rules and any at-rule, so @layer, @container and @property parse normally.
Can I minify the CSS once it is valid?
Yes. Press Ctrl/Cmd+Shift+M or open the CSS minifier; minification only runs on CSS that parses.