Pseudo-classes

A pseudo-class, written with one colon, selects elements by something other than their name, class or attributes: their state, their position in the tree, how the user is interacting with them, or a condition given as an argument. Each one adds 0,1,0 to specificity unless noted. Parts of an element, such as ::before, are under Pseudo-elements; the selectors pseudo-classes attach to are under Basic selectors and Combinators.

Logical

:is()

Matches any element that matches at least one selector in its list. It shortens repeated selectors, and because its list is forgiving, an invalid or unsupported selector inside it is ignored instead of dropping the whole rule.

Syntax:is( <forgiving-selector-list> )
SpecificityThat of its most specific argument
SupportChrome 88 · Firefox 78 · Safari 14
Specselectors-4

Pseudo-elements cannot appear inside :is(), so :is(::before, ::after) matches nothing.

:is(article, aside) :is(h2, h3) { margin-block-start: 0; }
Four selector combinations in one.

:where()

Works exactly like :is() but adds nothing to specificity, so anything written with it is easy to override. Useful for defaults and resets.

Syntax:where( <forgiving-selector-list> )
SpecificityAlways 0,0,0
SupportChrome 88 · Firefox 78 · Safari 14
Specselectors-4
:where(ul, ol)[role=list] { list-style: none; }
A reset that any later class selector can override.

:not()

Matches elements that do not match any selector in its list. The list is not forgiving: one invalid selector makes the whole :not() invalid.

Syntax:not( <complex-real-selector-list> )
SpecificityThat of its most specific argument
SupportChrome 1 · Firefox 1 · Safari 3.1
Selector lists and complex selectors: Chrome 88 · Firefox 84 · Safari 9
Specselectors-4
li:not(:last-child) { border-block-end: 1px solid; }
A divider under every item except the last.

:has()

Matches an element if any of its relative selectors matches something when measured from that element. With no leading combinator it looks at descendants; with >, + or ~ it looks at children or following siblings. This lets you style a parent by its contents, or an element by what comes after it.

Syntax:has( <relative-selector-list> )
SpecificityThat of its most specific argument
SupportChrome 105 · Firefox 121 · Safari 15.4
Specselectors-4

:has() cannot be nested inside another :has(), and pseudo-elements are not allowed in its argument. Its list is not forgiving.

figure:has(figcaption) { padding-block-end: 0; }
h2:has(+ p) { margin-block-end: 0.5rem; }
form:has(:user-invalid) button { opacity: 0.5; }
A figure with a caption, an h2 followed by a paragraph, a form containing an invalid field.

Location & links

:visited

Matches hyperlinks the user has already visited. To protect browsing history, only colour-related properties can be changed, and scripts reading the computed style see the unvisited values.

Syntax:visited
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4

:target

Matches the element whose id matches the fragment of the page URL, such as the element with id="faq" at page.html#faq. If the URL has no fragment, nothing matches.

Syntax:target
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 1.3
Specselectors-4
:target { scroll-margin-block-start: 4rem; outline: 2px solid; }
Highlight the section a link jumped to, clear of a sticky header.

:target-current

Matches the active scroll marker in a scroll marker group: the ::scroll-marker (or anchor link in a scroll-marker-group) whose target is currently scrolled into view. Use it to highlight the current dot or tab of a carousel.

Syntax:target-current
Specificity0,1,0 (one pseudo-class)
SupportChrome 135 · Firefox no · Safari no
Speccss-overflow-5
.carousel > li::scroll-marker:target-current { background: currentColor; }
Fill in the marker for the slide in view.

:target-before, :target-after

Match the scroll markers that come before, or after, the active :target-current marker in the same group. Useful for styling progress indicators.

Syntax:target-before · :target-after
Specificity0,1,0 (one pseudo-class)
SupportChrome 142 · Firefox no · Safari no
Speccss-overflow-5

:scope

Matches the scoping root: the root of an @scope block, or the element a script called querySelector() or closest() on. In a plain stylesheet with no scope it matches the same element as :root.

Syntax:scope
Specificity0,1,0 (one pseudo-class)
SupportChrome 27 · Firefox 32 · Safari 7
Specselectors-4
@scope (.card) {
  :scope { padding: 1rem; }
  :scope > h2 { margin: 0; }
}
Style the card itself and its direct heading.

User action

:hover

Matches an element while the user points at it, or at one of its descendants, with a pointing device. Touch screens may apply it only briefly on tap, so do not hide essential content behind it.

Syntax:hover
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 2
Specselectors-4

Wrap hover-only effects in @media (hover: hover) to keep them off devices that cannot hover.

:active

Matches an element while it is being activated, for example between pressing and releasing the mouse button on a link or button, or while a key is held on it.

Syntax:active
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4

:focus

Matches the element that currently has focus and receives keyboard input.

Syntax:focus
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4

For focus rings, :focus-visible is usually the better choice, since :focus also matches a button the user just clicked with the mouse.

:focus-visible

Matches the focused element when the browser decides focus should be shown, typically after keyboard navigation, and always for text fields, but not after a mouse click on a button.

Syntax:focus-visible
Specificity0,1,0 (one pseudo-class)
SupportChrome 86 · Firefox 85 · Safari 15.4
Specselectors-4
:focus-visible { outline: 3px solid; outline-offset: 2px; }
A clear focus ring for keyboard users only.

:focus-within

Matches an element that has focus or contains the focused element, including through shadow trees. Use it to highlight a whole form row or open a menu while focus is inside it.

Syntax:focus-within
Specificity0,1,0 (one pseudo-class)
SupportChrome 60 · Firefox 52 · Safari 10.1
Specselectors-4

Input & forms

:enabled, :disabled

:disabled matches form controls and other interface elements that are disabled, for example by the disabled attribute or by sitting inside a disabled <fieldset>. :enabled matches those that could be disabled but are not.

Syntax:enabled · :disabled
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 3.1
Specselectors-4

:checked

Matches checkboxes and radio buttons that are checked, and <option> elements that are selected.

Syntax:checked
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 3.1
Specselectors-4

:indeterminate

Matches controls in neither an on nor an off state: a checkbox whose indeterminate property is set by script, a radio group where no button is checked, and a <progress> element with no value.

Syntax:indeterminate
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 2 · Safari 3
Specselectors-4

:default

Matches the default item among a set: a form's default submit button, checkboxes and radio buttons that are checked by default in the markup, and options selected by default.

Syntax:default
Specificity0,1,0 (one pseudo-class)
SupportChrome 10 · Firefox 4 · Safari 5
Specselectors-4

:valid, :invalid

Match form controls, and forms and fieldsets containing them, whose value passes or fails its constraints, such as required, type=email or pattern. They apply as soon as the page loads, before the user has typed anything.

Syntax:valid · :invalid
Specificity0,1,0 (one pseudo-class)
SupportChrome 10 · Firefox 4 · Safari 5
On <form>: Chrome 40 · Firefox 13 · Safari 9
Specselectors-4

:user-valid, :user-invalid

Like :valid and :invalid, but only once the user has interacted with the control, for example by changing it and moving focus away, or by trying to submit the form. This avoids flagging empty required fields before anyone has touched them.

Syntax:user-valid · :user-invalid
Specificity0,1,0 (one pseudo-class)
SupportChrome 119 · Firefox 88 · Safari 16.5
Specselectors-4
input:user-invalid { border-color: crimson; }
Mark a field as wrong only after the user has had a go at it.

:in-range, :out-of-range

Match inputs that have range limits, such as min and max on a number or date input, when their value is inside or outside those limits. Inputs without limits match neither.

Syntax:in-range · :out-of-range
Specificity0,1,0 (one pseudo-class)
SupportChrome 10 · Firefox 29 · Safari 5.1
Specselectors-4

:required, :optional

:required matches form controls that must have a value before the form can be submitted, usually through the required attribute. :optional matches form controls that do not. Elements that are not form controls match neither.

Syntax:required · :optional
Specificity0,1,0 (one pseudo-class)
SupportChrome 10 · Firefox 4 · Safari 5
Specselectors-4

:read-only, :read-write

:read-write matches elements the user can edit: text inputs and textareas that are not readonly or disabled, and contenteditable elements. Every other element matches :read-only.

Syntax:read-only · :read-write
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 78 · Safari 4
Specselectors-4

:placeholder-shown

Matches an input or textarea while it is showing its placeholder text, which in practice means while it is empty. The placeholder text itself is styled with ::placeholder.

Syntax:placeholder-shown
Specificity0,1,0 (one pseudo-class)
SupportChrome 47 · Firefox 51 · Safari 9
Specselectors-4
input:not(:placeholder-shown) + label { translate: 0 -1.5em; }
A floating label that moves up once the field has a value.

