CSS, how to select elements that do NOT have a class
By Flavio Copes
Learn how to select HTML elements that do not have a class in CSS using the :not() selector, for example p:not(.description) to style unclassed paragraphs.
To select elements in an HTML document that do NOT have a specific class, use the :not() pseudo-class:
:not(.class)
For example, this styles every paragraph except the ones with the description class:
p:not(.description) {
color: red;
}
Given this HTML:
<p class="description">A short intro.</p>
<p>This one turns red.</p>
<p class="highlight">This one turns red too.</p>
The second and third paragraphs match. The highlight class doesn’t save the third one, because the rule only excludes .description.
Why would you need this?
:not() inverts a selector. Without it, styling “everything except X” means styling everything, then writing a second rule to undo it for X. With :not() you express the exception directly, in one rule.
I reach for it when a design has one special variant and many normal cases. Style the normal cases with :not(.variant) and the exception keeps its own rules, with no overrides fighting each other.
Selecting elements with no class at all
Sometimes you don’t want to exclude one class, you want elements that have no class attribute whatsoever. For that, combine :not() with an attribute selector:
p:not([class]) {
color: red;
}
[class] matches any element carrying a class attribute, so :not([class]) matches the ones without it.
One edge case: an element with an empty attribute, like <p class="">, still has the attribute, so p:not([class]) skips it.
Excluding more than one class
You can chain :not() to exclude several classes:
p:not(.description):not(.highlight) {
color: red;
}
Modern browsers also accept a list inside a single :not(), which reads better:
p:not(.description, .highlight) {
color: red;
}
The pitfall: forgetting the element part
Be careful with a bare :not(.description). Without an element in front, it matches every element that lacks the class, including html, body and all their children:
:not(.description) {
color: red;
}
This paints essentially the whole page red, which is rarely the plan. The fix is to anchor the selector to an element, like p:not(.description), or at least to a container, like .article :not(.description).
Also note that :not() adds the specificity of its argument. p:not(.description) has the same specificity as p.description, so it can win against selectors that look heavier than it is.
Related posts about css: