Pseudo-elements

A pseudo-element, written with two colons, selects something that is not an element in the document: generated content, a range of text, part of a form control or component, or a box the browser creates for scrolling or view transitions. It comes at the end of a selector, after the element it belongs to (its originating element), and adds 0,0,1 to specificity unless noted. Element states are under Pseudo-classes; the content property that fills generated boxes is under Lists, tables & content.

Generated content

::before

Creates a box as the first child of the element, before its actual content. It is only generated when content is set to something other than none or normal, and it is inline by default. Replaced elements such as <img> and <input> do not get one.

Syntax::before
Specificity0,0,1 (one pseudo-element)
SupportChrome 1 · Firefox 1.5 · Safari 4
Speccss-pseudo-4

The single-colon form :before from CSS 2 still works everywhere and means the same thing.

.required::before { content: '* '; color: crimson; }
A marker in front of required field labels.

::after

Creates a box as the last child of the element, after its actual content. Like ::before, it needs a content value to appear, and replaced elements do not get one.

Syntax::after
Specificity0,0,1 (one pseudo-element)
SupportChrome 1 · Firefox 1.5 · Safari 4
Speccss-pseudo-4

The single-colon form :after from CSS 2 still works everywhere and means the same thing.

a[target=_blank]::after { content: ' ↗' / ''; }
An external-link arrow, with empty alternative text so screen readers skip it.

::marker

The bullet or number box of a list item, or of any element with display: list-item. Only a few properties apply to it, mainly color, the font properties, content, white-space, and animations and transitions.

Syntax::marker
Specificity0,0,1 (one pseudo-element)
SupportChrome 86 · Firefox 68 · Safari 11.1 (Safari supports only some properties)
Speccss-pseudo-4
li::marker { color: var(--accent); font-weight: bold; }
Coloured bullets without replacing them.

Text fragments & highlights

::first-line

The first formatted line of a block container, which changes as the text reflows. Only font, colour, background, text decoration, spacing and similar inline properties apply.

Syntax::first-line
Specificity0,0,1 (one pseudo-element)
SupportChrome 1 · Firefox 1 · Safari 1
Speccss-pseudo-4

The single-colon form :first-line from CSS 2 still works and means the same thing.

::first-letter

The first letter, number or symbol on the first line of a block, together with any punctuation right before or after it. Use it for drop caps, often with initial-letter or a float.

Syntax::first-letter
Specificity0,0,1 (one pseudo-element)
SupportChrome 1 · Firefox 1 · Safari 1
Speccss-pseudo-4

The single-colon form :first-letter from CSS 2 still works and means the same thing.

article > p:first-of-type::first-letter { initial-letter: 3; }
A three-line drop cap on the opening paragraph.

::selection

The part of the document the user has selected, for example by dragging over text. Only color, background-color, text decorations, text-shadow and a few other painting properties apply.

