CSS Selector Tester Online — Specificity & DOM Debugger

CSS Selector Tester

Test CSS selectors against HTML with real-time matching and specificity analysis.

An interactive, browser-based CSS selector tester and specificity calculator for frontend developers, UI engineers, and QA automation specialists. Test and debug complex CSS selectors against any HTML fragment or document in real time with instant DOM node highlighting and ancestor path inspection. Calculate precise CSS specificity tuples (IDs, Classes/Attributes/Pseudo-classes, Elements/Pseudo-elements) and comparative weights according to the W3C Selectors Level 4 specification. Validate modern pseudo-classes including :has(), :is(), :where(), :not(), and functional :nth-child(An+B of S) arguments. Features categorized selector cheat sheets, attribute filters, and multi-color DOM matching. All parsing and evaluation executes 100% locally in your browser with zero data logging.

Keywords: css selector tester, css selector tester online, test css selector, css selector validator, css specificity calculator, querySelector tester, css selector debugger, css selector playground, css selector matcher, css selector checker, css nth-child tester, css has selector, css selector specificity, css selector reference, test querySelector, css selector tool, html selector tester, css selector online

Tags: css, selector, query, test, specificity, dom, html, querySelector

Browse all 21 Web Code tools →

CSS Selector Tester is also known as: CSS Selector Tester Online, CSS Specificity Calculator, DOM querySelector Tester, CSS Selector Debugger and Matcher, CSS Selector Playground, Modern CSS Selector Validator, CSS nth-child and :has Tester, Interactive CSS Query Tester.

How to CSS Selector Tester Online

  1. Paste or write your HTML markup into the left-hand editor panel, or click the "Examples" dropdown to load pre-configured DOM templates.

  2. Type any standard or modern CSS selector into the bottom query bar. The engine validates selector syntax and specificity scores on every keystroke.

  3. Inspect matched elements in real time (debounced 300 ms) or press ⌘↵ (Ctrl+Enter) to trigger immediate evaluation.

  4. Switch between the Matches tab (detailed DOM cards with tag, classes, IDs, and attributes), Highlight tab (color-coded HTML source view), and Specificity tab.

  5. Review the calculated Specificity Vector (IDs, Classes/Attributes/Pseudo-classes, Elements/Pseudo-elements) and comparative numeric score.

  6. Click on any matched element card to inspect its full ancestor path (e.g. main > section.hero > div > h1) and copy its outerHTML.

  7. Open the Selector Reference panel (⌘⇧H) to explore 26+ categorized CSS selector patterns with one-click injection into the query bar.

  8. Copy all matched element markups simultaneously with ⌘⇧C or clear both editors with ⌘⇧K to start fresh.

CSS Selector Tester Features

  • Real-time CSS selector testing and DOM matching powered by browser-native DOMParser and querySelectorAll engines.

  • W3C Selectors Level 4 compliance supporting :has(), :is(), :where(), :not(), and complex :nth-child(An+B of selector) patterns.

  • Precise Specificity Calculator displaying the three-column specificity tuple (a, b, c) and integer ranking score for any selector.

  • Three synchronized result views: Matches inspector, source-level HTML Highlighting, and Specificity score visualizer.

  • Full DOM ancestor path generation (e.g. div.wrapper > ul.nav > li:first-child) for pinpointing target node coordinates.

  • Deep attribute and property inspection: examine class lists, dataset attributes, IDs, and raw outerHTML snippets for every match.

  • Multi-color HTML source highlighting with clear visual delineations across multiple matched DOM nodes.

  • Comprehensive Selector Cheat Sheet and Reference library covering basic selectors, combinators, attributes, and modern pseudo-classes.

  • Instant syntax error diagnostics displaying exact browser parser errors when invalid selector tokens are typed.

  • Pre-loaded interactive templates covering relational :has() queries, case-insensitive attributes, and :nth-child sub-filtering.

  • High-speed batch copying of all matched elements or individual outerHTML nodes with dedicated keyboard shortcuts.

  • Automatic session state persistence using local storage to restore HTML markups and query selectors across page refreshes.

  • Zero-latency execution with microsecond execution timing and total document node counts.

  • 100% Client-side sandbox execution: your HTML markup and proprietary UI templates never leave your local browser.

Supported Formats & Dialects

The CSS Selector Tester supports 6 syntax formats and dialects for accurate parsing and processing.

Type & Universal Selectors (*, div, p, main)
Target DOM nodes by their HTML tag name (e.g. article, button, input) or match all document nodes using the universal asterisk (*) selector. Type selectors contribute (0, 0, 1) to specificity, while the universal selector contributes (0, 0, 0).
Class & ID Selectors (.class, #id, chained classes)
Target elements by class attribute (.btn-primary) or unique identifier (#main-content). Multiple classes can be chained (.btn.btn-lg.active) to require all classes simultaneously. ID selectors contribute (1, 0, 0) and class selectors contribute (0, 1, 0).
Combinators & Hierarchical Selectors (space, >, +, ~)
Define relational constraints between nodes: descendant space (div p), direct child (ul > li), adjacent sibling (h2 + p), and general sibling (h2 ~ p). Combinators establish DOM relationship requirements without contributing to specificity.
Attribute Selectors ([attr], [attr=val], [attr^=], [attr$=], [attr*=], [attr~=], [attr|=], case flags)
Query nodes based on attribute presence and value patterns: exact match ([type="checkbox"]), prefix ([href^="https"]), suffix ([src$=".png"]), substring ([class*="card"]), word list ([class~="badge"]), or language prefix ([lang|="en"]). Supports case-insensitive matching flags like [data-theme="dark" i]. Each attribute selector contributes (0, 1, 0).
Standard & Structural Pseudo-Classes (:first-child, :last-child, :nth-child(An+B), :nth-of-type, :empty)
Filter elements based on their positional index and tree structural state within parent containers. Supports algebraic formulas like :nth-child(2n+1) for odd rows, :nth-child(-n+3) for the first three items, and :empty for childless containers. Each pseudo-class contributes (0, 1, 0).
Modern Functional Pseudo-Classes (:has(), :is(), :where(), :not(), :nth-child(An+B of S))
W3C Selectors Level 4 features enabling relational parent selection (:has(> img)), forgiving list grouping (:is(h1, h2, h3)), zero-specificity base styling (:where(.card)), negation (:not(.disabled)), and sub-filtered sibling counting (:nth-child(2n of .active)). Specificity reflects the most specific argument, except :where() which always contributes (0, 0, 0).
All Guides
All Standards
AI Model Token Pricing

Explore Full AI Model Pricing Directory

Compare per-token rates, prompt caching discounts, and context windows across leading LLMs (GPT-4o, Claude 3.5 Sonnet, Gemini 2.5 Flash, DeepSeek, and more) in our verified catalog.

Pre-built Automation Pipelines

Chain CSS Selector Tester with other utilities in a multi-step visual workflow.

beginner
encoding

Base64 Decode → JSON Format

Decode a Base64 string and pretty-print the JSON inside it.

Flow:
InputBase64 Encode/DecodeJSON FormatterOutput
4 nodes
beginner
data-transformation

CSV → JSON → YAML

Convert CSV data to JSON, then to YAML format.

Flow:
InputCSV to JSONYAML ConverterOutput
4 nodes
intermediate
development

JSON Format → TypeScript Schema

Format JSON and generate TypeScript/Zod schema from it.

Flow:
InputJSON FormatterJSON to TypeScript & Schema GeneratorOutput
4 nodes

Frequently Asked Questions

How is CSS selector specificity calculated according to the W3C Selectors Level 4 specification?
CSS specificity is computed as a three-part vector (a, b, c) where: "a" represents the count of ID selectors (#header); "b" represents the count of class selectors (.btn), attribute selectors ([type="text"]), and pseudo-classes (:hover, :nth-child); and "c" represents the count of type selectors (div, span) and pseudo-elements (::before, ::placeholder). The universal selector (*) and combinators (>, +, ~, space) contribute (0, 0, 0). Specificity vectors are evaluated lexicographically: any value in "a" outweighs any value in "b", and any value in "b" outweighs "c". For example, (1, 0, 0) beats (0, 15, 8).
How does the :has() relational pseudo-class evaluate parent and sibling conditions?
:has() is a functional relational pseudo-class that evaluates relative selector lists against descendants or subsequent siblings of the subject element. For example, "article:has(img.featured)" matches any <article> containing a featured image descendant, while "h2:has(+ p.lead)" matches an <h2> immediately followed by a lead paragraph. The specificity of :has(S) is equal to the specificity of the most specific selector in its argument list S. The browser evaluates :has() dynamically without requiring JavaScript DOM tree traversal.
What are the operational differences between :is(), :where(), and :not() regarding specificity and forgiving parsing?
:is() and :where() both accept a forgiving selector list (meaning invalid selector tokens in the comma-separated list are ignored rather than invalidating the entire CSS rule). However, :is(A, B) adopts the specificity of its most specific argument (e.g., :is(div, #sidebar) has specificity (1, 0, 0)), whereas :where(A, B) always contributes zero specificity (0, 0, 0), making it ideal for design system resets. :not(A, B) negates matches and takes the specificity of its most specific argument list item.
How does the modern :nth-child(An+B of selector) syntax differ from :nth-of-type()?
:nth-of-type(n) counts elements among siblings that share the exact same HTML tag name, regardless of classes or attributes. In contrast, the modern Selectors Level 4 syntax ":nth-child(An+B of .active)" filters the sibling list to include only elements matching the ".active" selector before applying the An+B formula index. This enables developers to select "every second active item" (2n of .active) even when items have differing HTML tag types or are interspersed with inactive sibling elements.
How do attribute selector operators (^=, $=, *=, ~=, |=) and case-sensitivity flags (i, s) behave?
CSS attribute selectors match DOM element properties: [attr] checks presence; [attr="val"] checks exact equality; [attr^="val"] checks string prefix; [attr$="val"] checks string suffix; [attr*="val"] checks arbitrary substring inclusion; [attr~="val"] checks space-delimited word lists; and [attr|="val"] checks exact value or prefix followed by a hyphen (val-). Appending the "i" modifier ([data-type="user" i]) forces ASCII case-insensitive matching, while "s" forces strict case-sensitive matching.
What is the difference between direct child (>), descendant (space), adjacent sibling (+), and general sibling (~) combinators?
Combinators specify DOM relationship criteria between compound selectors without adding specificity weight. Descendant combinators ("A B") match any element B nested anywhere within the subtree of A. Direct child combinators ("A > B") match B only if A is the immediate parent. Adjacent sibling combinators ("A + B") match B only if it immediately follows A as the next element in the same parent. General sibling combinators ("A ~ B") match any sibling B that follows A anywhere within the shared parent container.
Why do dynamic pseudo-classes like :hover, :focus-visible, and :active behave differently during static HTML testing?
Dynamic pseudo-classes (:hover, :focus, :focus-visible, :active, :visited) depend on interactive browser states and user input event dispatching. When testing selectors against static HTML snippets parsed via DOMParser, elements do not possess active user focus, mouse pointer hover, or session history states. However, structural pseudo-classes (:first-child, :last-of-type, :empty), form attribute states (:checked, :disabled, :required), and relational pseudo-classes (:has, :not, :is) are fully evaluated on the parsed DOM.
How does the CSS Cascade resolve conflicts when multiple selectors match the same DOM element?
The CSS Cascade resolves conflicting declarations using an exact precedence hierarchy: (1) Importance and Origin (User-Agent < Author Normal < CSS @layer normal < Inline style normal < CSS @layer !important < Author !important < User-Agent !important); (2) Specificity Vector (a, b, c comparison); and (3) Source Order (declarations appearing later in stylesheet source code win when origin and specificity are identical).
How do pseudo-elements (::before, ::after, ::placeholder, ::marker) affect specificity calculations and DOM matching?
Pseudo-elements represent abstract structural components that do not exist as distinct HTML tags in the raw DOM tree (e.g. ::before creates a virtual child, ::marker styles a list bullet, ::placeholder styles input placeholder text). In specificity math, pseudo-elements count as element type selectors (0, 0, 1). In JavaScript DOM matching via document.querySelectorAll(), pseudo-elements cannot be selected directly because they are rendered in the CSS layout tree rather than the DOM Node tree.
How can developers debug CSS selector performance and minimize selector matching overhead in large DOM trees?
Modern browser rendering engines evaluate CSS selectors from right to left (beginning with the "key selector" at the end of the rule). A selector like "body div ul li a" forces the engine to test every <a> tag in the document and walk up its ancestor chain. Optimizing performance involves: using specific class names as key selectors (.menu-link), avoiding overly broad universal descendant chains (* > a), scoping with child combinators (>) rather than deep descendants, and leveraging :where() for shared reset rules.
How does browser-native document.querySelectorAll() differ from jQuery/Sizzle or CSSOM stylesheet evaluation?
Browser-native "querySelectorAll()" parses selectors strictly against the W3C Selectors specification and returns a static (non-live) NodeList representing a snapshot of matched elements at invocation time. Unlike legacy jQuery/Sizzle libraries, native querySelectorAll does not support non-standard proprietary pseudo-selectors like ":eq()" or ":visible". In our tool, querySelectorAll runs directly in your browser engine, ensuring 100% fidelity with real-world browser execution.
Does this CSS Selector Tester send HTML markup or sensitive UI data to any external server?
No. The DevFlow CSS Selector Tester runs entirely client-side inside your browser sandbox. HTML parsing is performed locally via the native DOMParser API, and selector matching executes using the local querySelectorAll interface. No markup, proprietary source code, or selector queries are transmitted to or logged on remote servers, ensuring complete privacy.

Developer Reference & Learning Hubs