Title: Selectors Level 4 Group: CSSWG Shortname: selectors Level: 4 Status: ED Work Status: Refining ED: https://drafts.csswg.org/selectors/ TR: https://www.w3.org/TR/selectors-4/ Previous Version: https://www.w3.org/TR/2022/WD-selectors-4-20220507/ Previous Version: https://www.w3.org/TR/2018/WD-selectors-4-20181121/ Previous Version: https://www.w3.org/TR/2018/WD-selectors-4-20180202/ Previous Version: https://www.w3.org/TR/2018/WD-selectors-4-20180201/ Previous Version: https://www.w3.org/TR/2013/WD-selectors4-20130502/ Previous Version: https://www.w3.org/TR/2012/WD-selectors4-20120823/ Previous Version: https://www.w3.org/TR/2011/WD-selectors4-20110929/ Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400 Editor: Tab Atkins Jr., Google, http://xanthir.com/contact/, w3cid 42199 Former Editor: Tantek Çelik, http://www.tantek.com Former Editor: Daniel Glazman Former Editor: Ian Hickson Former Editor: Peter Linss Former Editor: John Williams Abstract: Selectors are patterns that match against elements in a tree, and as such form one of several technologies that can be used to select nodes in a document. Selectors have been optimized for use with HTML and XML, and are designed to be usable in performance-critical code. They are a core component of CSS (Cascading Style Sheets), which uses Selectors to bind style properties to elements in the document. Abstract: Selectors Level 4 describes the selectors that already exist in [[!SELECT]], and further introduces new selectors for CSS and other languages that may need them. At Risk: the column combinator At Risk: [=user action pseudo-classes=] applying to non-[=tree-abiding=] [=pseudo-elements=] At Risk: the '':blank'' pseudo-class Ignored Terms: function token, Document, DocumentFragment, math, h1, shadow tree, querySelector(), quirks mode, button, a, span, object, p, div, q, area, link, label, input, html, em, li, ol, pre, CSS Value Definition Syntax Ignored Vars: identifier, i
spec:css-values-4; type:dfn; text:identifier spec:css-display-3; type:property; text:display spec:css-pseudo-4; type:selector; text: ::before text: ::after text: ::first-line text: ::first-letter spec:html; type:element-attr; for:a; text:href spec:html; type:element; text:meta text:audio
element.matches()
function defined in [[DOM]]
document.querySelectorAll()
function defined in [[DOM]]
or the selector of a CSS style rule.
Pattern | Represents | Section | Level |
---|---|---|---|
*
| any element | [[#the-universal-selector]] | 2 |
E
| an element of type E | [[#type-selectors]] | 1 |
E:not(s1, s2, …)
| an E element that does not match either compound selector s1 or compound selector s2 | [[#negation]] | 3/4 |
E:is(s1, s2, …)
| an E element that matches compound selector s1 and/or compound selector s2 | [[#matches]] | 4 |
E:where(s1, s2, …)
| an E element that matches compound selector s1 and/or compound selector s2 but contributes no specificity. | [[#zero-matches]] | 4 |
E:has(rs1, rs2, …)
| an E element, if there exists an element that matches either of the relative selectors rs1 or rs2, when evaluated with E as the anchor elements | [[#relational]] | 4 |
E.warning
| an E element belonging to the class warning
(the document language specifies how class is determined).
| [[#class-html]] | 1 |
E#myid
| an E element with ID equal to myid .
| [[#id-selectors]] | 1 |
E[foo]
| an E element with a foo attribute
| [[#attribute-representation]] | 2 |
E[foo="bar"]
| an E element whose foo attribute value is
exactly equal to bar
| [[#attribute-representation]] | 2 |
E[foo="bar" i]
| an E element whose foo attribute value is
exactly equal to any (ASCII-range) case-permutation of bar
| [[#attribute-case]] | 4 |
E[foo="bar" s]
| an E element whose foo attribute value is
[=identical to=] bar
| [[#attribute-case]] | 4 |
E[foo~="bar"]
| an E element whose foo attribute value is
a list of whitespace-separated values, one of which is
exactly equal to bar
| [[#attribute-representation]] | 2 |
E[foo^="bar"]
| an E element whose foo attribute value
begins exactly with the string bar
| [[#attribute-substrings]] | 3 |
E[foo$="bar"]
| an E element whose foo attribute value
ends exactly with the string bar
| [[#attribute-substrings]] | 3 |
E[foo*="bar"]
| an E element whose foo attribute value
contains the substring bar
| [[#attribute-substrings]] | 3 |
E[foo|="en"]
| an E element whose foo attribute value is
a hyphen-separated list of values beginning with en
| [[#attribute-representation]] | 2 |
E:dir(ltr)
| an element of type E with left-to-right directionality (the document language specifies how directionality is determined) | [[#the-dir-pseudo]] | 4 |
E:lang(zh, "*-hant")
| an element of type E tagged as being either in Chinese (any dialect or writing system) or otherwise written with traditional Chinese characters | [[#the-lang-pseudo]] | 2/4 |
E:any-link
| an E element being the source anchor of a hyperlink | [[#the-any-link-pseudo]] | 4 |
E:link
| an E element being the source anchor of a hyperlink of which the target is not yet visited | [[#link]] | 1 |
E:visited
| an E element being the source anchor of a hyperlink of which the target is already visited | [[#link]] | 1 |
E:local-link
| an E element being the source anchor of a hyperlink targeting the current URL | [[#the-local-link-pseudo]] | 4 |
E:target
| an E element being the target of the current URL | [[#the-target-pseudo]] | 3 |
E:target-within
| an E element that is the target of the current URL or contains an element that does. | [[#the-target-within-pseudo]] | 4 |
E:scope
| an E element being a [=scoping root=] | [[#the-scope-pseudo]] | 4 |
E:current
| an E element that is currently presented in a time-dimensional canvas | [[#the-current-pseudo]] | 4 |
E:current(s)
| an E element that is the deepest '':current'' element that matches selector s | [[#the-current-pseudo]] | 4 |
E:past
| an E element that is in the past in a time-dimensional canvas | [[#the-past-pseudo]] | 4 |
E:future
| an E element that is in the future in a time-dimensional canvas | [[#the-future-pseudo]] | 4 |
E:active
| an E element that is in an activated state | [[#the-active-pseudo]] | 1 |
E:hover
| an E element that is under the cursor, or that has a descendant under the cursor | [[#the-hover-pseudo]] | 2 |
E:focus
| an E element that has user input focus | [[#the-focus-pseudo]] | 2 |
E:focus-within
| an E element that has user input focus or contains an element that has input focus. | [[#the-focus-within-pseudo]] | 4 |
E:focus-visible
| an E element that has user input focus, and the UA has determined that a focus ring or other indicator should be drawn for that element | [[#the-focus-visible-pseudo]] | 4 |
E:enabled
| a user interface element E that is enabled or disabled, respectively | [[#enableddisabled]] | 3 |
E:read-write E:read-only
| a user interface element E that is user alterable, or not | [[#rw-pseudos]] | 3-UI/4 |
E:placeholder-shown
| an input control currently showing placeholder text | [[#placeholder]] | 3-UI/4 |
E:default
| a user interface element E that is the default item in a group of related choices | [[#the-default-pseudo]] | 3-UI/4 |
E:checked
| a user interface element E that is checked/selected (for instance a radio-button or checkbox) | [[#checked]] | 3 |
E:indeterminate
| a user interface element E that is in an indeterminate state (neither checked nor unchecked) | [[#indeterminate]] | 4 |
E:valid E:invalid
| a user-input element E that meets, or doesn't, its data validity semantics | [[#validity-pseudos]] | 3-UI/4 |
E:in-range E:out-of-range
| a user-input element E whose value is in-range/out-of-range | [[#range-pseudos]] | 3-UI/4 |
E:required E:optional
| a user-input element E that requires/does not require input | [[#opt-pseudos]] | 3-UI/4 |
E:blank
| a user-input element E whose value is blank (empty/missing) | [[#blank]] | 4 |
E:user-invalid
| a user-altered user-input element E with incorrect input (invalid, out-of-range, omitted-but-required) | [[#user-pseudos]] | 4 |
E:root
| an E element, root of the document | [[#the-root-pseudo]] | 3 |
E:empty
| an E element that has no children (neither elements nor text) except perhaps white space | [[#the-empty-pseudo]] | 3 |
E:nth-child(n [of S]?)
| an E element, the n-th child of its parent matching S | [[#the-nth-child-pseudo]] | 3/4 |
E:nth-last-child(n [of S]?)
| an E element, the n-th child of its parent matching S, counting from the last one | [[#the-nth-last-child-pseudo]] | 3/4 |
E:first-child
| an E element, first child of its parent | [[#the-first-child-pseudo]] | 2 |
E:last-child
| an E element, last child of its parent | [[#the-last-child-pseudo]] | 3 |
E:only-child
| an E element, only child of its parent | [[#the-only-child-pseudo]] | 3 |
E:nth-of-type(n)
| an E element, the n-th sibling of its type | [[#the-nth-of-type-pseudo]] | 3 |
E:nth-last-of-type(n)
| an E element, the n-th sibling of its type, counting from the last one | [[#the-nth-last-of-type-pseudo]] | 3 |
E:first-of-type
| an E element, first sibling of its type | [[#the-first-of-type-pseudo]] | 3 |
E:last-of-type
| an E element, last sibling of its type | [[#the-last-of-type-pseudo]] | 3 |
E:only-of-type
| an E element, only sibling of its type | [[#the-only-of-type-pseudo]] | 3 |
E F
| an F element descendant of an E element | [[#descendant-combinators]] | 1 |
E > F
| an F element child of an E element | [[#child-combinators]] | 2 |
E + F
| an F element immediately preceded by an E element | [[#adjacent-sibling-combinators]] | 2 |
E ~ F
| an F element preceded by an E element | [[#general-sibling-combinators]] | 3 |
F || E
| an E element that represents a cell in a grid/table belonging to a column represented by an element F | [[#the-column-combinator]] | 4 |
E:nth-col(n)
| an E element that represents a cell belonging to the nth column in a grid/table | [[#the-nth-col-pseudo]] | 4 |
E:nth-last-col(n)
| an E element that represents a cell belonging to the nth column in a grid/table, counting from the last one | [[#the-nth-last-col-pseudo]] | 4 |
>
),
the next-sibling combinator (U+002B, +
),
and the subsequent-sibling combinator (U+007E, ~
).
Two given elements are said to match a combinator
when the condition of relationship between these elements is true.
A complex selector is
a sequence of one or more compound selectors
and/or [=pseudo-compound selectors=],
with [=compound selectors=] separated by combinators.
It represents a set of simultaneous conditions
on a set of elements in the particular relationships
described by its combinators.
(Complex selectors are represented by <widget.querySelector("a")
will thus only find <{a}> elements inside of the widget
element,
ignoring any other <{a}>s that might be scattered throughout the document.
For example, '':valid'' is a regular pseudo-class, and '':lang()'' is a functional pseudo-class. Like all CSS keywords, pseudo-class names are ASCII case-insensitive. No white space is allowed between the colon and the name of the pseudo-class, nor, as usual for CSS syntax, between a functional pseudo-class’s name and its opening parenthesis (which thus form a CSS function token). Also as usual, white space is allowed around the arguments inside the parentheses of a functional pseudo-class unless otherwise specified. Like other simple selectors, pseudo-classes are allowed in all compound selectors contained in a selector, and must follow the type selector or universal selector, if present. Note: Some pseudo-classes are mutually exclusive (such that a compound selector containing them, while valid, will never match anything), while others can apply simultaneously to the same element.
foo>a
.
h1 { font-family: sans-serif } h2 { font-family: sans-serif } h3 { font-family: sans-serif }is equivalent to:
h1, h2, h3 { font-family: sans-serif }
h1 { font-family: sans-serif } h2..foo { font-family: sans-serif } h3 { font-family: sans-serif }is not equivalent to:
h1, h2..foo, h3 { font-family: sans-serif }because the above selector (''h1, h2..foo, h3'') is entirely invalid and the entire style rule is dropped. (When the selectors are not grouped, only the rule for ''h2..foo'' is dropped.)
*|*:is(:hover, :focus)The following selector, however, represents only hovered or focused elements that are in the default namespace, because it uses an explicit universal selector within the '':is()'' notation:
*|*:is(*:hover, *:focus)
button:not(\[DISABLED])The following selector represents all but FOO elements.
*:not(FOO)The following compound selector represents all HTML elements except links.
html|*:not(:link):not(:visited)
a:not(:hover) { text-decoration: none; } nav a { /* Has no effect */ text-decoration: underline; }However, by using '':where()'' the author can explicitly declare their intent:
a:where(:not(:hover)) { text-decoration: none; } nav a { /* Works now! */ text-decoration: underline; }
<a>
elements that contain an <img>
child:
a:has(> img)The following selector matches a
<dt>
element
immediately followed by another <dt>
element:
dt:has(+ dt)The following selector matches
<section>
elements
that don't contain any heading elements:
section:not(:has(h1, h2, h3, h4, h5, h6))Note that ordering matters in the above selector. Swapping the nesting of the two pseudo-classes, like:
section:has(:not(h1, h2, h3, h4, h5, h6))...would result in matching any
<section>
element
which contains anything that's not a heading element.
*
U+002A) as the local name.
Like a type selector,
the universal selector can be qualified by a namespace,
restricting it to only elements belonging to that namespace,
and is affected by a default namespace as defined in [[#type-nmsp]].
Unless an element is featureless,
the presence of a universal selector has no effect on whether the element matches the selector.
(Featureless elements do not match any selector,
including the universal selector.)
|
U+007C).
(See, e.g., [[XML-NAMES]] for the use of namespaces in XML.)
It has the following meaning in each form:
ns|E
*|E
|E
E
@namespace foo url(http://www.example.com); foo|h1 { color: blue } /* first rule */ foo|* { color: yellow } /* second rule */ |h1 { color: red } /* ...*/ *|h1 { color: green } h1 { color: green }The first rule (not counting the ''@namespace'' at-rule) will match only h1 elements in the "http://www.example.com" namespace. The second rule will match all elements in the "http://www.example.com" namespace. The third rule will match only h1 elements with no namespace. The fourth rule will match h1 elements in any namespace (including those without any namespace). The last rule is equivalent to the fourth rule because no default namespace has been defined.
@namespace url("http://example.com/foo"); .special { ... }The ''.special'' selector only matches elements in the "http://example.com/foo" namespace, even though no reference to the type name (which is paired with the namespace in the DOM) appeared.
p:defined { ... }[=Custom elements=], on the other hand, start out undefined, and only become defined when
custom-element { visibility: hidden }
custom-element:defined { visibility: visible }
Add comma-separated syntax for multiple-value matching? e.g. [rel ~= next, prev, up, first, last]
att
attribute,
whatever the value of the attribute.
att
attribute
whose value is exactly "val".
att
attribute
whose value is a whitespace-separated list of words,
one of which is exactly "val".
If "val" contains whitespace,
it will never represent anything
(since the words are separated by spaces).
Also if "val" is the empty string,
it will never represent anything.
att
attribute,
its value either being exactly "val"
or beginning with "val" immediately followed by "-" (U+002D).
This is primarily intended to allow language subcode matches
(e.g., the hreflang
attribute on the a element in HTML)
as described in BCP 47 ([[BCP47]]) or its successor.
For lang
(or xml:lang
) language subcode matching,
please see the '':lang()'' pseudo-class.
title
attribute,
whatever its value:
h1[title]In the following example, the selector represents a span element whose
class
attribute has
exactly the value "example":
span[class="example"]Multiple attribute selectors can be used to represent several attributes of an element, or several conditions on the same attribute. Here, the selector represents a span element whose
hello
attribute has exactly the value "Cleveland"
and whose goodbye
attribute has exactly the value
"Columbus":
span[hello="Cleveland"][goodbye="Columbus"]The following CSS rules illustrate the differences between "=" and "~=". The first selector would match, for example, an a element with the value "copyright copyleft copyeditor" on a
rel
attribute. The second selector
would only match an a element with an href
attribute having the exact value "http://www.w3.org/".
a[rel~="copyright"] { ... } a[href="http://www.w3.org/"] { ... }The following selector represents an a element whose
hreflang
attribute is exactly "fr".
a[hreflang=fr]The following selector represents an a element for which the value of the
hreflang
attribute begins with
"en", including "en", "en-US", and "en-scouse":
a[hreflang|="en"]The following selectors represent a DIALOGUE element whenever it has one of two different values for an attribute
character
:
DIALOGUE[character=romeo] DIALOGUE[character=juliet]
att
attribute
whose value begins with the prefix "val".
If "val" is the empty string
then the selector does not represent anything.
att
attribute
whose value ends with the suffix "val".
If "val" is the empty string
then the selector does not represent anything.
att
attribute
whose value contains at least one instance of the substring "val".
If "val" is the empty string
then the selector does not represent anything.
object[type^="image/"]The following selector represents an HTML a element with an
href
attribute whose value ends with ".html".
a[href$=".html"]The following selector represents an HTML paragraph with a
title
attribute whose value contains the substring "hello"
p[title*="hello"]
i
before the closing bracket (]
).
When this flag is present,
UAs must match the attribute's value
[=ASCII case-insensitively=]
(i.e. [a-z] and \[A-Z] are considered equivalent).
Alternately, the attribute selector may include the identifier s
before the closing bracket (]
);
in this case the UA must match the value case-sensitively,
with “[=identical to=]” semantics [[INFRA]],
regardless of document language rules.
Like the rest of Selectors syntax,
the i
and s
identifiers themselves
are [=ASCII case-insensitive=].
frame
attribute when it
has a value of hsides
, whether that value is represented
as hsides
, HSIDES
, hSides
, etc.
even in an XML environment where attribute values are case-sensitive.
[frame=hsides i] { border-style: solid none; }
type="a"
attributes differently than type="A"
even though HTML defines the type
attribute
to be case-insensitive.
[type="a" s] { list-style: lower-alpha; } [type="A" s] { list-style: upper-alpha; }
s
flags is only possible
in systems that preserve the original case.
|
). In keeping with
the Namespaces in the XML recommendation, default namespaces do not
apply to attributes, therefore attribute selectors without a namespace
component apply only to attributes that have no namespace (equivalent
to ''|attr''). An asterisk may be used for
the namespace prefix indicating that the selector is to match all
attribute names without regard to the attribute's namespace.
An attribute selector with an attribute name containing a namespace
prefix that has not been previously [=declared=] is
an invalid selector.
@namespace foo "http://www.example.com"; [foo|att=val] { color: blue } [*|att] { color: yellow } [|att] { color: green } [att] { color: green }The first rule will match only elements with the attribute
att
in the "http://www.example.com" namespace with the
value "val".
The second rule will match only elements with the attribute
att
regardless of the namespace of the attribute
(including no namespace).
The last two rules are equivalent and will match only elements
with the attribute att
where the attribute is not
in a namespace.
EXAMPLE
with an attribute radix
that has a default value of "decimal"
. The DTD fragment might be
<!ATTLIST EXAMPLE radix (decimal,octal) "decimal">If the style sheet contains the rules
EXAMPLE[radix=decimal] { /*... default property settings ...*/ } EXAMPLE[radix=octal] { /*... other settings...*/ }the first rule might not match elements whose
radix
attribute is
set by default, i.e. not set explicitly. To catch all cases, the
attribute selector for the default value must be dropped:
EXAMPLE { /*... default property settings ...*/ } EXAMPLE[radix=octal] { /*... other settings...*/ }Here, because the selector ''EXAMPLE[radix=octal]'' is more specific than the type selector alone, the style declarations in the second rule will override those in the first for elements that have a
radix
attribute value of "octal"
. Care has to be taken that
all property declarations that are to apply only to the default case
are overridden in the non-default cases' style rules.
class
attribute: in these languages
it is equivalent to the ~=
notation applied to the
local class
attribute
(i.e. [class~=identifier]
).
class~="pastoral"
as follows:
*.pastoral { color: green } /* all elements with class~=pastoral */or just
.pastoral { color: green } /* all elements with class~=pastoral */The following assigns style only to H1 elements with
class~="pastoral"
:
H1.pastoral { color: green } /* H1 elements with class~=pastoral */Given these rules, the first
H1
instance below would not have
green text, while the second would:
<H1>Not green</H1> <H1 class="pastoral">Very green</H1>The following rule matches any P element whose
class
attribute has been assigned a list of whitespace-separated values that includes both
pastoral
and marine
:
p.pastoral.marine { color: green }This rule matches when
class="pastoral blue aqua
marine"
but does not match for class="pastoral
blue"
.
id
;
XML applications may name ID attributes differently,
but the same restriction applies.
Which attribute on an element is considered the “ID attribute“ is defined by the document language.
An ID selector consists of a “number sign” (U+0023, #
)
immediately followed by the ID value,
which must be a CSS identifier.
An ID selector represents an element instance that has an identifier that matches the identifier in the ID selector.
(It is possible in non-conforming documents for multiple elements to match a single ID selector.)
h1#chapter1The following ID selector represents any element whose ID-typed attribute has the value "chapter1":
#chapter1The following selector represents any element whose ID-typed attribute has the value "z98y".
*#z98y
dir
attribute, the surrounding text, and other factors.
As another example, the its:dir
and dirRule
element
of the Internationalization Tag Set [[ITS20]]
are able to define the directionality of an element in [[XML10]].
The '':dir()'' pseudo-class does not select based on stylistic
states—for example, the CSS 'direction' property does not affect
whether it matches.
The pseudo-class '':dir(ltr)'' represents an element that
has a directionality of left-to-right (ltr
). The
pseudo-class '':dir(rtl)'' represents an element that has
a directionality of right-to-left (rtl
). The argument to
'':dir()'' must be a single identifier, otherwise the selector
is invalid. White space is optionally allowed between the identifier
and the parentheses. Values other than ltr
and
rtl
are not invalid, but do not match anything. (If a
future markup spec defines other directionalities, then Selectors may
be extended to allow corresponding values.)
The difference between '':dir(C)'' and ''[dir=C]''
is that ''[dir=C]'' only performs a comparison against a given
attribute on the element, while the '':dir(C)'' pseudo-class
uses the UAs knowledge of the document's semantics to perform the
comparison. For example, in HTML, the directionality of an element
inherits so that a child without a dir
attribute will have
the same directionality as its closest ancestor with a valid dir
attribute. As another example, in HTML,
an element that matches ''[dir=auto]'' will match either
'':dir(ltr)'' or '':dir(rtl)'' depending on the resolved
directionality of the elements as determined by its contents. [[HTML5]]
lang
attribute,
information from meta elements,
and possibly also the protocol (e.g. from HTTP headers).
XML languages can use the xml:lang
attribute
to indicate language information for an element. [[XML10]]
The element's content language matches a language range if
its content language, as represented in BCP 47 syntax,
matches the given language range in an extended filtering
operation per [[!RFC4647]] Matching of Language Tags (section 3.3.2).
Both the [=content language=] and the [=language range=]
must be canonicalized
and converted to extlang form as per section 4.5 of [[!RFC5646]]
prior to the extended filtering operation.
The matching is performed case-insensitively within the ASCII range.
The language range does not need to be a valid language code to
perform this comparison.
A [=language range=] consisting of an empty string
('':lang("")'')
matches (only) elements whose language is not tagged.
Note: It is recommended that documents and protocols
indicate language using codes from [[BCP47]] or its successor,
and in the case of XML-based formats, by means of xml:lang
attributes. [[XML10]]
See “FAQ: Two-letter or three-letter language codes.”
html:lang(fr-be) html:lang(de) :lang(fr-be) > q :lang(de) > q
<body lang=fr> <p>Je suis français.</p> </body>
:any-link
.
It matches an element if the element would match either '':link'' or '':visited'',
and is equivalent to '':is(:link, :visited)''.
footnote
and already visited:
.footnote:visited
nav :local-link { text-decoration: none; }
pushState
API;
as well as by the more obvious actions of navigating to a different page
or following a redirect (which could be initiated by protocols such as HTTP,
markup instructions such as <meta http-equiv="...">
,
or scripting instructions ).
UAs must ensure that '':local-link'',
as well as the '':target'' and '':target-within'' pseudo-classes below,
respond correctly to all such changes in state.
https://example.com/index.html#section2
,
for example,
points to the element with id="section2"
in the document at https://example.com/index.html
.
p.note:targetThis selector represents a <{p}> element of class
note
that is the target element of the referring
URL.
:target { color : red } :target::before { content : url(target.png) }
df
,
then df.querySelectorAll(":scope > .foo")
matches all the ''.foo'' elements that are "top-level" in the document fragment
(those that have the document fragment as their {{Node/parentNode}}).
However, df.querySelector(":scope")
will not match anything,
as the document fragment itself can't be the [=subject of the selector=].
a:hover /* user hovers over the link */ a:focus /* user focuses the link */ a:focus:hover /* user hovers over the link while it's focused */
:hover
when its label is hovered.
Note: Since the '':hover'' state can apply to an element
because its child is designated by a pointing device,
it is possible for '':hover'' to apply
to an element that is not underneath the pointing device.
:root { --focus-gold: #ffbf47; } :focus-visible { outline: 3px solid var(--focus-gold); } a:focus-visible { background-color: var(--focus-gold); }
:current(p, li, dt, dd) { background: yellow; }
<input>
element is '':read-write'',
as is any element with the contenteditable
attribute set to the true state.
placeholder
attribute in [[HTML5]].
The :placeholder-shown pseudo-class
matches an input element that is showing such placeholder text,
whether that text is given by an attribute or a real element,
or is otherwise implied by the UA.
<option>
(s) in a <select>
,
and a few other elements.
<option>
elements match '':checked''.
While the '':checked'' pseudo-class is dynamic in nature,
and can altered by user action,
since it can also be based on the presence of semantic attributes in the document
(such as the selected
and checked
attributes in [[HTML5]]),
it applies to all media.
input[type=checkbox]:not(:checked)
<input type=text>
when its value is empty.)
* If it sometimes submits, and is set to not submit, it matches '':blank''.
(Such as HTML’s <input type=checkbox>
when not checked.)
* If it's an “action button”
(rather than a “toggle button” that represents a state)
such as <button>
, <input type=submit>
, etc.,
it never matches '':blank''.
Host languages can specify more precise rules
for when form controls match '':blank''.
<input type="text">
element may have no constraints,
but a p element has no validity semantics at all,
and so it never matches either of these pseudo-classes.
<form> <label> Volume: <input name='vol' type=number min=0 max=10 value=11> </label> ... </form>
<p></p> <p> <p> </p> <p></p>''div:empty'' is not a valid representation of the
<div>
elements
in the following fragment:
<div>text</div> <div><p></p></div> <div> </div> <div><p>bla</p></div> <div>this is not <p>:empty</p></div>
n=0
the expression evaluates to ''1''.
For example, this selector could address every other row in a table,
and could be used to alternate the color of paragraph text in a cycle of four.
:nth-child(even) /* represents the 2nd, 4th, 6th, etc elements :nth-child(10n-1) /* represents the 9th, 19th, 29th, etc elements */ :nth-child(10n+9) /* Same */ :nth-child(10n+-1) /* Syntactically invalid, and would be ignored */
:nth-child(-n+3 of li.important)Note that this is different from moving the selector outside of the function, like:
li.important:nth-child(-n+3)This selector instead just selects the first three children if they also happen to be "important" list items.
tr { background: white; } tr:nth-child(even) { background: silver; }However, if some of the rows are hidden and not displayed, this can break up the pattern, causing multiple adjacent rows to have the same background color. Assuming that rows are hidden with the ''[hidden]'' attribute in HTML, the following CSS would zebra-stripe the table rows robustly, maintaining a proper alternating background regardless of which rows are hidden:
tr { background: white; } tr:nth-child(even of :not([hidden])) { background: silver; }
tr:nth-last-child(-n+2) /* represents the two last rows of an HTML table */ foo:nth-last-child(odd) /* represents all odd foo elements in their parent element, counting from the last one */
div > p:first-childThis selector can represent the
p
inside the
div
of the following fragment:
<p> The last P before the note.</p> <div class="note"> <p> The first P inside the note.</p> </div>but cannot represent the second
p
in the following fragment:
<p> The last P before the note.</p> <div class="note"> <h2> Note </h2> <p> The first P inside the note.</p> </div>The following two selectors are usually equivalent:
* > a:first-child /* a is first child of any element */ a:first-child /* Same (assuming a is not the root element) */
li
that
is the last child of an ordered list ol
.
ol > li:last-child
html
namespace is declared).
img:nth-of-type(2n+1) { float: right; } img:nth-of-type(2n) { float: left; }
html
namespace is declared).
h2
children of an XHTML
body
except the first and last, one could use the
following selector:
body > h2:nth-of-type(n+2):nth-last-of-type(n+2)In this case, one could also use '':not()'', although the selector ends up being just as long:
body > h2:not(:first-of-type):not(:last-of-type)
dt
inside a definition list dl
, this
dt
being the first of its type in the list of children of
its parent element.
dl dt:first-of-typeIt is a valid description for the first two
dt
elements in the following example but not for the third one:
<dl> <dt>gigogne</dt> <dd> <dl> <dt>fusée</dt> <dd>multistage rocket</dd> <dt>table</dt> <dd>nest of tables</dd> </dl> </dd> </dl>
td
of a table row tr
.
tr > td:last-of-type
)B
that is an
arbitrary descendant of some ancestor element A
.
h1 emIt represents an em element being the descendant of an h1 element. It is a correct and valid, but partial, description of the following fragment:
<h1>This <span class="myclass">headline is <em>very</em> important</span></h1>The following selector:
div * prepresents a p element that is a grandchild or later descendant of a div element. Note the whitespace on either side of the "*" is not part of the universal selector; the whitespace is a combinator indicating that the
div
must be the
ancestor of some element, and that that element must be an ancestor
of the p
.
The following selector, which combines descendant combinators and
attribute selectors, represents an
element that (1) has the href
attribute set and (2) is
inside a p
that is itself inside a div
:
div p *[href]
>
)body
:
body > pThe following example combines descendant combinators and child combinators.
div ol>li pIt represents a p element that is a descendant of an li element; the li element must be the child of an ol element; the ol element must be a descendant of a
div
. Notice that the optional white
space around the ">" combinator has been left out.
+
)math + pThe following selector is conceptually similar to the one in the previous example, except that it adds an attribute selector — it adds a constraint to the h1 element, that it must have
class="opener"
:
h1.opener + h2
~
)h1 ~ prerepresents a pre element following an
h1
. It
is a correct and valid, but partial, description of:
<h1>Definition of the function a</h1> <p>Function a(x) has to be applied to all figures in the table.</p> <pre>function a(x) = 12x/13.5</pre>
||
)col.selected || td { background: gray; color: white; font-weight: bold; }
<table> <col span="2"> <col class="selected"> <tr><td>A <td>B <td>C <tr><td colspan="2">D <td>E <tr><td>F <td colspan="2">G </table>
n
. Column membership is determined
based on the semantics of the document language only: whether and how the
elements are presented is not considered. If a cell element belongs to
more than one column, it is represented by a selector indicating any of
those columns.
The CSS Syntax Module [[!CSS3SYN]] defines the An+B notation.
n
. Column membership is determined
based on the semantics of the document language only: whether and how the
elements are presented is not considered. If a cell element belongs to
more than one column, it is represented by a selector indicating any of
those columns.
The CSS Syntax Module [[!CSS3SYN]] defines the An+B notation.
<em>
, <p id=foo>
, or <em id=foo>
.
<li>
, <ul class=item>
, or <li class=item id=foo>
.
* /* a=0 b=0 c=0 */ LI /* a=0 b=0 c=1 */ UL LI /* a=0 b=0 c=2 */ UL OL+LI /* a=0 b=0 c=3 */ H1 + *[REL=up] /* a=0 b=1 c=1 */ UL OL LI.red /* a=0 b=1 c=3 */ LI.red.level /* a=0 b=2 c=1 */ #x34y /* a=1 b=0 c=0 */ #s12:not(FOO) /* a=1 b=0 c=1 */ .foo :is(.bar, #baz) /* a=1 b=1 c=0 */
style
attribute
is described in CSS Style Attributes. [[CSSSTYLEATTR]]
<selector-list> = <In interpreting the above grammar, the following rules apply:> <complex-selector-list> = < ># <complex-real-selector-list> = < ># <compound-selector-list> = < ># <simple-selector-list> = < ># <relative-selector-list> = < ># <relative-real-selector-list> = < ># <complex-selector> = < > [ < >? < > ]* <complex-selector-unit> = [ < >? < >* ]! <complex-real-selector> = < > [ < >? < > ]* <relative-selector> = < >? < > <relative-real-selector> = < >? < > <compound-selector> = [ < >? < >* ]! <pseudo-compound-selector> = < > < >* <simple-selector> = < > | < > <combinator> = '>' | '+' | '~' | [ '|' '|' ] <wq-name> = < >? < > <ns-prefix> = [ < > | '*' ]? '|' <type-selector> = < > | < >? '*' <subclass-selector> = < > | < > | < > | < > <id-selector> = < > <class-selector> = '.' < > <attribute-selector> = '[' < > ']' | '[' < > < > [ < > | < > ] < >? ']' <attr-matcher> = [ '~' | '|' | '^' | '$' | '*' ]? '=' <attr-modifier> = i | s <pseudo-class-selector> = ':' < > | ':' < > < > ')' <pseudo-element-selector> = ':' < > | < > <legacy-pseudo-element-selector> = ':' [before | after | first-line | first-letter]
The four Level 2 pseudo-elements
(''::before'', ''::after'', ''::first-line'', and ''::first-letter'')
may, for legacy reasons,
be written with only a single ":" character at their front,
making them resemble a <
<
For legacy reasons,
the general behavior of a selector list
is that if any selector in the list fails to parse
(because it uses new or UA-specific selector features, for instance),
the entire selector list becomes invalid.
This can make it hard to write CSS that uses new selectors
and still works correctly in older user agents.
The <<
.
It is then [=parsed as a forgiving selector list=]
to obtain its actual value.
API Hooks
To aid in the writing of specs that use Selectors concepts,
this section defines several API hooks that can be invoked by other specifications.
Issue: Are these still necessary now that we have more rigorous definitions for match and invalid selector?
Nouns are a lot easier to coordinate across specification than predicates,
and details like the exact order of elements returned from querySelector
seem to make more sense being defined in the DOM specification than in Selectors.
Parse A Selector
This section defines how to parse a selector from a string source.
It returns either a complex selector list,
or failure.
Parse A Relative Selector
This section defines how to parse a relative selector from a string source.
It returns either a complex selector list,
or failure.
Match a Selector Against an Element
This section defines how to match a selector against an element.
APIs using this algorithm must provide a selector and an element.
Callers may optionally provide:
This algorithm returns either success or failure.
For each complex selector in the given selector
(which is taken to be a list of complex selectors),
match the complex selector against element,
as described in the following paragraph.
If the matching returns success for any complex selector,
then the algorithm return success; otherwise it returns failure.
To match a complex selector against an element,
process it compound selector at a time,
in right-to-left order.
This process is defined recursively as follows:
Match a Selector Against a Pseudo-element
This section defines how to match a selector against a pseudo-element.
APIs using this algorithm must provide a selector
and a pseudo-element.
They may optionally provide the same things they may optionally provide
to the algorithm to match a selector against an element.
This algorithm returns success or failure.
For each complex selector in the given selector, if both:
then return success.
Otherwise
(that is, if this doesn't happen for any of the complex selectors in selector),
return failure.
Match a Selector Against a Tree
This section defines how to match a selector against a tree.
APIs using this algorithm must provide a selector,
and one or more root elements
indicating the [=tree|subtrees=] that will be searched by the selector.
All of the root elements must share the same [=tree/root=],
or else calling this algorithm is invalid.
They may optionally provide:
This algorithm returns a (possibly empty) list of elements.
Appendix A: Guidance on Mapping Source Documents & Data to an Element Tree
This section is informative.
The element tree structure described by the DOM is powerful and useful,
but generic enough to model pretty much any language that describes tree-based data
(or even graph-based, with a suitable interpretation).
Some languages, like HTML, already have well-defined procedures
for producing a DOM object from a resource.
If a given language does not,
such a procedure must be defined
in order for Selectors to apply to documents in that language.
At minimum,
the document language must define what maps to the DOM concept of an "element".
The primary one-to-many relationship between nodes--
parent/child in tree-based structures,
element/neighbors in graph-based structures--
should be reflected as the child nodes of an element.
Other features of the element should be mapped
to something that serves a similar purpose to the same feature in DOM:
This structure is sufficient to allow powerful, compact querying of JSON documents with selectors.
Appendix B: Obsolete but Required
This appendix is normative.
Due to legacy Web-compat constraints,
user agents expecting to parse Web documents must support the following features:
* '':-webkit-autofill'' must be treated as a [=legacy selector alias=] of '':autofill''.
* All other [=pseudo-elements=] whose names begin with the string “-webkit-”
(matched ASCII case-insensitively)
and that are not functional notations
must be treated as valid at parse time.
(That is, -webkit-
Parsing Quirks for Web CompatWhat's this quirk about?
Selectors have long had a behavior
where a single unknown/invalid selector
invalidates the entire selector list
(rather than just invalidating the one complex selector it finds itself in).
This is generally considered a legacy mistake by the WG,
but can't be fixed at this point,
as too many stylesheets depend on this behavior,
intentionally or not.
One aspect of this is that use of vendor-specific selectors
invalidates the entire selector in other user agents
that don't recognize them,
and takes the entire style rule down with it.
This has been used intentionally in the past--
in the severely-not-recommended practice of hiding style rules from some browsers
by making them invalid in every other browser--
and unintentionally,
with people styling an element
and also applying those styles to a vendor-specific pseudo-element
(such as the various <{input}>-related pseudos some browsers expose),
not realizing that this hides the entire rule from other browsers.
In addition to this more general reasoning,
WebKit-derived user agents,
such as Safari or Chrome,
have an additional quirk related to their vendor-prefixed pseudo-elements,
where any
Changes
Changes since the 7 May 2022 Working Draft
Significant changes since the 7 May 2022 Working Draft:
* Marked '':blank'' as at-risk and removed the at-risk status from '':read-write'' and '':has()''
* Added '':open'' and '':closed'' pseudo-classes.
(Issue 7319)
* Disallowed [=pseudo-elements=] from '':has()'' unless explicitly allowed
by the pseudo-element’s definition.
(Issue 7463)
* Disallowed nesting of '':has()''.
(Issue 7344)
* Made '':has()'' and the selector argument of '':nth-child()''/'':nth-last-child()''
no longer forgiving.
(Issue 7676)
* Defined matching of ''::lang("")'' and of elements not tagged with a language.
(Issue 6915)
* Untangled the concepts of "scoped" and "relative" selectors completely.
(Issue 6399)
* Removed "absolutize a selector" as well,
and just defined relative selector matching
in terms of the anchoring element.
* Reverted compound selector limitation on '':nth-child()''.
(Issue 3760)
* Defined '':-webkit-autofill'' [=legacy selector alias=].
(Issue 7474)
* Moved the legacy single-colon pseudo-element syntax into the grammar itself.
(Issue 8122)
Changes since the 21 November 2018 Working Draft
Significant changes since the 21 November 2018 Working Draft:
Changes since the 2 February 2018 Working Draft
Significant changes since the 2 February 2018 Working Draft:
s
to the attribute selector.
(Issue 2101)
Changes since the 2 May 2013 Working Draft
Significant changes since the 2 May 2013 Working Draft include:
Note: The 1 February 2018 draft included an inadvertent commit of unfinished work;
2 February 2018 has reverted this commit (and fixed some links because why not).
:local-link()
pseudo-class and reference combinator for lack of interest.
Changes since the 23 August 2012 Working Draft
Significant changes since the 23 August 2012 Working Draft include:
Changes since the 29 September 2011 Working Draft
Significant changes since the 29 September 2011 Working Draft include:
Changes Since Level 3
Additions since Level 3:
Acknowledgements
The CSS working group would like to thank everyone who contributed
to the previous Selectors specifications over the years,
as those specifications formed the basis for this one.
In particular, the working group would like to extend special thanks
to the following for their specific contributions to Selectors Level 4:
L. David Baron,
Andrew Fedoniouk,
Daniel Glazman,
Ian Hickson,
Grey Hodge,
Lachlan Hunt,
Anne van Kesteren,
Jason Cranford Teague,
Lea Verou
Privacy Considerations
Security Considerations
The Privacy Considerations
could also be considered to affect Security.