Syntax::selection
Specificity0,0,1 (one pseudo-element)
SupportChrome 1 · Firefox 62 · Safari 1.1
Speccss-pseudo-4
::selection { background-color: #ffd21a; color: black; }
A brand-coloured selection across the whole page.

::target-text

The text a URL's text fragment points to, such as a link ending in #:~:text=example. Browsers scroll to and highlight it; this lets you choose the highlight.

Syntax::target-text
Specificity0,0,1 (one pseudo-element)
SupportChrome 89 · Firefox 131 · Safari 18.2
Speccss-pseudo-4

::spelling-error

Text the browser has flagged as misspelled, usually in an editable field. Use it to change how spelling mistakes are marked.

Syntax::spelling-error
Specificity0,0,1 (one pseudo-element)
SupportChrome 121 · Firefox no · Safari 17.4
Speccss-pseudo-4

::grammar-error

Text the browser has flagged as grammatically incorrect.

Syntax::grammar-error
Specificity0,0,1 (one pseudo-element)
SupportChrome 121 · Firefox no · Safari 17.4
Speccss-pseudo-4

::highlight()

Styles text ranges that a script has registered under a name with the CSS Custom Highlight API (CSS.highlights). It highlights text such as search results without adding wrapper elements to the DOM.

Syntax::highlight(<highlight-name-selector>)
Specificity0,0,1 (one pseudo-element)
SupportChrome 105 · Firefox 149 · Safari 17.2
Speccss-pseudo-4

The argument is a highlight name (a <custom-ident>) or * for every highlight.

::highlight(search) { background-color: yellow; }
Paired with CSS.highlights.set('search', new Highlight(range)) in script.

::search-text

Text matched by the browser's find-in-page feature. Use it to make find results match the page's colours.

Syntax::search-text
Specificity0,0,1 (one pseudo-element)
SupportChrome 144 · Firefox no · Safari no
Speccss-pseudo-4

Form & element parts

::placeholder

The placeholder text of an <input> or <textarea>. To style the field itself while the placeholder shows, use :placeholder-shown.

Syntax::placeholder
Specificity0,0,1 (one pseudo-element)
SupportChrome 57 · Firefox 51 · Safari 10.1
Speccss-forms-1
::placeholder { color: #6b6b6b; opacity: 1; }
A placeholder colour with enough contrast; Firefox lowers its opacity by default.

::file-selector-button

The button of an <input type="file"> that opens the file picker. It can be styled like any button.

Syntax::file-selector-button
Specificity0,0,1 (one pseudo-element)
SupportChrome 89 · Firefox 82 · Safari 14.1
Speccss-forms-1

::backdrop

A box drawn directly beneath an element in the top layer, covering the viewport. Modal dialogs, popovers and full-screen elements each get one. Use it to dim or blur the page behind.

Syntax::backdrop
Specificity0,0,1 (one pseudo-element)
SupportChrome 37 · Firefox 47 · Safari 15.4
On popovers: Chrome 114 · Firefox 125 · Safari 17
Inherits from its element: Chrome 122 · Firefox 120 · Safari 17.4
Speccss-position-4
dialog::backdrop { background: rgb(0 0 0 / 0.5); backdrop-filter: blur(4px); }
Dim and blur the page behind a modal dialog.

::details-content

The part of a <details> element that is shown and hidden, that is everything except its <summary>. It is backed by a real element, so it takes most properties, which makes it possible to animate the opening and closing.

Syntax::details-content
Specificity0,0,1 (one pseudo-element)
SupportChrome 131 · Firefox 143 · Safari 18.4
Speccss-pseudo-4
details::details-content { padding-inline: 1rem; border-inline-start: 2px solid; }
Indent and rule the expanded content without a wrapper element.

::picker()

The part of a form control that pops out of the page, such as the drop-down list of a <select>. It can be styled once the control and its picker opt in to the customisable appearance with appearance: base-select.

Syntax::picker( <form-control-identifier>+ )
Specificity0,0,1 (one pseudo-element)
SupportChrome 135 · Firefox no · Safari 27
Speccss-forms-1

The only <form-control-identifier> is select.

select, ::picker(select) { appearance: base-select; }
::picker(select) { border-radius: 0.5rem; }
Opt in, then style the drop-down list.

::picker-icon

The icon on a form control that shows it opens a picker, such as the arrow on a <select>. It is generated only when the control uses the customisable appearance.

Syntax::picker-icon
Specificity0,0,1 (one pseudo-element)
SupportChrome 133 · Firefox no · Safari 27
Speccss-forms-1

::checkmark

The indicator that shows whether a checkbox, radio button or <option> is checked, such as the tick next to the selected option in a customisable <select>.

Syntax::checkmark
Specificity0,0,1 (one pseudo-element)
SupportChrome 133 · Firefox no · Safari 27
Speccss-forms-1

::field-content

The part of an input that holds the editable text, as distinct from the rest of the control.

Syntax::field-content
Specificity0,0,1 (one pseudo-element)
SupportChrome no · Firefox no · Safari 27.2
Speccss-forms-1

::interest-button

A button the browser generates on an element with the interestfor attribute. Pressing it shows interest in the element, which gives touch and keyboard users a way to reveal what hovering would show. See :interest-source.

Syntax::interest-button
Specificity0,0,1 (one pseudo-element)
SupportChrome 149 · Firefox no · Safari no
Speccss-pseudo-4

::cue, ::cue()

::cue styles the WebVTT captions and subtitles of a <video>. ::cue() styles only the parts of the cue text that match its selector, such as voice spans or :past and :future words. Only colour, font, background, text decoration, outline and a few text properties apply.

Syntax::cue · ::cue(selector)
Specificity::cue: 0,0,1
Support::cue: Chrome 26 · Firefox 55 · Safari 7
::cue(): Chrome 26 · Firefox no · Safari 7
Specwebvtt
video::cue { background-color: rgb(0 0 0 / 0.8); font-size: 1.25em; }
Larger captions on a darker band.

Shadow DOM

::part()

From outside a component, styles elements inside its shadow tree that the component has exposed with the part attribute. With several names it matches elements that have all of them. User-action pseudo-classes such as :hover can follow it, but tree-structural ones cannot.

Syntax::part( <ident>+ )
Specificity0,0,1 (one pseudo-element)
SupportChrome 73 · Firefox 72 · Safari 13.1
Speccss-shadow-1
my-tabs::part(tab active) { border-block-end-color: currentColor; }
my-tabs::part(tab):hover { background: #eee; }
Style a component's exposed tab elements from the page.

::slotted()

In a shadow tree's stylesheet, styles light-DOM elements that have been assigned to a <slot> and match the compound selector given. It reaches only the slotted elements themselves, not their descendants. Styles from the page outside win over ::slotted() rules.

Syntax::slotted( <compound-selector> )
Specificity0,0,1 plus that of its argument
SupportChrome 50 · Firefox 63 · Safari 10
Speccss-shadow-1
slot[name=title]::slotted(*) { margin: 0; }
Inside the component: reset whatever is slotted as the title.

Scroll markers & buttons

These build carousel controls in CSS alone: a group of markers that track and jump to items in a scroll container, and buttons that scroll it.

::scroll-marker-group

A box generated before or after a scroll container whose scroll-marker-group property is not none. It holds the container's ::scroll-marker boxes and can be laid out and styled like any other box.

Syntax::scroll-marker-group
Specificity0,0,1 (one pseudo-element)
SupportChrome 135 · Firefox no · Safari no
Speccss-overflow-5

::scroll-marker

A marker generated for an item inside a scroll container, placed in the container's ::scroll-marker-group. It appears when its content is not none; activating it scrolls its item into view, and the marker for the item in view matches :target-current.

Syntax::scroll-marker
Specificity0,0,1 (one pseudo-element)
SupportChrome 135 · Firefox no · Safari no
Speccss-overflow-5
.carousel { overflow-x: auto; scroll-marker-group: after; }
.carousel > li::scroll-marker { content: ''; inline-size: 0.75rem; aspect-ratio: 1; border: 1px solid; border-radius: 50%; }
.carousel > li::scroll-marker:target-current { background: currentColor; }
A row of dots under a carousel, with the current one filled.

::scroll-button()

A button generated on a scroll container that scrolls it by about a page in the given direction. It appears when its content is not none, and is disabled when the container cannot scroll further that way. * selects all of a container's scroll buttons.

Syntax::scroll-button( '*' | <scroll-button-direction> )
Specificity0,0,1 (one pseudo-element)
SupportChrome 135 · Firefox no · Safari no
Speccss-overflow-5

The supported directions are up, down, left, right, block-start, block-end, inline-start and inline-end.

.carousel::scroll-button(inline-start) { content: '◀' / 'Previous'; }
.carousel::scroll-button(inline-end) { content: '▶' / 'Next'; }
Previous and next buttons with accessible labels.

::column

Each column of a multi-column container. It only takes a few properties; its main use is to give every column its own scroll marker with ::column::scroll-marker, so a paged multi-column layout gets one dot per page.

Syntax::column
Specificity0,0,1 (one pseudo-element)
SupportChrome 135 · Firefox no · Safari no
Speccss-multicol-2

View transitions

During a view transition the browser builds a tree of pseudo-elements on the root element: ::view-transition, then for each captured view-transition-name a ::view-transition-group() holding a ::view-transition-image-pair(), which holds ::view-transition-old() and ::view-transition-new(). The named ones take a <pt-name-and-class-selector>: a view transition name, * for all, and optionally one or more classes from view-transition-class written as .name. A name or class counts 0,0,1; * alone counts 0,0,0.

::view-transition

The root of the view transition tree: an overlay above the whole page that contains every transition group.

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

::view-transition-group()

One for each captured name. By default it animates its size and position from the old state to the new one. Set animation-duration or animation-timing-function here to change the timing for that element.

Syntax::view-transition-group( <pt-name-and-class-selector> )
Specificity0,0,1; with *, 0,0,0
SupportChrome 109 · Firefox 144 · Safari 18
Speccss-view-transitions-2
::view-transition-group(*) { animation-duration: 0.4s; }
Slow down every part of the transition.

::view-transition-group-children()

A container for nested transition groups, created when the view-transition-group property places groups inside another element's group. It is sized like its parent group, so nested groups can be clipped or transformed with it.

Syntax::view-transition-group-children( <pt-name-and-class-selector> )
Specificity0,0,1; with *, 0,0,0
SupportChrome 140 · Firefox no · Safari no
Speccss-view-transitions-2

::view-transition-image-pair()

The child of a transition group that holds its old and new snapshots. It isolates them so the two images blend only with each other during the cross-fade.

Syntax::view-transition-image-pair( <pt-name-and-class-selector> )
Specificity0,0,1; with *, 0,0,0
SupportChrome 109 · Firefox 144 · Safari 18
Speccss-view-transitions-2

::view-transition-old(), ::view-transition-new()

Snapshots of the element before and after the change, drawn like replaced elements. By default the old one fades out and the new one fades in; replace their animation to slide, scale or wipe instead. Each is left out if there is no old or new state to show.

Syntax::view-transition-old( <pt-name-and-class-selector> ) · ::view-transition-new( <pt-name-and-class-selector> )
Specificity0,0,1; with *, 0,0,0
SupportChrome 109 · Firefox 144 · Safari 18
Speccss-view-transitions-2
::view-transition-old(root) { animation: 0.3s ease-in both slide-out; }
::view-transition-new(root) { animation: 0.3s ease-out both slide-in; }
Replace the page-wide cross-fade with your own keyframes.