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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 1 · Firefox 1.5 · Safari 4 |
| Spec | css-pseudo-4 |
The single-colon form :before from CSS 2 still works everywhere and means the same thing.
.required::before { content: '* '; color: crimson; }
::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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 1 · Firefox 1.5 · Safari 4 |
| Spec | css-pseudo-4 |
The single-colon form :after from CSS 2 still works everywhere and means the same thing.
a[target=_blank]::after { content: ' ↗' / ''; }
::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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 86 · Firefox 68 · Safari 11.1 (Safari supports only some properties) |
| Spec | css-pseudo-4 |
li::marker { color: var(--accent); font-weight: bold; }
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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 1 · Firefox 1 · Safari 1 |
| Spec | css-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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 1 · Firefox 1 · Safari 1 |
| Spec | css-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; }
::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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 1 · Firefox 62 · Safari 1.1 |
| Spec | css-pseudo-4 |
::selection { background-color: #ffd21a; color: black; }
::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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 89 · Firefox 131 · Safari 18.2 |
| Spec | css-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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 121 · Firefox no · Safari 17.4 |
| Spec | css-pseudo-4 |
::grammar-error
Text the browser has flagged as grammatically incorrect.
| Syntax | ::grammar-error |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 121 · Firefox no · Safari 17.4 |
| Spec | css-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>) |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 105 · Firefox 149 · Safari 17.2 |
| Spec | css-pseudo-4 |
The argument is a highlight name (a <custom-ident>) or * for every highlight.
::highlight(search) { background-color: yellow; }
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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 144 · Firefox no · Safari no |
| Spec | css-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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 57 · Firefox 51 · Safari 10.1 |
| Spec | css-forms-1 |
::placeholder { color: #6b6b6b; opacity: 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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 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 |
| Spec | css-position-4 |
dialog::backdrop { background: rgb(0 0 0 / 0.5); backdrop-filter: blur(4px); }
::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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 131 · Firefox 143 · Safari 18.4 |
| Spec | css-pseudo-4 |
details::details-content { padding-inline: 1rem; border-inline-start: 2px solid; }
::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>+ ) |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 135 · Firefox no · Safari 27 |
| Spec | css-forms-1 |
The only <form-control-identifier> is select.
select, ::picker(select) { appearance: base-select; }
::picker(select) { border-radius: 0.5rem; }
::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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 133 · Firefox no · Safari 27 |
| Spec | css-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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 133 · Firefox no · Safari 27 |
| Spec | css-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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome no · Firefox no · Safari 27.2 |
| Spec | css-forms-1 |
::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 |
| Spec | webvtt |
video::cue { background-color: rgb(0 0 0 / 0.8); font-size: 1.25em; }
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>+ ) |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 73 · Firefox 72 · Safari 13.1 |
| Spec | css-shadow-1 |
my-tabs::part(tab active) { border-block-end-color: currentColor; }
my-tabs::part(tab):hover { background: #eee; }
::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> ) |
|---|---|
| Specificity | 0,0,1 plus that of its argument |
| Support | Chrome 50 · Firefox 63 · Safari 10 |
| Spec | css-shadow-1 |
slot[name=title]::slotted(*) { margin: 0; }
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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 135 · Firefox no · Safari no |
| Spec | css-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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 135 · Firefox no · Safari no |
| Spec | css-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; }
::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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 135 · Firefox no · Safari no |
| Spec | css-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 |
|---|---|
| Specificity | 0,0,1 (one pseudo-element) |
| Support | Chrome 109 · Firefox 144 · Safari 18 |
| Spec | css-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> ) |
|---|---|
| Specificity | 0,0,1; with *, 0,0,0 |
| Support | Chrome 109 · Firefox 144 · Safari 18 |
| Spec | css-view-transitions-2 |
::view-transition-group(*) { animation-duration: 0.4s; }
::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> ) |
|---|---|
| Specificity | 0,0,1; with *, 0,0,0 |
| Support | Chrome 140 · Firefox no · Safari no |
| Spec | css-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> ) |
|---|---|
| Specificity | 0,0,1; with *, 0,0,0 |
| Support | Chrome 109 · Firefox 144 · Safari 18 |
| Spec | css-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> ) |
|---|---|
| Specificity | 0,0,1; with *, 0,0,0 |
| Support | Chrome 109 · Firefox 144 · Safari 18 |
| Spec | css-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; }