Universal selector
Match all non-pseudo-elements with *
. So, to set all non-pseudo-elements in sans serif, use * { font-family: sans-serif; }
Match all non-pseudo-elements with *
. So, to set all non-pseudo-elements in sans serif, use * { font-family: sans-serif; }
Match the <dt>
element with the dt
selector, so you can say this: dt { text-transform: uppercase; }
, and get this:
Match elements with the class name .cls-bigger
Match an element that is both
.cls-bigger
and .cls-blue
with the multiple class selector .cls-bigger.cls-blue
. In this case let's italicise it with .cls-bigger.cls-blue {font-style: italic; }
Use the selector #me
to match an element with an id of me
.
Match an element assigned the attribute data-hello-world
with the selector [data-hello-world]
. This will match no matter what the value of the attribute, or even if the attribute doesn't have a value.
data-hello-world="true"
matches;data-hello-world="false"
matches;data-hello-world="unicorns"
matches, anddata-hello-world
also matches.Match those elements with the attribute data-highlight-color
set to the value "blue" or e.g. "BLUE" (or any other case variation of the same string) using the selector [data-highlight-color="blue" i]
data-highlight-color="blue"
data-highlight-color="BLUE"
Only match those elements with the attribute data-highlight-color
set to the value "RED" but not, e.g. "red" (nor any other case variation of the same string), using the selector [data-highlight-color="RED"]
:
data-highlight-color="red"
data-highlight-color="RED"
Note that case sensitivity can be explicitly specified with the selector [data-highlight-color="RED" s]
under level 4, but not sure why you'd want to.
Make the text green if "grass" is a word (a whitespace-separated string) in the value of the data-ground-type
attribute, by matching [data-ground-type~="grass"]
data-ground-type="grass outside"
and matchesdata-ground-type="outside grass"
and matchesdata-ground-type="outside grass garden"
and matchesdata-ground-type="outside patio"
and doesn't matchMatch fully qualified links with [href^="http"]
Match links ending in ".pdf" with [href$=".pdf"]
Match links containing the string "untrusted" in their path with [href*="untrusted"]
.
Browse the safe content with confidence, but be careful of the untrusted content.
Used mainly for the use case: matching of elements with any en
value of hreflang
.
Match any <span>
living anywhere inside a <ul>
, with ul span
.
ul
.ul
, so am not italic.
Match any child <p>
of .parent
, but none nested more deeply, by using .parent > p
, in this case turning it steel blue.
The <p>
in <div class="parent"><p>...</p></div>
is a child of .parent
, so this matches.
The <p>
in <div class="parent"><div><p>...</p></div></div>
is not a child of .parent
, so this doesn't match.
Match a target element that immediately follows a specified sibling with immediately-preceding-sibling-selector + target-selector
Match one or more targets that follow a specified sibling with preceding-sibling-selector ~ target
.
Match a target within the specified column of a table or grid. No implementations yet in 2020, more details on MDN.
:is
(used to be called :matches
), takes a list of elements, any one of which will cause a match. Here, elements selected with :is(span, q)
are coloured blue:
matching span
and I'm a matching q
, but I'm a non-matching i
.
Note that unlike the usual parsing rules of CSS, the selector list within is
is forgiving: if a selector within is
is not recognised by the browser, rather than invalidating the entire selector containing is
, only the individual invalid selector within is
is ignored.
is
takes the specificity of the most specific selector in its arguments.
:where
always has a specificity of 0, but otherwise is identical to :is
.
:has
takes a selector list as an argument and matches the selector it's bound to when any selector in the list matches. This could easily be used to match an element based on its descendants. Before level 4 this was not possible in CSS. Unfortunately as of Jan 2021 there is no browser support yet, but you can
keep an eye on it.
:not
matches elements that do not match the supplied selector or selector list. Note that you can't pass pseudo-elements, they won't work with :not
. Browser support is good for passing a single selector; if you want to pass a selector list (this is the level 4 addition),
check browser support.
To match all but the third child in the list, use li:not( :nth-child(3) )
You can chain individual single selector :not
s together to get some of the effect of a selector list, for example to match all but the first and last list items, you can use li:not(:first-child):not(:last-child)
To match all but the first and last list items, as above but using a selector list instead of multiple :not
clauses, use li:not( :first-child, :last-child)
:root
matches the root element. Can also use <html>
in html docs, but :root
is necessary for other doc types e.g. XML, SVG etc.
:empty
matches empty elements. N.B. element nodes and text nodes (including whitespace) prevent a containing element from being empty. Comment nodes do not prevent their parent element from being empty.
Here, empty list items have a background pattern applied.
Selectors level 3 describes this type of matching as being based on the index of the target element relative to its parent, as encapsulated in the inclusion of "child" in some of the pseudo-class names. Selectors level 4 allows for a non-element parent, or no parent at all, by describing an element's relative index with respect to its siblings. Language in this section refers to "child" to match the pseudo class names, but if you're in a level 4 implementation, the implied parent is not a requirement.
Note that indices are always 1-indexed.
:only-child
matches if an element is the only child element of its parent.
In this paragraph, I am the only child element, so I match, (it doesn't matter what type of element I am).
In this paragraph, there is more than one child, both here and here, so the :only-child
selector doesn't find a match.
:only-of-type
matches an element of specified type that is the only child element of that type of its parent. Here we're using span:only-of-type
to target <span>
elements that are the only span element of their parents:
In this paragraph, this <span>
, and , are the only child elements of their respective types, so the span:only-child-of-type
selector matches the span but not the label.
In this paragraph, both this <span>
, and this <span>
, are child elements of the same parent, so the selector doesn't match.
:first-child
matches an element that is the first child of its parent.
:first-of-type
matches an element that is the first child element of its type, (it needn't be the first overall element child). Here we're using span:first-of-type
to select the first <span>
element.
This paragraph contains a , this first <span>
which matches, and this second <span>
, which doesn't.
:last-child
is the converse of :first-child
.
:last-of-type
is the converse of :first-of-type
.
This paragraph contains a , this first <span>
which doesn't match, and this second <span>
, which does.
Some of these function-like pseudo-elements are invoked with (An+B)
, which can be useful to match a specific child, or all child elements at regularly spaced intervals. Child-indexed pseudo-class selectors using this microsyntax match a child element when its index is the result of the evaluation of terms inside the parentheses. You can think of the child list as being is divided into A
groups (the last group also containing any remainder), and it's the B
th element of each group that is matched.
For An+B
, n
is a literal representing consecutive integers between 0 and the number of child elements, A
represents a multiple of n
, and B
is an integer offset which may be positive, negative, or 0.
A
is 0 it may be omitted, so the expression becomes (B)
, which will match exactly one element with that index (if a child element of the specified index exists).A
is 1 or -1, it may be omitted, as long as the correct sign is applied to n
, so that 1n
becomes n
and -1n
becomes -n
.(An)
, which will match every Ath child element.(An-B)
Just a few of the things you can do with this are shown as examples below:
Counts from the beginning of the list of child elements.
S
represents a user-supplied selector list used to scope the child list, think of it as a more flexible version of :nth-of-type
where you're not restricted to scoping by the type of the child element. [Note that as at December 2020, only Safari supports of S
, so the scoping isn't ready for prime time yet, but keep an eye on the
browser support.
:nth-child(2)
will match exactly the second child.
:nth-child(-n+4)
will match the first four children.
:nth-child(2n)
will match every other child, starting with the second. (Note that 2n
is aliased to even
, so the more readable :nth-child(even)
may be preferred.)
:nth-child(2n+1)
will match every other child, starting with the first. (Note that 2n+1
is aliased to odd
, so the more readable :nth-child(odd)
may be preferred.)
:nth-child(3n+2)
will match the second child, then every third one after that.
The same as :nth-child
, but counting from the end rather than the beginning of the list of child elements.
As :nth-child
, but only elements of the element type to match are included in the evaluation of the child count. It is more specific than :nth-child
.
As :nth-last-child
, but only elements of the element type to match are included in the evaluation of the child count. It is more specific than :nth-last-child
.
These are used to target the Shadow host from within the Shadow DOM CSS. Shouldn't really be possible as the Shadow host is outside of the Shadow root, but there are good reasons for it. Basically, Shadow hosts are weird.
:host
matches the Shadow tree's Shadow host.
::host(selector)
matches the Shadow tree's Shadow host if it also matches the selector.
:host-context(selector)
matches a Shadow host if it, or one of its Shadow-including ancestors matches the selector (meaning that this selector pierces Shadow boundaries in its upward search). Browser support patchy (Jan 2021), so
check before you use.
:link
matches any unvisited <a>
.:visited
matches any visited <a>
.:local-link
matches any reflexive link within the current document. If the href
includes a fragment identifier, this must be matched in the document's URL for the selector to match. No browser support data available as of 2020.:any-link
matches any <a>
, <area>
or <link>
with an href
attribute.:target
matches the element referenced by the document URL's fragment identifier, if any.:target-within
matches when an element, or a descendant element, is referenced by the document URL's fragment identifier, if any. (This is a rare example in CSS of being able to style an ancestor based on a descendant. No browser support yet as of 2020).:scope
only useful with JavaScript since <style scoped>
currently lacks browser support. I've not seen a compelling reason to use it yet.Note that privacy concerns may cause a browser to disregard developer-supplied :link
/ :visited
styles. In that case it should still style them differently from each other.
:hover
remember not all input modes are capable of hovering:active
for example, the state of a link between the time the mouse button is depressed to start to click on it, and the time that the button is released.:focus
matches the currently focused element.
:focus-within
matches an element when that element is an ancestor of the currently focused element. Note that focus-within
is a rare example in CSS of being able to style an ancestor depending on the state of a descendant. [Well, okay, in theory there's :has()
, but no browser supports that as of Jan 2021.]
This next form uses focus-visible
rather than focus
. This allows the user agent to use heuristics to determine whether to apply the rules or not, based on whether it seems that the user needs to know where the focus is. One example is navigation mode: both tabbing through and clicking on text inputs and buttons will result in any focus
styles being used, whereas if you specify focus-visible
instead, the browser decides whether or not to show them when the element receives focus. This is a good thing as clicking on a button and seeing a big outline appear unnecessarily on it can be ugly.
Check browser support.
Matches an interactive element that's explicitly disabled.
Matches an interactive element that's not explicitly disabled.
Matches an element that's user-alterable.
Matches an element that's not user-alterable.
I'm not alterable by the user.
Matches an element that's currently displaying its placeholder. Note the difference compared to the pseudo-element
::placeholder
, which matches the placeholder text itself.
Showing a placeholder:
Not showing a placeholder:
Matches the default element in a set of radio buttons or checkboxes, the initially selected
<option>
element , and form's default submit button.
Matches checked checkboxes and radio buttons, and selected
<option>
elements.
:indeterminate
matches a radio <input>
element where no radio buttons are selected, and also a <progress>
element that lacks a value
attribute. A checkbox <input>
element may match :indeterminate
if its IDL :indeterminate
property is set to true. Not sure in practice when that happens, but there's
some details in the WHATWG spec.
Here, matching :indeterminate
elements have a teal border.
Click on the progress indicator below to toggle the presence of a value
attribute:
Matches a form element whose value is required or optional, respectively.
:valid
matches <input>
and <form>
elements that validate successfully.
:invalid
matches elements that don't validate successfully. Elements without validity semantics can neither be
:valid
nor :invalid
.
Applies to form control elements with data range limits range limits.
A validation failure matching one of the above failure states, but only after the user has attempted to submit the form, and before they have interacted with it again. But also at other times too, at the discretion of the user-agent. No browser support yet as of Jan 2021.
Matches a user-input element that has no contents (not the same as :empty
, which matches an element without any non-comment child nodes). Note that this is not supported in any browser and is marked as "at risk".
Relate to currently displayed, or active position, in some timeline. Might be used for highlighting the currently spoken phrase from VTT, for example. No browser support information available.
Note that :playing
includes situations when the user intent is that the media is playing, even if it currently isn't, for example if the resource stream is buffering. :paused
includes the state before playing has been activated by the user.
matches elements of the specified language. In contrast with the lang attribute selector, this :lang
pseudo element takes many document methods of language specification into account (including the lang attribute).
Make Portuguese text a different color:
Left-to-right languages ara matched with dir(ltr)
, right-to-left languages are matched with dir(rtl)
. This is superior to [dir="ltr"]
/ [dir="rtl"]
as the pseudo-class matching includes the browser's knowledge of document semantics. Stylistic states are not used in the matching, so the CSS direction
property is irrelevant here.
Only supported in Firefox as at Jan 2021. Experience teaches this is difficult but not impossible to provide some fallback for (using the [dir]
attribute selector). It can get gnarly if you're trying to cater for the possibility of nested language direction changes.
Pseudo-elements are featureless, and so aren't matched by any other selector.
As pseudo-elements don't modify the document tree, they do not affect the interpretation of structural pseudo-classes.
User action pseudo-classes are the only type of pseudo-classes that may be compounded to a pseudo-element, and then only if the definition of that user action pseudo-class permits it.
Only pseudo-elements defined to have internal structure may be followed by descendant combinators.
::first-letter
matches the first letter within an element.
"First-letter" needn't be an actual letter, it refers to the first typographical letter unit on the first formatted line, so could be a digit, for example. It also includes any preceding punctuation and interleaving space. As ::first-letter
is always contained within ::first-line
if it exists, ::first-letter
can inherit from ::first-line
.
::first-line
matches the first letter within an element.
The first line of this paragraph is always going to be bold, no matter how long it is. If you resize the viewport, you will still be able to see the first line of this paragraph emboldened. That's how it works.
Only a limited subset of CSS properties are usable to style ::first-line
.
Only a very few properties may be set on these. They mustn't affect layout, and must be performant.
:selection
refers to content selected to be the target or object of a future user interaction.
::selection
.::target-text
represents text directly targeted by the document URL's fragment. Not totally clear what this means. See the
W3C reference. There is no browser support as of Jan 2021, but Chrome has expressed an intent to ship. When it's out, the possibilities will become clear.
One thing that is clear in the spec is that because of privacy concerns the page must not be able to read the styling of these pseudo-elements (similar to :visited
.)
What you'd expect. No browser support as of Jan 2021.
Generates an element immediately before the originating element, containing the value specified in the content
property (not generated if the value is none
).
Generates an element immediately after the originating element, containing the value specified in the content
property (not generated if the value is none
).
::marker
represents the marker box of a list item. Limited CSS properties available. Some browser support, so consider an enhancement.
::placeholder
represents the text displayed as the placeholder. Compare this to the
:placeholder-shown
pseudo-class which selects elements that are displaying placeholder text. Limited to the same CSS properties as ::first-line
.
This works in Firefox, but Webkit / Blink currently implement the non-standard ::-webkit-file-upload-button
(Jan 2021).
Used without the optional selector, ::cue
styles a WebVTT track's cues as if they were a single unit, except background styling, which is applied individually Good browser support.
::cue(selector)
lacks Firefox support, so be careful.
Not entirely sure what the practical difference is between this and ::cue
. No browser support info, so prolly not worth worrying about atm (Jan 2021).
Shadow hosts may use the HTML attribute part
to expose selected Shadow tree elements outside of the Shadow root. The ::part
pseudo-element allows them to be styled by page-level CSS. For example, if a Shadow element is exposed with part="foo"
, then the page CSS may style it with ::part(foo)
.
::part
with pseudo-classes is available, but only with those that use local element information, not those that are structural.
Good browser support.
If you're really digging into this, this
more detailed explainer of ::part
may be useful. Note that it's from Jan 2019, so parts (ha!) may be out of date (I can't find any other references to ::theme
, for example, so this may have been dropped?).
Also, remember that CSS custom properties pierce the Shadow boundary so could be used in conjunction with these.
::slotted(selector)
, when used by Shadow DOM CSS, targets (only) element nodes placed into HTML template slots, which also match the specified selector.