Basic selectors

The building blocks of every selector: the simple selectors that match by element name, class, id or attribute, plus namespaces, selector lists and the nesting selector. Ways of joining selectors are under Combinators; state and structure are under Pseudo-classes and Pseudo-elements.

Simple selectors

Type selector

Matches elements by their name: p matches every <p> element. In HTML documents the name is matched case-insensitively.

Syntax<wq-name>
Specificity0,0,1 (one type)
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4

A <wq-name> is an element name with an optional namespace prefix, such as svg|a. See Namespace prefix.

h1 { font-size: 2rem; }
Every h1 on the page.

*

The universal selector matches every element. It is often scoped to a subtree, as in section *, or used in resets. Inside a compound selector it can be left out: *.card and .card are the same.

Syntax<ns-prefix>? '*'
Specificity0,0,0 (adds nothing)
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4

.class

Matches elements whose class attribute contains the given name as one of its space-separated words. Chain classes, as in .card.featured, to require several at once.

Syntax'.' <ident-token>
Specificity0,1,0 (one class)
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4

Class names are case-sensitive, except in documents in quirks mode.

#id

Matches the element whose id attribute equals the given name. Its specificity outranks any number of classes, so id selectors are best kept for anchors and scripting rather than everyday styling.

Syntax<hash-token>
Specificity1,0,0 (one id)
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4

A <hash-token> is a # followed by a name. An id that starts with a digit must be escaped, as in #\31 23 for id="123".

[attr]

Attribute selectors match on whether an attribute is present, or on its value.

Syntax'[' <wq-name> ']' | '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'
Specificity0,1,0 (one attribute)
SupportChrome 1 · Firefox 1 · Safari 3
i flag: Chrome 49 · Firefox 47 · Safari 9
s flag: Chrome no · Firefox 66 · Safari 27
Specselectors-4
SelectorMatches
[attr]The attribute is present, whatever its value.
[attr=value]The value is exactly value.
[attr~=value]One of the value's space-separated words is value.
[attr|=value]The value is value or starts with value followed by a hyphen. Made for language codes such as en-GB.
[attr^=value]The value starts with value.
[attr$=value]The value ends with value.
[attr*=value]The value contains value anywhere.
[attr=value i]Compares the value case-insensitively (ASCII letters only).
[attr=value s]Compares the value case-sensitively, even where the document language would not.

The value can be an identifier or a quoted string; it must be quoted if it contains spaces or starts with a digit. An empty value with ^=, $= or *= matches nothing.

a[href^="https:"] { … }
input[type=email i] { … }
Links to secure URLs, and email inputs however the type is written.

Namespaces

ns|

A namespace prefix limits a type, universal or attribute selector to one XML namespace, using a prefix declared with @namespace. svg|a matches only SVG links, *|a matches a in any namespace, and |a matches only a elements with no namespace.

Syntax[ <ident-token> | '*' ]? '|'
SpecificityAdds nothing; svg|a counts the same as a
SupportChrome 1 · Firefox 1 · Safari 3
Specselectors-4

Without a default namespace declared, an unprefixed selector matches elements in any namespace.

@namespace svg url(http://www.w3.org/2000/svg);
svg|a { fill: currentColor; }
Declare the prefix, then use it in the selector.

Lists & nesting

Selector list

A comma-separated list applies one rule to several selectors, as in h1, h2, h3. If any selector in the list is invalid the whole rule is dropped; wrap the list in :is() or :where() to have invalid parts ignored instead.

Syntax<complex-selector>#
SpecificityEach selector in the list keeps its own specificity
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4

&

The nesting selector stands for the elements matched by the parent rule's selector, inside a nested style rule. It lets you write state and context rules next to the base rule. When a nested selector does not contain &, it is treated as if it began with & and a space.

Syntax'&'
SpecificityThat of the most specific selector in the parent rule's list, as with :is()
SupportChrome 120 · Firefox 117 · Safari 17.2
Inside @scope: Chrome 143 · Firefox 142 · Safari 26.2
Speccss-nesting-1
.card {
  padding: 1rem;
  &:hover { outline: 2px solid; }
  .dark & { background: #222; }
}
.card:hover and .dark .card, written inside the .card rule.

Specificity

When several rules in the same cascade layer and origin set the same property on an element, the one with the highest specificity wins; if they tie, the one that comes last wins. Specificity is counted as three numbers, compared left to right: ids, then classes, attributes and pseudo-classes, then types and pseudo-elements.

SelectorSpecificity (a, b, c)
*0, 0, 0
li0, 0, 1
ul li0, 0, 2
.card0, 1, 0
a[href]0, 1, 1
li:first-child::marker0, 1, 2
#main1, 0, 0
#main .card a1, 1, 1

The universal selector and combinators add nothing. :is(), :not() and :has() take the specificity of their most specific argument; :where() always counts as zero. A declaration in a style attribute beats any selector, and !important beats both.