Paste some HTML, type any CSS selector and instantly see which elements it matches, highlighted in the rendered page and in the source tree, plus the match count and the selector's specificity.
Last updated:
0matches
HTML
Scripts never run and external images/styles are not loaded. Your HTML stays in your browser.
Matched elements
Advertisement
Advertisement
How to use the CSS Selector Tester
Paste your HTML into the HTML box or upload an .html file. The sample page loads by default.
Type a CSS selector, for example .card > h3 or li:nth-child(odd), or click one of the example chips.
Check the result: the counter shows how many elements match and matched elements get an orange outline in the preview.
Switch to Source to see the parsed DOM tree with each match numbered, and click any match in the list to jump to it.
Read the specificity boxes (ID, class, type) to understand which rule wins in your stylesheet.
CSS selector quick reference
Selector
Matches
Specificity
p
Every <p> element
0, 0, 1
.price
Elements with class="price"
0, 1, 0
#main-nav
The element with id="main-nav"
1, 0, 0
[data-price], a[href^="https"]
Has the attribute / attribute starts with
0, 1, 0 / 0, 1, 1
nav a
Any <a> inside <nav> (descendant)
0, 0, 2
ul > li
<li> that are direct children of <ul>
0, 0, 2
h2 + p
The <p> right after an <h2>
0, 0, 2
h2 ~ p
All <p> siblings after an <h2>
0, 0, 2
li:nth-child(2n+1)
Odd list items (1st, 3rd, 5th…)
0, 1, 1
p:not(.intro)
Paragraphs without class "intro"
0, 1, 1
.card:has(img)
Cards that contain an image
0, 1, 1
:where(h2, h3)
Any h2 or h3, with zero specificity
0, 0, 0
p::first-line
Pseudo-element (not selectable by querySelectorAll)
0, 0, 2
How specificity decides which rule wins
When two rules set the same property on the same element, the browser compares their specificity from left to right: the selector with more IDs wins; if tied, the one with more classes, attributes and pseudo-classes wins; if still tied, the one with more type selectors and pseudo-elements wins. If the specificity is identical, the rule that appears later in the CSS wins. Inline style attributes beat any selector, and !important overrides normal declarations regardless of specificity.
A practical tip: keep specificity low and flat (mostly single classes) so components are easy to override, and use :where() for defaults that should be trivial to replace.
Why the source can differ from what you pasted
The Source tab shows the DOM the browser actually built, not your raw text. HTML parsers add missing <html>, <head>, <body> and <tbody> elements, close unclosed tags and move invalid nesting (a block element inside a <p> ends the paragraph). Selectors run against that DOM, so this view explains most "why doesn't it match" surprises.
Frequently asked questions
How does the CSS selector tester work?
Your HTML is parsed by the browser into a sandboxed preview, and the selector is run with document.querySelectorAll, the same engine your stylesheets and JavaScript use. Every matching element is outlined and listed.
How is CSS specificity calculated?
Specificity is three numbers (A, B, C). A counts ID selectors, B counts classes, attribute selectors and pseudo-classes, and C counts type selectors and pseudo-elements. The universal selector * and combinators add nothing. :is(), :not() and :has() take the specificity of their most specific argument, and :where() always counts as zero. Higher A wins, then B, then C.
Why does my selector match nothing?
Common causes are a typo in a class name, a missing combinator (a space means descendant, > means direct child), or HTML that the parser rewrites: for example a <div> inside a <p> closes the paragraph, and tables get an automatic <tbody>. Open the Source tab to see the DOM exactly as the browser built it.
Do :hover and :focus work here?
State pseudo-classes such as :hover, :focus and :active only match while the user interacts with the element, so in a static test they normally match nothing. Structural and attribute-based pseudo-classes like :checked, :disabled, :required, :empty and :nth-child() work fully.
Is :has() supported?
Yes, if your browser supports it (Chrome, Edge, Safari and Firefox 121 or newer). The tester uses your browser's native engine, so an unsupported selector shows an invalid selector message.
Is my HTML sent anywhere?
No. Everything runs in your browser. The preview is a sandboxed frame that blocks scripts, forms and external images or stylesheets, so pasting untrusted HTML is safe.
Are all the tools on FreeToolCabin tested for quality and accuracy?
Yes! Every tool on our site undergoes automated Q/A testing in real browser environments to ensure high precision, correct output, and zero errors. If you happen to spot a bug or have a suggestion, please contact us at [email protected] and our team will review it right away.