Skip to content
AgileLogics

CSS Validator

Checks brace balance and basic "property: value" declaration syntax. A best-effort sanity check, not a full CSS specification validator.

Working on a whole file? Open it in the CSS editor →

How it works

Paste CSS into the input panel and click Validate.

What does this CSS check actually test?

This tool is a quick structural sanity check for CSS, meant to catch the mistakes that break a whole stylesheet: a missing or extra brace, a rule with no selector, or a declaration typed without its colon. It doesn't parse CSS the way a browser does, and it isn't a substitute for the W3C CSS Validation Service.

A missing brace is worth catching early because of how CSS error recovery works. Per CSS Syntax Level 3, a browser that hits an unclosed block keeps consuming until it finds the matching brace or the end of the file, so one stray { can silently swallow every rule after it.

How the check works

The JavaScript does four things, in order, and stops at the first problem:

  1. Removes /* ... */ comments, reporting a comment that's never closed.
  2. Walks through the text, skipping over quoted strings (an unclosed string is an error) and tracking braces. A } with no open block is reported; any { left open at the end is reported with a count, for example "1 unclosed opening brace".
  3. For each innermost selector { ... } block, rejects one whose selector is empty.
  4. Splits each block's body on semicolons that sit outside strings and parentheses, and rejects any non-empty piece without a colon, quoting it back to you.

If no rule block was found at all, that's an error too. Success returns "Valid CSS (best-effort check: brace balance and basic declaration syntax only, not a full CSS spec validator)".

Results on real input

Input Result
.btn { color: #fff; padding: 4px 8px; } Valid
.btn { color: red; then .card { margin: 0; } 1 unclosed opening brace
.btn { color: red; } } unmatched closing brace
.btn { color red; } malformed declaration "color red"
{ color: red } rule block with an empty selector
@import url("a.css"); on its own no rule blocks were found
.btn { colr: blu; width: -5banana; } Valid (names and values aren't checked)
.a { color: red background: blue } Valid (the missing semicolon isn't noticed)
@media (max-width: 600px) { .btn { color: red } } Valid
.a::after { content: "}"; } Valid (the brace is inside a string)
.a { background: url(data:image/png;base64,AAA) } Valid (the semicolon is inside url())
.a { content: "oops } unclosed string starting on line 1

Read the table as two lists. The first five rows and the last one are what it's good at. Rows six and seven show what slips through, and the content and url() rows show that braces and semicolons inside values don't cause false alarms.

What a pass does not tell you

  • Property names and values are never checked. colr: blu passes. The browser will drop that declaration without complaint, which is why typos like this survive for months. Your browser's developer tools show such declarations struck through or marked invalid, which is the quickest way to find them.
  • A missing semicolon between two declarations passes. The browser treats red background: blue as one invalid value for color, and both declarations are lost.
  • At-rules aren't understood. @media, @supports and @layer blocks pass as long as their braces balance, but their conditions aren't checked.
  • Selectors aren't checked beyond being non-empty.
  • Nesting syntax (native CSS nesting, or Sass and Less) isn't modelled; braces just have to balance.

When to use which checker

Use this tool when a stylesheet stops working after an edit and you suspect a brace, or as a quick pass before minifying. The CSS minifier will happily compress broken CSS, so checking first is cheap insurance. For anything you'd ship, run the W3C service too; it parses against the CSS specifications and reports unknown properties and bad values with line numbers.

If the CSS is hard to read, run it through the code beautifier first so each declaration sits on its own line, then edit it in the online CSS editor. The CSS lessons cover the syntax rules that this check is built around.

Last updated

Frequently asked questions

Does this validate against the full CSS specification?
No. It checks brace balance and that each declaration inside a rule looks like property: value. It won't catch misspelled property names, invalid values or unsupported selectors. For a specification-level check, use the W3C CSS Validation Service.
Does a brace or semicolon inside a string confuse it?
No. The checker reads quoted strings, comments and parentheses as units, so content: "}" or url(data:image/png;base64,...) is treated as one value, not as a closing brace or the end of a declaration.
Why wasn't my missing semicolon reported?
In .a { color: red background: blue } the text color: red background: blue still contains a colon, so it looks like one declaration with an odd value. Spotting that needs knowledge of which values each property accepts, which this quick check doesn't have.
Is my CSS uploaded?
No. The check is a few lines of JavaScript that run in your browser, and nothing is sent anywhere.