:autofill

Matches inputs whose value the browser has filled in automatically, until the user edits them. Browsers apply their own autofill colours that may be hard to override.

Syntax:autofill
Specificity0,1,0 (one pseudo-class)
SupportChrome 110 · Firefox 86 · Safari 15
Specselectors-4

Tree-structural

These match by an element's position among its siblings. Text nodes are not counted, only elements. The functional ones take an An+B argument: 3 is the third, 2n or even every second one starting from the second, 2n+1 or odd the first, third and so on, and -n+3 the first three.

:root

Matches the root element of the document, which is <html> in HTML. It is the usual place to declare custom properties for the whole page, as it has higher specificity than html.

Syntax:root
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 1
Specselectors-4
:root { --accent: #ffd21a; }
A page-wide custom property.

:empty

Matches an element with no children at all: no elements and no text. Comments do not count, but in current browsers whitespace does, so an element containing only a line break does not match.

Syntax:empty
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 3.1
Specselectors-4

:first-child

Matches an element that is the first element among its siblings. Same as :nth-child(1).

Syntax:first-child
Specificity0,1,0 (one pseudo-class)
SupportChrome 4 · Firefox 3 · Safari 3.1
Specselectors-4

:last-child

Matches an element that is the last element among its siblings. Same as :nth-last-child(1).

Syntax:last-child
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 3.1
Specselectors-4

:only-child

Matches an element that has no sibling elements. Same as :first-child:last-child, but with lower specificity.

Syntax:only-child
Specificity0,1,0 (one pseudo-class)
SupportChrome 2 · Firefox 1.5 · Safari 3.1
Specselectors-4

:nth-child()

Matches elements by their position among all their sibling elements, counting from the first. With of S, only siblings matching the selector list S are counted, and the element itself must match S.

Syntax:nth-child( <an+b> [ of <complex-real-selector-list> ]? )
Specificity0,1,0, plus that of the most specific selector in the of list
SupportChrome 1 · Firefox 3.5 · Safari 3.1
of syntax: Chrome 111 · Firefox 113 · Safari 9
Specselectors-4
tr:nth-child(even) { background: #f4f4f4; }
li:nth-child(-n+3 of .featured) { font-weight: bold; }
Zebra-striped rows, and the first three featured items.

:nth-last-child()

Like :nth-child(), but counts from the last sibling backwards. :nth-last-child(-n+2) matches the last two.

Syntax:nth-last-child( <an+b> [ of <complex-real-selector-list> ]? )
Specificity0,1,0, plus that of the most specific selector in the of list
SupportChrome 4 · Firefox 3.5 · Safari 3.1
of syntax: Chrome 111 · Firefox 113 · Safari 9
Specselectors-4
li:first-child:nth-last-child(n+5) ~ li { font-size: 0.9em; }
A quantity query: smaller items when the list has five or more.

:first-of-type

Matches an element that is the first sibling of its element type. p:first-of-type matches the first paragraph even if a heading comes before it. Same as :nth-of-type(1).

Syntax:first-of-type
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 3.5 · Safari 3.1
Specselectors-4

:last-of-type

Matches an element that is the last sibling of its element type. Same as :nth-last-of-type(1).

Syntax:last-of-type
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 3.5 · Safari 3.1
Specselectors-4

:only-of-type

Matches an element that has no siblings of the same element type. Same as :first-of-type:last-of-type, but with lower specificity.

Syntax:only-of-type
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 3.5 · Safari 3.1
Specselectors-4

:nth-of-type()

Matches elements by their position among siblings of the same element type, counting from the first.

Syntax:nth-of-type( <an+b> )
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 3.5 · Safari 3.1
Specselectors-4
img:nth-of-type(odd) { float: inline-start; }
Alternate images left and right, ignoring the paragraphs between them.

:nth-last-of-type()

Like :nth-of-type(), but counts from the last sibling of the type backwards.

Syntax:nth-last-of-type( <an+b> )
Specificity0,1,0 (one pseudo-class)
SupportChrome 4 · Firefox 3.5 · Safari 3.1
Specselectors-4

Display & element states

:open

Matches an element that has open and closed states and is currently open: a <details> that is expanded, a <dialog> that is showing, or a <select> or <input> whose picker is showing.

Syntax:open
Specificity0,1,0 (one pseudo-class)
SupportChrome 133 · Firefox 136 · Safari 26.5
Specselectors-4

:popover-open

Matches an element with the popover attribute while it is showing.

Syntax:popover-open
Specificity0,1,0 (one pseudo-class)
SupportChrome 114 · Firefox 125 · Safari 17
Specselectors-4
[popover] { opacity: 0; transition: opacity 0.2s, display 0.2s allow-discrete; }
[popover]:popover-open { opacity: 1; }
@starting-style { [popover]:popover-open { opacity: 0; } }
Fade a popover in and out.

:fullscreen

Matches an element that is displayed full screen, for example after a script calls requestFullscreen() on it.

Syntax:fullscreen
Specificity0,1,0 (one pseudo-class)
SupportChrome 71 · Firefox 64 · Safari 16.4
Specselectors-4

:picture-in-picture

Matches an element, usually a <video>, while its content is playing in a picture-in-picture window that floats over other content.

Syntax:picture-in-picture
Specificity0,1,0 (one pseudo-class)
SupportChrome 110 · Firefox 153 · Safari 13.1
Specselectors-4

:defined

Matches elements that are defined: every built-in HTML element, and custom elements once customElements.define() has registered them. Use :not(:defined) to hide or reserve space for custom elements before their script loads.

Syntax:defined
Specificity0,1,0 (one pseudo-class)
SupportChrome 54 · Firefox 63 · Safari 10
Specselectors-4
my-tabs:not(:defined) { visibility: hidden; }
Avoid a flash of unstyled content while the element upgrades.

:state()

Matches a custom element that has the named custom state, which its script adds to ElementInternals.states. It lets a component expose states, such as :state(loading), the way built-in elements expose :checked.

Syntax:state( <ident> )
Specificity0,1,0 (one pseudo-class)
SupportChrome 125 · Firefox 126 · Safari 17.4
Specselectors-5

:heading

Matches elements that have a heading level in the document language, which in HTML means <h1> to <h6>. It is shorthand for :is(h1, h2, h3, h4, h5, h6) with the specificity of one pseudo-class.

Syntax:heading
Specificity0,1,0 (one pseudo-class)
SupportChrome no · Firefox no · Safari 27
Specselectors-5

:interest-source, :interest-target

:interest-source matches an element with the interestfor attribute while the user is showing interest in it, for example by hovering or focusing it. :interest-target matches the element it points to, such as the popover it reveals.

Syntax:interest-source · :interest-target
Specificity0,1,0 (one pseudo-class)
SupportChrome 142 · Firefox no · Safari no
Specselectors-5

:xr-overlay

Matches the element being shown as a DOM overlay during an immersive WebXR session, so page content such as controls can be styled for display over the AR view.

Syntax:xr-overlay
Specificity0,1,0 (one pseudo-class)
SupportChrome 83 · Firefox no · Safari no
Specdom-overlays

Media playback

These match <audio> and <video> elements by their playback state.

:playing, :paused

:playing matches a media element that is playing, including while it is briefly waiting for data. :paused matches one that is not playing, whether it was paused or has not started or has ended.

Syntax:playing · :paused
Specificity0,1,0 (one pseudo-class)
SupportChrome no · Firefox 150 · Safari 15.4
Specselectors-4

:seeking

Matches a media element while it is seeking to a new playback position.

Syntax:seeking
Specificity0,1,0 (one pseudo-class)
SupportChrome no · Firefox 150 · Safari 15.4
Specselectors-4

:buffering

Matches a playing media element that cannot continue because it is still loading data. Use it to show a loading indicator.

Syntax:buffering
Specificity0,1,0 (one pseudo-class)
SupportChrome no · Firefox 150 · Safari 15.4
Specselectors-4

:stalled

Matches a media element that is trying to load data but has received none for some time.

Syntax:stalled
Specificity0,1,0 (one pseudo-class)
SupportChrome no · Firefox 150 · Safari 15.4
Specselectors-4

:muted

Matches a media element that can make sound but is currently muted.

Syntax:muted
Specificity0,1,0 (one pseudo-class)
SupportChrome no · Firefox 150 · Safari 15.4
Specselectors-4

:volume-locked

Matches a media element whose volume is locked by the browser or the user, so the page cannot change it. Use it to hide a volume slider that would do nothing.

Syntax:volume-locked
Specificity0,1,0 (one pseudo-class)
SupportChrome no · Firefox 150 · Safari 15.4
Specselectors-4

:past, :future

Inside a WebVTT caption cue, match the parts of the cue text whose timestamps are before or after the current playback position. They are used inside ::cue() for karaoke-style captions that change as each word is spoken.

Syntax:past · :future
Specificity0,1,0 (one pseudo-class)
SupportChrome 23 · Firefox no · Safari 7
Specselectors-5
::cue(:future) { color: gray; }
Grey out caption words that have not been spoken yet.

Linguistic

:lang()

Matches elements in a given human language, as set by the lang attribute on the element or an ancestor. A range matches its sub-languages: :lang(en) matches en, en-GB and en-US. Unlike [lang|=en], it also matches descendants that inherit the language.

Syntax:lang( [ <ident> | <string> ]# )
Specificity0,1,0 (one pseudo-class)
SupportChrome 1 · Firefox 1 · Safari 3.1
Comma-separated list and wildcards: Chrome no · Firefox 114 · Safari 9
Specselectors-4
:lang(de) { quotes: '„' '“'; }
German quotation marks for German text.

:dir()

Matches elements by their text direction, left-to-right or right-to-left, as worked out by the document language. Unlike [dir=rtl], it follows inherited direction and the result of dir="auto".

Syntax:dir( ltr | rtl )
Specificity0,1,0 (one pseudo-class)
SupportChrome 120 · Firefox 49 · Safari 16.4
Specselectors-4

Shadow DOM

:host, :host()

In a shadow tree's stylesheet, :host matches the shadow host: the custom element the shadow root is attached to. :host() matches the host only if it also matches the compound selector given. Outside a shadow tree both match nothing. Styles from the page outside win over :host rules.

Syntax:host · :host( <compound-selector> )
Specificity:host: 0,1,0
:host(): 0,1,0 plus that of its argument
SupportChrome 54 · Firefox 63 · Safari 10
Speccss-shadow-1
:host { display: block; }
:host([disabled]) { opacity: 0.5; }
Inside the component: a default display, and a disabled state.

:host-context() Deprecated

Matches the shadow host if it, or any ancestor outside the shadow tree, matches the compound selector given. Only Chrome supports it and the other engines do not plan to. To let a component react to its surroundings, pass the information in with an inherited custom property instead.

Syntax:host-context( <compound-selector> )
Specificity0,1,0 plus that of its argument
SupportChrome 54 · Firefox no · Safari no
Speccss-shadow-1

:has-slotted

Matches a <slot> element that has content assigned to it from the light DOM. Use it to hide a slot's wrapper or fallback styling when nothing is slotted.

Syntax:has-slotted
Specificity0,1,0 (one pseudo-class)
SupportChrome no · Firefox 136 · Safari no
Speccss-shadow-1

View transitions

:active-view-transition

Matches the root element while a view transition is running. Use it to apply styles only during the transition.

Syntax:active-view-transition
Specificity0,1,0 (one pseudo-class)
SupportChrome 125 · Firefox 144 · Safari 18
Speccss-view-transitions-2

:active-view-transition-type()

Matches the root element while a view transition with at least one of the given types is running. Types are set by startViewTransition({ types }) or by the types descriptor of @view-transition, so one stylesheet can animate forward and back navigations differently.

Syntax:active-view-transition-type( <custom-ident># )
Specificity0,1,0 (one pseudo-class)
SupportChrome 125 · Firefox 147 · Safari 18.2
Speccss-view-transitions-2
:active-view-transition-type(back)::view-transition-old(root) {
  animation-name: slide-out-right;
}
A different animation when the transition type is back.

Paged media

These are page selectors, used after @page to style printed pages. They follow page-selector specificity, which ranks a page name above :first, and :first above :left and :right. See At-rules.

:first

Matches the first page of a printed document.

Syntax:first
SpecificityPage-selector specificity; counts above :left and :right
SupportChrome 18 · Firefox 116 · Safari 6
Speccss2
@page :first { margin-block-start: 6cm; }
A deeper top margin on the title page.

:left, :right

Match left-hand and right-hand pages of a double-sided document. Every page is one or the other; whether the first page is a right or a left page depends on the writing direction of the root element.

Syntax:left · :right
SpecificityPage-selector specificity; counts below :first
SupportChrome 6 · Firefox no · Safari 5
Speccss2
@page :left { margin-inline-end: 3cm; }
@page :right { margin-inline-start: 3cm; }
A wider inner margin for binding.