# Custom properties (--*): CSS variables
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since April 2017.
* Learn more
* See full compatibility
* Report feedback
Property names that are prefixed with `--`, like `--example-name`, represent
_custom properties_ that contain a value that can be used in other
declarations using the `var()` function.
Custom properties are scoped to the element(s) they are declared on, and
participate in the cascade: the value of such a custom property is that from
the declaration decided by the cascading algorithm.
Initial value | see prose
---|---
Applies to | all elements
Inherited | yes
Computed value | as specified with variables substituted
Animation type | discrete
## Syntax
--some-keyword: left;
--some-color: #0000ff;
--some-complex-value: 3px 6px rgb(20 32 54);
``
This value matches any sequence of one or more tokens, so long as the sequence
does not contain any disallowed token. It represents the entirety of what a
valid declaration can have as its value.
**Note:** Custom property names are case sensitive — `--my-color` will be
treated as a separate custom property to `--My-color`.
## Example
### HTML
This paragraph should have a blue background and yellow text.
This paragraph should have a yellow background and blue text.
This paragraph should have a green background and yellow text.
### CSS
:root {
--first-color: #16f;
--second-color: #ff7;
}
#firstParagraph {
background-color: var(--first-color);
color: var(--second-color);
}
#secondParagraph {
background-color: var(--second-color);
color: var(--first-color);
}
#container {
--first-color: #290;
}
#thirdParagraph {
background-color: var(--first-color);
color: var(--second-color);
}
### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`--*` | 49 | 15 | 31 | 36 | 9.1 | 49 | 31 | 36 | 9.3 | 5.0 | 49
## See also
* The `var()` function
* `@property` at-rule
* Using CSS custom properties (variables) guide
* CSS custom properties for cascading variables module
# -webkit-border-before
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
The `-webkit-border-before` CSS property is a shorthand property for setting
the individual logical block start border property values in a single place in
the style sheet.
## Constituent properties
This property is a shorthand for the following CSS properties:
* `-webkit-border-before-color`
* `-webkit-border-before-style`
* `-webkit-border-before-width`
## Syntax
/* Border values */
-webkit-border-before: 1px;
-webkit-border-before: 2px dotted;
-webkit-border-before: medium dashed blue;
/* Global values */
-webkit-border-before: inherit;
-webkit-border-before: initial;
-webkit-border-before: revert;
-webkit-border-before: revert-layer;
-webkit-border-before: unset;
### Values
One or more of the following, in any order:
`<'border-width'>`
See `border-width`
`<'border-style'>`
See `border-style`
`<'color'>`
See `color`
## Description
The `-webkit-border-before` property maps to a physical border depending on
the element's writing mode, directionality, and text orientation. It
corresponds to the `border-top`, `border-right`, `border-bottom`, or `border-
left` property depending on the values defined for `writing-mode`,
`direction`, and `text-orientation`.
It relates to `-webkit-border-after`, `-webkit-border-start`, and `-webkit-
border-end`, which define the other borders of the element.
The standard-track equivalent of this property is `border-block-start`.
## Formal definition
Initial value | as each of the properties of the shorthand:
* `border-width`: as each of the properties of the shorthand:
* `border-top-width`: `medium`
* `border-right-width`: `medium`
* `border-bottom-width`: `medium`
* `border-left-width`: `medium`
* `border-style`: as each of the properties of the shorthand:
* `border-top-style`: `none`
* `border-right-style`: `none`
* `border-bottom-style`: `none`
* `border-left-style`: `none`
* `color`: `canvastext`
---|---
Applies to | all elements
Inherited | yes
Percentages | as each of the properties of the shorthand:
* `-webkit-border-before-width`: logical-width of containing block
Computed value | as each of the properties of the shorthand:
* `border-width`: as each of the properties of the shorthand:
* `border-bottom-width`: the absolute length or `0` if `border-bottom-style` is `none` or `hidden`
* `border-left-width`: the absolute length or `0` if `border-left-style` is `none` or `hidden`
* `border-right-width`: the absolute length or `0` if `border-right-style` is `none` or `hidden`
* `border-top-width`: the absolute length or `0` if `border-top-style` is `none` or `hidden`
* `border-style`: as each of the properties of the shorthand:
* `border-bottom-style`: as specified
* `border-left-style`: as specified
* `border-right-style`: as specified
* `border-top-style`: as specified
* `color`: computed color
Animation type | discrete
## Formal syntax
-webkit-border-before =
<'border-width'> ||
<'border-style'> ||
=
{1,4}
=
{1,4}
=
|
thin |
medium |
thick
=
none |
hidden |
dotted |
dashed |
solid |
double |
groove |
ridge |
inset |
outset
Sources: CSS Backgrounds and Borders Module Level 3
## Examples
### Applying a border with vertical text
#### HTML
#### CSS
div {
background-color: yellow;
width: 120px;
height: 120px;
}
.exampleText {
writing-mode: vertical-rl;
-webkit-border-before: 5px dashed blue;
}
#### Result
## Specifications
Not part of any standard, but it relates to the standards-track `border-block-
start` property.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`-webkit-border-before` | 8 | 79 | No | 15 | 5.1 | 18 | No | 15 | 5 | 1.0 | 3
## See also
* `border-block-start`
* The mapped physical properties: `border-top`, `border-right`, `border-bottom`, and `border-left`
* `writing-mode`, `direction`, `text-orientation`
# -webkit-tap-highlight-color
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
`-webkit-tap-highlight-color` is a non-standard CSS property that sets the
color of the highlight that appears over a link while it's being tapped. The
highlighting indicates to the user that their tap is being successfully
recognized, and indicates which element they're tapping on.
## Syntax
-webkit-tap-highlight-color: red;
-webkit-tap-highlight-color: transparent; /* for removing the highlight */
/* Global values */
-webkit-tap-highlight-color: inherit;
-webkit-tap-highlight-color: initial;
-webkit-tap-highlight-color: revert;
-webkit-tap-highlight-color: revert-layer;
-webkit-tap-highlight-color: unset;
### Values
A ``.
## Formal definition
Initial value | `black`
---|---
Applies to | all elements
Inherited | yes
Computed value | as specified
Animation type | discrete
## Formal syntax
-webkit-tap-highlight-color =
## Specifications
Not part of any standard. Apple has a description in the Safari Web Content
Guide.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`-webkit-tap-highlight-color` | 16 | 12 | No | 15 | No | 18 | No | 14 | 4 | 1.0 | 4.4
## See also
* WebKit CSS extensions
* Related CSS pseudo-classes:
* `:hover`
* `:active`
* `:visited`
# -webkit-text-fill-color
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since September 2016.
* Learn more
* See full compatibility
* Report feedback
The `-webkit-text-fill-color` CSS property specifies the fill color of
characters of text. If this property is not set, the value of the `color`
property is used.
## Syntax
/* values */
-webkit-text-fill-color: red;
-webkit-text-fill-color: #000000;
-webkit-text-fill-color: rgb(100 200 0);
/* Global values */
-webkit-text-fill-color: inherit;
-webkit-text-fill-color: initial;
-webkit-text-fill-color: revert;
-webkit-text-fill-color: revert-layer;
-webkit-text-fill-color: unset;
### Values
``
The foreground fill color of the element's text content.
## Formal definition
Initial value | `currentcolor`
---|---
Applies to | all elements
Inherited | yes
Computed value | computed color
Animation type | a color
## Formal syntax
-webkit-text-fill-color =
Sources: Compatibility Standard
## Examples
### Changing the fill color
#### CSS
p {
margin: 0;
font-size: 3em;
-webkit-text-fill-color: green;
}
#### HTML
This text is green.
#### Results
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`-webkit-text-fill-color` | 1 | 12 | 49 | 15 | 3 | 18 | 49 | 15 | 2 | 1.0 | 37
## See also
* Introducing Text-Stroke on webkit.org (2006)
* CSS-Tricks article explaining this feature
* `-webkit-text-stroke-color`
* `-webkit-text-stroke-width`
* `-webkit-text-stroke`
# -webkit-text-stroke-color
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since April 2017.
* Learn more
* See full compatibility
* Report feedback
The `-webkit-text-stroke-color` CSS property specifies the stroke color of
characters of text. If this property is not set, the value of the `color`
property is used.
## Syntax
/* values */
-webkit-text-stroke-color: red;
-webkit-text-stroke-color: #e08ab4;
-webkit-text-stroke-color: rgb(200 100 0);
/* Global values */
-webkit-text-stroke-color: inherit;
-webkit-text-stroke-color: initial;
-webkit-text-stroke-color: revert;
-webkit-text-stroke-color: revert-layer;
-webkit-text-stroke-color: unset;
### Values
``
The color of the stroke.
## Formal definition
Initial value | `currentcolor`
---|---
Applies to | all elements
Inherited | yes
Computed value | computed color
Animation type | a color
## Formal syntax
-webkit-text-stroke-color =
Sources: Compatibility Standard
## Examples
### Varying the stroke color
#### HTML
Text with stroke
#### CSS
p {
margin: 0;
font-size: 4em;
-webkit-text-stroke-width: 3px;
-webkit-text-stroke-color: #ff0000; /* Can be changed in the live sample */
}
#### Results
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`-webkit-text-stroke-color` | 1 | 15 | 49 | 15 | 3 | 18 | 49 | 15 | 2 | 1.0 | 37
## See also
* Introducing Text-Stroke on webkit.org (2006)
* CSS-Tricks article explaining this feature
* `-webkit-text-fill-color`
* `-webkit-text-stroke-width`
* `-webkit-text-stroke`
# -webkit-text-stroke-width
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since April 2017.
* Learn more
* See full compatibility
* Report feedback
The `-webkit-text-stroke-width` CSS property specifies the width of the stroke
for text.
## Syntax
/* Keyword values */
-webkit-text-stroke-width: thin;
-webkit-text-stroke-width: medium;
-webkit-text-stroke-width: thick;
/* values */
-webkit-text-stroke-width: 2px;
-webkit-text-stroke-width: 0.1em;
-webkit-text-stroke-width: 1mm;
-webkit-text-stroke-width: 5pt;
/* Global values */
-webkit-text-stroke-width: inherit;
-webkit-text-stroke-width: initial;
-webkit-text-stroke-width: revert;
-webkit-text-stroke-width: revert-layer;
-webkit-text-stroke-width: unset;
### Values
``
The width of the stroke.
## Formal definition
Initial value | `0`
---|---
Applies to | all elements
Inherited | yes
Computed value | absolute ``
Animation type | discrete
## Formal syntax
-webkit-text-stroke-width =
=
|
thin |
medium |
thick
Sources: Compatibility Standard, CSS Backgrounds and Borders Module Level 3
## Examples
### Varying stroke widths
#### CSS
p {
margin: 0;
font-size: 4em;
-webkit-text-stroke-color: red;
}
#thin {
-webkit-text-stroke-width: thin;
}
#medium {
-webkit-text-stroke-width: 3px;
}
#thick {
-webkit-text-stroke-width: 1.5mm;
}
#### HTML
Thin stroke
Medium stroke
Thick stroke
#### Results
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`-webkit-text-stroke-width` | 1 | 15 | 49 | 15 | 3 | 18 | 49 | 15 | 2 | 1.0 | 38
## See also
* Introducing Text-Stroke on webkit.org (2006)
* CSS-Tricks article explaining this feature
* `-webkit-text-stroke-color`
* `-webkit-text-stroke`
* `-webkit-text-fill-color`
# -webkit-text-stroke
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since April 2017.
* Learn more
* See full compatibility
* Report feedback
The `-webkit-text-stroke` CSS property specifies the width and color of
strokes for text characters. This is a shorthand property for the longhand
properties `-webkit-text-stroke-width` and `-webkit-text-stroke-color`.
/* Width and color values */
-webkit-text-stroke: 4px navy;
/* Global values */
-webkit-text-stroke: inherit;
-webkit-text-stroke: initial;
-webkit-text-stroke: revert;
-webkit-text-stroke: revert-layer;
-webkit-text-stroke: unset;
## Constituent properties
This property is a shorthand for the following CSS properties:
* `-webkit-text-stroke-color`
* `-webkit-text-stroke-width`
## Syntax
### Values
``
The width of the stroke.
``
The color of the stroke.
## Formal definition
Initial value | as each of the properties of the shorthand:
* `-webkit-text-stroke-width`: `0`
* `-webkit-text-stroke-color`: `currentcolor`
---|---
Applies to | all elements
Inherited | yes
Computed value | as each of the properties of the shorthand:
* `-webkit-text-stroke-width`: absolute ``
* `-webkit-text-stroke-color`: computed color
Animation type | as each of the properties of the shorthand:
* `-webkit-text-stroke-width`: discrete
* `-webkit-text-stroke-color`: a color
## Formal syntax
-webkit-text-stroke =
||
=
|
thin |
medium |
thick
Sources: Compatibility Standard, CSS Backgrounds and Borders Module Level 3
## Examples
### Adding a red text stroke
#### HTML
The stroke of this text is red.
#### CSS
#example {
font-size: 3em;
margin: 0;
-webkit-text-stroke: 2px red;
}
#### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`-webkit-text-stroke` | 4 | 15 | 49 | 15 | 3 | 18 | 49 | 14 | 2 | 1.0 | 4
## See also
* Introducing Text-Stroke on webkit.org (2006)
* CSS-Tricks article explaining this feature
* `-webkit-text-stroke-width`
* `-webkit-text-stroke-color`
* `-webkit-text-fill-color`
# :-moz-first-node
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in
production.
The `:-moz-first-node` CSS pseudo-class is a Mozilla extension that represents
any element that is the first child node of some other element. It differs
from `:first-child` because it does not match a first-child element with (non-
whitespace) text before it.
**Note:** Any whitespace at the start of an element is ignored for the
determination of `:-moz-first-node`.
## Syntax
:-moz-first-node {
/* ... */
}
## Examples
### CSS
span:-moz-first-node {
background-color: lime;
}
### HTML
This matches!
This doesn't match.
Blahblah.
This doesn't match because it's preceded by text.
### Result
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`:-moz-first-node` | No | No | ≤72 | No | No | No | ≤79 | No | No | No | No
## See also
* `:-moz-last-node`
* `:first-child`
# :-moz-last-node
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in
production.
The `:-moz-last-node` CSS pseudo-class is a Mozilla extension that represents
any element that is the last child node of some other element. It differs from
`:last-child` because it does not match a last-child element with (non-
whitespace) text after it.
**Note:** Any whitespace at the end of an element is ignored for the
determination of `:-moz-last-node`.
## Syntax
:-moz-last-node {
/* ... */
}
## Examples
### CSS
span:-moz-last-node {
background-color: lime;
}
### HTML
This does not match.
This matches!
This doesn't match because it's followed by text.
Blahblah.
### Result
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`:-moz-last-node` | No | No | ≤72 | No | No | No | ≤79 | No | No | No | No
## See also
* `:-moz-first-node`
* `:last-child`
# :-moz-only-whitespace
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
**Note:** In Selectors Level 4, the `:empty` selector was changed to act like
`:-moz-only-whitespace`, but no browser currently supports this yet.
The `:-moz-only-whitespace` CSS pseudo-class matches elements that only
contain text nodes that only contain whitespace. (This includes elements with
empty text nodes and elements with no child nodes.)
## Syntax
:-moz-only-whitespace {
/* ... */
}
## Examples
### Basic :-moz-only-whitespace example
#### HTML
#### CSS
div {
border: 4px solid red;
}
:-moz-only-whitespace {
border-color: lime;
}
#### Result
## Specifications
Briefly defined as `:blank` in Selectors Level 4, but then the functionality
was merged into `:empty` and `:blank` redefined to mean empty ` `.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`:-moz-only-whitespace` | No | No | 1 | No | No | No | 4 | No | No | No | No
## See also
* `:blank`
* `:empty`
# :-moz-submit-invalid
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
The `:-moz-submit-invalid` CSS pseudo-class is a Mozilla extension that
represents any submit `` on forms whose contents aren't valid based on
their validation constraints.
By default, no style is applied. You can use this pseudo-class to customize
the appearance of the submit button when there are invalid form fields.
## Syntax
:-moz-submit-invalid {
/* ... */
}
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`:-moz-submit-invalid` | No | No | 88From Firefox 88 the feature has been placed behind a flag. See bug 1694129.4–88 | No | No | No | 4–88From version 88, the feature has been withdrawn. See bug 1694129. | No | No | No | No
## See also
* `:valid`
* `:invalid`
* `:required`
* `:optional`
# ::-moz-range-progress
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
The `::-moz-range-progress` CSS pseudo-element is a Mozilla extension that
represents the lower portion of the _track_ (i.e., groove) in which the
indicator slides in an ` ` of `type="range"`. This portion corresponds
to values lower than the value currently selected by the _thumb_ (i.e.,
virtual knob).
**Note:** Using `::-moz-range-progress` with anything but an ` ` doesn't match anything and has no effect.
## Syntax
::-moz-range-progress {
/* ... */
}
## Examples
### HTML
### CSS
input[type="range"]::-moz-range-progress {
background-color: green;
height: 1em;
}
### Result
A progress bar using this style might look something like this:
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-moz-range-progress` | No | No | 22 | No | No | No | 22 | No | No | No | No
## See also
* The pseudo-elements used by Gecko to style other parts of a range input:
* `::-moz-range-thumb` represents the indicator that slides in the groove.
* `::-moz-range-track` represents the groove in which the thumb slides.
* CSS-Tricks: Styling Cross-Browser Compatible Range Inputs with CSS
* QuirksMode: Styling and scripting sliders
# ::-moz-range-thumb
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
The `::-moz-range-thumb` CSS pseudo-element is a Mozilla extension that
represents the _thumb_ (i.e., virtual knob) of an ` ` of `type="range"`.
The user can move the thumb along the input's track to alter its numerical
value.
**Note:** Using `::-moz-range-thumb` with anything but an ` ` doesn't match anything and has no effect.
## Syntax
::-moz-range-thumb {
/* ... */
}
## Examples
### HTML
### CSS
input[type="range"]::-moz-range-thumb {
background-color: green;
}
### Result
A progress bar using this style might look something like this:
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-moz-range-thumb` | No | No | 21 | No | No | No | 21 | No | No | No | No
## See also
* The pseudo-elements used by Gecko to style other parts of a range input:
* `::-moz-range-track` represents the groove in which the thumb slides.
* `::-moz-range-progress` represents the lower portion of the track.
* Similar pseudo-elements used by other browsers:
* `::-webkit-slider-thumb`, pseudo-element supported by WebKit and Blink (Safari, Chrome, and Opera)
* CSS-Tricks: Styling Cross-Browser Compatible Range Inputs with CSS
* QuirksMode: Styling and scripting sliders
# ::-moz-range-track
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
The `::-moz-range-track` CSS pseudo-element is a Mozilla extension that
represents the _track_ (i.e., groove) in which the indicator slides in an
` ` of `type="range"`.
**Note:** Using `::-moz-range-track` with anything but an ` ` doesn't match anything and has no effect.
## Syntax
::-moz-range-track {
/* ... */
}
## Examples
### HTML
### CSS
input[type="range"]::-moz-range-track {
background-color: green;
}
### Result
A range slider using this style might look something like this:
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-moz-range-track` | No | No | 21 | No | No | No | 21 | No | No | No | No
## See also
* The pseudo-elements used by Gecko to style other parts of a range input:
* `::-moz-range-thumb` represents the indicator that slides in the groove.
* `::-moz-range-progress` represents the lower portion of the track.
* Similar pseudo-elements used by other browsers:
* `::-webkit-slider-runnable-track`, pseudo-element supported by WebKit and Blink (Safari, Chrome, and Opera)
* CSS-Tricks: Styling Cross-Browser Compatible Range Inputs with CSS
* QuirksMode: Styling and scripting sliders
# ::-webkit-scrollbar
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
The `::-webkit-scrollbar` CSS pseudo-element affects the style of an element's
scrollbar when it has scrollable overflow.
The `scrollbar-color` and `scrollbar-width` standard properties may be used as
alternatives for browsers that do not support this pseudo-element and the
related `::-webkit-scrollbar-*` pseudo-elements (see Browser compatibility).
**Note:** If `scrollbar-color` and `scrollbar-width` are supported and have
any value other than `auto` set, they will override `::-webkit-scrollbar-*`
styling. See Adding a fallback for scrollbar styles for more details.
## CSS Scrollbar Selectors
You can use the following pseudo-elements to customize various parts of the
scrollbar for WebKit browsers:
* `::-webkit-scrollbar` — the entire scrollbar.
* `::-webkit-scrollbar-button` — the buttons on the scrollbar (arrows pointing upwards and downwards that scroll one line at a time).
* `::-webkit-scrollbar:horizontal` — the horizontal scrollbar.
* `::-webkit-scrollbar-thumb` — the draggable scrolling handle.
* `::-webkit-scrollbar-track` — the track (progress bar) of the scrollbar, where there is a gray bar on top of a white bar.
* `::-webkit-scrollbar-track-piece` — the part of the track (progress bar) not covered by the handle.
* `::-webkit-scrollbar:vertical` — the vertical scrollbar.
* `::-webkit-scrollbar-corner` — the bottom corner of the scrollbar, where both horizontal and vertical scrollbars meet. This is often the bottom-right corner of the browser window.
* `::-webkit-resizer` — the draggable resizing handle that appears at the bottom corner of some elements.
## Accessibility
Authors should avoid styling scrollbars, as changing the appearance of
scrollbars away from the default breaks external consistency which negatively
impacts usability. If styling scrollbars, ensure there is enough color
contrast and touch targets are at least 44px wide and tall. See Techniques for
WCAG 2.0: G183: Using a contrast ratio of 3:1 and Understanding WCAG 2.1 :
Target Size.
## Examples
### Styling scrollbars using `-webkit-scrollbar`
#### CSS
.visible-scrollbar,
.invisible-scrollbar,
.mostly-customized-scrollbar {
display: block;
width: 10em;
overflow: auto;
height: 2em;
padding: 1em;
margin: 1em auto;
outline: 2px dashed cornflowerblue;
}
.invisible-scrollbar::-webkit-scrollbar {
display: none;
}
/* Demonstrate a "mostly customized" scrollbar
* (won't be visible otherwise if width/height is specified) */
.mostly-customized-scrollbar::-webkit-scrollbar {
width: 5px;
height: 8px;
background-color: #aaa; /* or add it to the track */
}
/* Add a thumb */
.mostly-customized-scrollbar::-webkit-scrollbar-thumb {
background: #000;
}
#### HTML
#### Result
### Adding a fallback for scrollbar styles
You can use a `@supports` at-rule to detect if a browser supports the standard
`scrollbar-color` and `scrollbar-width` properties, and otherwise use a
fallback with `::-webkit-scrollbar-*` pseudo-elements. The following example
shows how to apply colors to scrollbars using `scrollbar-color` if supported
and `::-webkit-scrollbar-*` pseudo-elements if not.
#### HTML
#### CSS
/* For browsers that support `scrollbar-*` properties */
@supports (scrollbar-color: auto) {
.scroll-box {
scrollbar-color: aquamarine cornflowerblue;
}
}
/* Otherwise, use `::-webkit-scrollbar-*` pseudo-elements */
@supports selector(::-webkit-scrollbar) {
.scroll-box::-webkit-scrollbar {
background: aquamarine;
}
.scroll-box::-webkit-scrollbar-thumb {
background: cornflowerblue;
}
}
#### Result
In the example below, you can scroll the bordered box vertically to see the
effect of styling the scrollbar.
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-scrollbar` | 2 | 79 | No | 15 | 4 | 18 | No | 14 | 3.2 | 1.0 | 4.4
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-scrollbar` | 2 | 79 | No | 15 | 4 | 18 | No | 14 | 3–13 | 1.0 | 4.4
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-scrollbar` | 2 | 79 | No | 15 | 4 | 18 | No | 14 | 3–13 | 1.0 | 4.4
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-scrollbar` | 2 | 79 | No | 15 | 4 | 18 | No | 14 | 3–13 | 1.0 | 4.4
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-scrollbar` | 2 | 79 | No | 15 | 4 | 18 | No | 14 | 3–13 | 1.0 | 4.4
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-scrollbar` | 2 | 79 | No | 15 | 4 | 18 | No | 14 | 3–13 | 1.0 | 4.4
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-scrollbar` | 2 | 79 | No | 15 | 4 | 18 | No | 14 | 3From Safari 13, only `display: none` works with this pseudo-element. Other styles have no effect. | 1.0 | 4.4
### css.selectors.-webkit-scrollbar
### css.selectors.-webkit-scrollbar-button
### css.selectors.-webkit-scrollbar-thumb
### css.selectors.-webkit-scrollbar-track
### css.selectors.-webkit-scrollbar-track-piece
### css.selectors.-webkit-scrollbar-corner
### css.selectors.-webkit-resizer
## See also
* `scrollbar-width`
* `scrollbar-color`
* Don't use custom scrollbars (2023)
* Scrollbar styling on developer.chrome.com (2024)
* Styling Scrollbars on WebKit.org (2009)
# ::-webkit-slider-runnable-track
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
The `::-webkit-slider-runnable-track` CSS pseudo-element represents the
"track" (the groove in which the indicator slides) of an .
## Syntax
::-webkit-slider-runnable-track {
/* ... */
}
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-slider-runnable-track` | ≤83 | ≤83 | No | ≤69 | 18 | ≤83 | No | ≤59 | 18 | ≤13.0 | ≤83
## See also
* `::-webkit-slider-thumb`
* Similar pseudo-elements used by other browsers:
* `::-moz-range-track`
* CSS-Tricks: Styling Cross-Browser Compatible Range Inputs with CSS
* QuirksMode: Styling and scripting sliders
# ::-webkit-slider-thumb
**Non-standard:** This feature is not standardized. We do not recommend using
non-standard features in production, as they have limited browser support, and
may change or be removed. However, they can be a suitable alternative in
specific cases where no standard option exists.
The `::-webkit-slider-thumb` CSS pseudo-element represents the "thumb" that
the user can move within the "groove" of an ` ` of `type="range"` to
alter its numerical value.
## Syntax
::-webkit-slider-thumb {
/* ... */
}
## Specifications
Not part of any standard.
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::-webkit-slider-thumb` | ≤83 | ≤83 | No | ≤69 | 18 | ≤83 | No | ≤59 | 18 | ≤13.0 | ≤83
## See also
* `::-webkit-slider-runnable-track`
* Similar pseudo-elements used by other browsers:
* `::-moz-range-thumb`
* CSS-Tricks: Styling Cross-Browser Compatible Range Inputs with CSS
* QuirksMode: Styling and scripting sliders
* Couple of Gotchas to Watch-out For
# ::after
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since July 2015.
* Learn more
* See full compatibility
* Report feedback
In CSS, `::after` creates a pseudo-element that is the last child of the
selected element. It is often used to add cosmetic content to an element with
the `content` property. It is inline by default.
## Try it
a::after {
content: " (" attr(href) ")";
}
.dead-link {
text-decoration: line-through;
}
.dead-link::after {
content: url("/shared-assets/images/examples/warning.svg");
display: inline-block;
width: 12px;
height: 12px;
}
The sailfish is named for its sail-like dorsal fin and is widely considered
the fastest fish in the ocean.
You can read more about it here .
The red lionfish is a predatory scorpionfish that lives on coral reefs of the
Indo-Pacific Ocean and more recently in the western Atlantic.
You can read more about it here .
## Syntax
::after {
content: /* value */;
/* properties */
}
## Description
The `::after` pseudo-element is an inline box generated as an immediate child
of the element it is associated with, or the "originating element". It is
often used to add cosmetic content to an element via the `content` property,
such as icons, quote marks, or other decoration.
`::after` pseudo-elements can't be applied to _replaced elements_ such as
` `, whose contents are determined by external resources and not affected
by the current document's styles.
An `::after` pseudo-element with a `display` value of `list-item` behaves like
a list item, and can therefore generate a `::marker` pseudo-element just like
an `` element.
If the `content` property is not specified, has an invalid value, or has
`normal` or `none` as a value, then the `::after` pseudo-element is not
rendered. It behaves as if `display: none` is set.
**Note:** The Selectors Level 3 specification introduced the double-colon
notation `::after` to distinguish pseudo-classes from pseudo-elements.
Browsers also accept single-colon notation `:after`, introduced in CSS2.
## Accessibility
Using an `::after` pseudo-element to add content is discouraged, as it is not
reliably accessible to screen readers.
## Examples
### Basic usage
Let's create two classes: one for boring paragraphs and one for exciting ones.
We can use these classes to add pseudo-elements to the end of paragraphs.
#### HTML
Here is some plain old boring text.
Here is some normal text that is neither boring nor exciting.
Contributing to MDN is easy and fun.
#### CSS
.exciting-text::after {
content: " <- EXCITING!";
color: darkgreen;
font-weight: bolder;
}
.boring-text::after {
content: " <- BORING";
color: darkviolet;
font-weight: bolder;
}
#### Result
### Decorative example
We can style text or images in the `content` property almost any way we want.
#### HTML
Look at the orange box after this text.
#### CSS
.ribbon {
background-color: #5bc8f7;
}
.ribbon::after {
content: "This is a fancy orange box.";
background-color: #ffba10;
border-color: black;
border-style: dotted;
}
#### Result
### Tooltips
This example uses `::after`, in conjunction with the `attr()` CSS expression
and a `data-description` custom data attribute, to create tooltips. No
JavaScript is required!
We can also support keyboard users with this technique, by adding a `tabindex`
of `0` to make each `span` keyboard focusable, and using a CSS `:focus`
selector. This shows how flexible `::before` and `::after` can be, though for
the most accessible experience a semantic disclosure widget created in some
other way (such as with details and summary elements) is likely to be more
appropriate.
#### HTML
Here we have some
text
with a few
tooltips .
#### CSS
span[data-description] {
position: relative;
text-decoration: underline;
color: #00f;
cursor: help;
}
span[data-description]:hover::after,
span[data-description]:focus::after {
content: attr(data-description);
position: absolute;
left: 0;
top: 24px;
min-width: 200px;
border: 1px #aaaaaa solid;
border-radius: 10px;
background-color: #ffffcc;
padding: 12px;
color: #000000;
font-size: 14px;
z-index: 1;
}
#### Result
### `::after::marker` nested pseudo-elements
The `::after::marker` nested pseudo-element selects the list `::marker` of an
`::after` pseudo-element that is itself a list item, that is, it has its
`display` property set to `list-item`.
In this demo, we generate extra list items before and after a list navigation
menu using `::before` and `::after` (setting them to `display: list-item` so
they behave like list items). We then use `ul::before::marker` and
`ul::after::marker` to give their list markers a different color.
#### HTML
#### CSS
ul {
font-size: 1.5rem;
font-family: Arial, Helvetica, sans-serif;
}
ul::before,
ul::after {
display: list-item;
color: orange;
}
ul::before {
content: "Start";
}
ul::after {
content: "End";
}
ul::before::marker,
ul::after::marker {
color: red;
}
#### Result
While the list bullets of the three navigation items are generated because
they are ` ` elements, "Start" and "End" have been inserted via pseudo-
elements and `::marker` is used to style their bullets.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::after` | 11 | 1212 | 1.5["Before Firefox 57, Firefox had a bug where `::after` pseudo-elements were still generated, even if the `content` property value were set to `normal` or `none`.", "Before Firefox 3.5, only the CSS level 2 behavior of `:after` was supported, which disallowed `position`, `float`, `list-style-*` and some `display` properties."]1 | 74 | 44 | 1818 | 4["Before Firefox for Android 57, Firefox for Android had a bug where `::after` pseudo-elements were still generated, even if the `content` property value were set to `normal` or `none`.", "Before Firefox for Android 4.5, only the CSS level 2 behavior of `:after` was supported, which disallowed `position`, `float`, `list-style-*` and some `display` properties."]4 | 10.110.1 | 3.23.2 | 1.01.0 | 4.44.4
`animation_and_transition_support` | 26 | 12 | 4 | 15 | 7 | 26 | 4 | 14 | 7 | 1.5 | 4.4
`nested_marker` | 135 | 135 | No | 120 | No | 135 | No | 89 | No | No | 135
## See also
* `::before`
* `content`
# ::backdrop
Baseline Widely available *
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since March 2022.
* Some parts of this feature may have varying levels of support.
* Learn more
* See full compatibility
* Report feedback
The `::backdrop` CSS pseudo-element is a box the size of the viewport, which
is rendered immediately beneath any element being presented in the top layer.
## Try it
button {
font-size: 1.2rem;
padding: 5px 15px;
}
dialog::backdrop {
background-color: salmon;
}
Show a dialog
const showDialogBtn = document.getElementById("showDialogBtn");
const favDialog = document.getElementById("favDialog");
showDialogBtn.addEventListener("click", () => favDialog.showModal());
## Syntax
::backdrop {
/* ... */
}
## Description
Backdrops appear in the following instances:
* Elements which have been placed in fullscreen mode using the Fullscreen API `Element.requestFullscreen()` method.
* `` elements that have been shown in the top layer via a `HTMLDialogElement.showModal()` call.
* Popover elements that have been shown in the top layer via a `HTMLElement.showPopover()` call.
When multiple elements have been placed into the top layer, each one has its
own `::backdrop` pseudo-element.
/* Backdrop is only displayed when dialog is opened with dialog.showModal() */
dialog::backdrop {
background: rgb(255 0 0 / 25%);
}
Elements are placed in a last-in/first out (LIFO) stack in the top layer. The
`::backdrop` pseudo-element makes it possible to obscure, style, or completely
hide everything located below a top layer element.
`::backdrop` neither inherits from nor is inherited by any other elements. No
restrictions are made on what properties apply to this pseudo-element.
## Examples
### Styling a modal dialog's backdrop
In this example, we use the `::backdrop` pseudo-element to style the backdrop
that is used when a modal `` is open.
#### HTML
We include a `` that, when clicked, will open the included ``.
When the `` is opened, we give focus to the button that closes the
dialog:
Close
This modal dialog has a beautiful backdrop!
Show the dialog
#### CSS
We add a background to the backdrop, creating a colorful donut using CSS
gradients:
::backdrop {
background-image:
radial-gradient(
circle,
#fff 0 5vw,
transparent 5vw 20vw,
#fff 20vw 22.5vw,
#eee 22.5vw
),
conic-gradient(
#272b66 0 50grad,
#2d559f 50grad 100grad,
#9ac147 100grad 150grad,
#639b47 150grad 200grad,
#e1e23b 200grad 250grad,
#f7941e 250grad 300grad,
#662a6c 300grad 350grad,
#9a1d34 350grad 400grad,
#43a1cd 100grad 150grad,
#ba3e2e
);
}
#### JavaScript
The dialog is opened modally using the `.showModal()` method and closed using
the `.close()` method.
const dialog = document.querySelector("dialog");
const showButton = document.querySelector("dialog + button");
const closeButton = document.querySelector("dialog button");
// "Show the dialog" button opens the dialog modally
showButton.addEventListener("click", () => {
dialog.showModal();
});
// "Close" button closes the dialog
closeButton.addEventListener("click", () => {
dialog.close();
});
#### Results
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::backdrop` | 3732 | 7912–79 | 47 | 2419 | 15.4 | 3732 | 47 | 2419 | 15.4 | 3.02.0 | 374.4.3
`dialog` | 32 | 79 | 98 | 19 | 15.4 | 32 | 98 | 19 | 15.4 | 2.0 | 4.4.3
`fullscreen` | 69 | 12 | 47 | 56 | 16.4 | 69 | 47 | 48 | 16.4 | 10.0 | 69
`inherit_from_originating_element` | 122 | 122 | 120 | 108 | 17.4 | 122 | 120 | 81 | 17.4 | 26.0 | 122
`popover` | 114 | 114 | 125 | 100 | 17 | 114 | 125 | 76 | 17 | 23.0 | 114
## See also
* `:fullscreen` pseudo-class
* `` HTML element
* Fullscreen API
* `popover` HTML global attribute
* Popover API
# ::before
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since July 2015.
* Learn more
* See full compatibility
* Report feedback
In CSS, `::before` creates a pseudo-element that is the first child of the
selected element. It is often used to add cosmetic content to an element with
the `content` property. It is inline by default.
## Try it
a {
color: #0000ff;
text-decoration: none;
}
a::before {
content: "🔗";
}
.local-link::before {
content: url("/shared-assets/images/examples/firefox-logo.svg");
display: inline-block;
width: 15px;
height: 15px;
margin-right: 5px;
}
Learning resources for web developers can be found all over the internet. Try
out
web.dev ,
w3schools.com or our
MDN web docs .
## Syntax
::before {
content: /* value */;
/* properties */
}
## Description
The `::before` pseudo-element is an inline box generated as an immediate child
of the element it is associated with, or the "originating element". It is
often used to add cosmetic content to an element via the `content` property,
such as icons, quote marks, or other decoration.
`::before` pseudo-elements can't be applied to _replaced elements_ such as
` `, whose contents are determined by external resources and not affected
by the current document's styles.
A `::before` pseudo-element with a `display` value of `list-item` behaves like
a list item, and can therefore generate a `::marker` pseudo-element just like
an `` element.
If the `content` property is not specified, has an invalid value, or has
`normal` or `none` as a value, then the `::before` pseudo-element is not
rendered. It behaves as if `display: none` is set.
**Note:** The Selectors Level 3 specification introduced the double-colon
notation `::before` to distinguish pseudo-classes from pseudo-elements.
Browsers also accept single-colon notation `:before`, introduced in CSS2.
## Accessibility
Using a `::before` pseudo-element to add content is discouraged, as it is not
reliably accessible to screen readers.
## Examples
### Quotation marks
One example of using `::before` pseudo-elements is to provide quotation marks.
Here we use both `::before` and `::after` to insert quotation characters.
#### HTML
Some quotes , he said, are better than none.
#### CSS
q::before {
content: "«";
color: blue;
}
q::after {
content: "»";
color: red;
}
#### Result
### Decorative example
We can style text or images in the `content` property almost any way we want.
#### HTML
Notice where the orange box is.
#### CSS
.ribbon {
background-color: #5bc8f7;
}
.ribbon::before {
content: "Look at this orange box.";
background-color: #ffba10;
border-color: black;
border-style: dotted;
}
#### Result
### To-do list
In this example we will create a to-do list using pseudo-elements. This method
can often be used to add small touches to the UI and improve user experience.
#### HTML
Buy milk
Take the dog for a walk
Exercise
Write code
Play music
Relax
#### CSS
li {
list-style-type: none;
position: relative;
margin: 2px;
padding: 0.5em 0.5em 0.5em 2em;
background: lightgrey;
font-family: sans-serif;
}
li.done {
background: #ccff99;
}
li.done::before {
content: "";
position: absolute;
border-color: #009933;
border-style: solid;
border-width: 0 0.3em 0.25em 0;
height: 1em;
top: 1.3em;
left: 0.6em;
margin-top: -1em;
transform: rotate(45deg);
width: 0.5em;
}
#### JavaScript
const list = document.querySelector("ul");
list.addEventListener(
"click",
(ev) => {
if (ev.target.tagName === "LI") {
ev.target.classList.toggle("done");
}
},
false,
);
Here is the above code example running live. Note that there are no icons
used, and the check-mark is actually the `::before` that has been styled in
CSS. Go ahead and get some stuff done.
#### Result
### Unicode escape sequences
As generated content is CSS, not HTML, you **can't** use markup entities in
content values. If you need to use a special character, and can't enter it
literally into your CSS content string, use a unicode escape sequence. This
consists of a backslash followed by the character's hexadecimal unicode value.
#### HTML
Crack Eggs into bowl
Add Milk
Add Flour
Mix thoroughly into a smooth batter
Pour a ladleful of batter onto a hot, greased, flat frying pan
Fry until the top of the pancake loses its gloss
Flip it over and fry for a couple more minutes
serve with your favorite topping
#### CSS
li {
padding: 0.5em;
}
li[aria-current="step"] {
font-weight: bold;
}
li[aria-current="step"]::before {
content: "\21E8 "; /* Unicode escape sequence for "Rightwards White Arrow" */
display: inline;
}
#### Result
### `::before::marker` nested pseudo-elements
The `::before::marker` nested pseudo-element selects the list `::marker` of an
`::after` pseudo-element that is itself a list item, that is, it has its
`display` property set to `list-item`.
In this demo, we generate extra list items before and after a list navigation
menu using `::before` and `::after` (setting them to `display: list-item` so
they behave like list items). We then use `ul::before::marker` and
`ul::after::marker` to give their list markers a different color.
#### HTML
#### CSS
ul {
font-size: 1.5rem;
font-family: Arial, Helvetica, sans-serif;
}
ul::before,
ul::after {
display: list-item;
color: orange;
}
ul::before {
content: "Start";
}
ul::after {
content: "End";
}
ul::before::marker,
ul::after::marker {
color: red;
}
#### Result
While the list bullets of the three navigation items are generated because
they are ` ` elements, "Start" and "End" have been inserted via pseudo-
elements and `::marker` is used to style their bullets.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::before` | 11 | 1212 | 1.5["Before Firefox 57, Firefox had a bug where `::before` pseudo-elements were still generated, even if the `content` property value were set to `normal` or `none`.", "Before Firefox 3.5, only the CSS level 2 behavior of `:before` was supported, which disallowed `position`, `float`, `list-style-*` and some `display` properties."]1 | 74 | 44 | 1818 | 4Before Firefox 57, Firefox had a bug where `::before` pseudo-elements were still generated, even if the `content` property value were set to `normal` or `none`.4 | 10.110.1 | 33 | 1.01.0 | 4.44.4
`animation_and_transition_support` | 26 | 12 | 4 | 15 | 7 | 26 | 4 | 14 | 7 | 1.5 | 4.4
`nested_marker` | 135 | 135 | No | 120 | No | 135 | No | 89 | No | No | 135
## See also
* `::after`
* `content`
# ::checkmark
Limited availability
This feature is not Baseline because it does not work in some of the most
widely-used browsers.
* Learn more
* See full compatibility
* Report feedback
**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in
production.
The `::checkmark` CSS pseudo-element targets the checkmark placed inside the
currently-selected `` element of a customizable select element. It can
be used to provide a visual indication of which option is selected.
## Try it
Select pet:
Cat
Dog
Chicken
option::checkmark {
color: orange;
font-size: 1.5rem;
}
select,
::picker(select) {
appearance: base-select;
width: 200px;
}
select {
border: 2px solid #ddd;
background: #eee;
padding: 10px;
}
::picker(select) {
border: none;
}
option {
border: 2px solid #ddd;
background: #eee;
padding: 10px;
}
option:first-of-type {
border-radius: 8px 8px 0 0;
}
option:last-of-type {
border-radius: 0 0 8px 8px;
}
option:nth-of-type(odd) {
background: #fff;
}
option:not(option:last-of-type) {
border-bottom: none;
}
## Syntax
::checkmark {
/* ... */
}
## Description
The `::checkmark` pseudo-element targets the checkmark placed inside a
customizable select element's currently-selected ` `.
It is only available to target when the originating element has a picker and
has base appearance set on it via the `appearance` property `base-select`
value. Its generated box appears before any boxes generated by the `::before`
pseudo-element. The icon can be customized using the `content` property.
The `::checkmark` selector is useful for example if you want to hide the
checkmark, use a custom icon, or adjust the checkmark's rendering position
inside ` ` elements.
**Note:** The `::checkmark` pseudo-element is not included in the
accessibility tree, so any generated `content` set on it will not be announced
by assistive technologies. You should still make sure that any new icon you
set visually makes sense for its intended purpose.
## Examples
### Customizing the checkmark
To opt-in to customizable select functionality, the `` element and its
picker both need to have an `appearance` value of `base-select` set on them:
select,
::picker(select) {
appearance: base-select;
}
Assuming flexbox is being used to lay out the `` elements (which is
true in **current implementations** of customizable selects), you could then
move the checkmark from the start of the row to the end by setting an `order`
value on it greater than `0`, and aligning it to the end of the row using an
`auto` `margin-left` value (see Alignment and auto margins).
The value of the `content` property could also be set to a different emoji to
change the displayed icon.
option::checkmark {
order: 1;
margin-left: auto;
content: "☑️";
}
See Styling the current selection checkmark for a full example that uses this
code, along with a live example rendering.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::checkmark` | 133 | 133 | No | 118 | No | 133 | No | 88 | No | No | 133
## See also
* ``, ``, ` `, ``, ``, ``
* `appearance`
* `::picker(select)`, `::picker-icon`
* `:open`, `:checked`
* Customizable select elements
# ::column
**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in
production.
The `::column` CSS pseudo-element represents the individual columns generated
when a container is set to display its content in multiple columns via CSS
multi-column layout. The `::column` pseudo-element enables applying styles
that do not affect the layout to these generated fragments.
## Syntax
::column {
/* ... */
}
## Description
When CSS multi-column layout is used to lay out a container's content in
multiple columns (for example, using the `column-count` property), `::column`
pseudo-elements are generated to contain each individual column.
The `::column` pseudo-element only accepts scroll snap properties that apply
to elements inside a scroll container, including `scroll-margin`, `scroll-
snap-align`, and `scroll-snap-stop`.
The `::column` pseudo-element can have a `::scroll-marker` pseudo-element.
Other pseudo-elements like `::before` and `::after` are not generated on
`::column`. Applying `::column::scroll-marker` creates a marker for every
column of the originating scroll container, with the `::scroll-marker` pseudo-
elements inheriting from the `::column` pseudo-element's originating element
rather than the `::column` itself.
This is useful for CSS carousels — `::column` can be used to generate
`::scroll-marker` pseudo-elements for each column, and set them as snap
targets using CSS scroll snap.
While the styling that can be applied to `::column` is very limited, it may be
expanded in the future. Any properties and values supported in the future will
be limited to ones that do not affect layout.
## Examples
### Scrolling column layout
This demo creates a responsive container that snaps each "page" of content
into place. It uses the `columns` property and the `::columns` pseudo-element
to create content columns that span the full width of their parent scroll
container, which can be scrolled horizontally. Each column contains one or
more list items, which vary in number depending on the viewport width.
#### HTML
The HTML consists of an unordered list, with each list item containing some
sample content:
#### CSS
The list is given a fixed `height` and a `width` of `100vw` to make it span
the full width of the viewport. An `overflow-x` value of `scroll` is then set
so that the content will scroll horizontally, and CSS scroll snap is used to
snap to each item or "page" — a `scroll-snap-type` value of `x mandatory` is
used to make the list into a scroll snap container. Finally, a `columns` value
of `1` is set to force the list contents to display as a single column. A
`text-align` value of `center` is also applied, to align the content with the
center of the list.
ul {
width: 100vw;
height: 300px;
padding: 10px;
overflow-x: scroll;
scroll-snap-type: x mandatory;
columns: 1;
text-align: center;
}
The list items are then styled:
* A `display` value of `inline-block` is set to make the list items sit alongside one another and make the list scroll horizontally.
* A fixed `width` and `height` has been set on them.
* A `text-align` value of `left` is set on them to override the `text-align: center` set on the parent container, so the item content will be left-aligned.
* Every even-numbered list item is given a different background-color via `:nth-child()`, so that it is easier to see the scrolling effect.
li {
list-style-type: none;
display: inline-block;
height: 100%;
width: 200px;
text-align: left;
background-color: #eee;
outline: 1px solid #ddd;
padding: 0 20px;
margin: 0 10px;
}
li:nth-child(even) {
background-color: cyan;
}
The `scroll-snap-align` property is set on the `::column` pseudo-elements —
which represent the content columns generated by the `columns` property — so
that when scrolled, a column is snapped to be centered within the scroll
container.
ul::column {
scroll-snap-align: center;
}
#### Result
### Column-based carousel with scroll markers
Expanding on the previous example, we will create scroll markers to enable
direct navigation to different columns by applying a `scroll-marker-group` to
the container and a `::scroll-marker` to each `::column` pseudo-element. The
HTML remains unchanged.
#### CSS
We create a scroll marker group with the `scroll-marker-group` property,
placing the group after all the content:
ul {
scroll-marker-group: after;
}
We then apply styles to the `::scroll-marker-group` pseudo-element to lay out
the scroll markers in the center of the row with a `0.4em` gap between each
one:
::scroll-marker-group {
display: flex;
gap: 0.4em;
place-content: center;
}
Finally, we use the `::scroll-marker` pseudo-element to create a round,
transparent marker for each list item with a black border, then style the
marker of the currently-scrolled element differently from the others,
targeting the marker with the `:target-current` pseudo-class:
ul::column::scroll-marker {
content: "";
width: 16px;
height: 16px;
background-color: transparent;
border: 2px solid black;
border-radius: 10px;
}
ul::column::scroll-marker:target-current {
background-color: black;
}
#### Result
Try pressing the scroll markers to jump straight to each page. Note how the
current marker is highlighted so you can see where you are in the pagination.
Also try tabbing to the scroll marker group, then use the cursor keys to cycle
through each page.
See Creating CSS carousels for more carousel examples.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::column` | 135 | 135 | No | 120 | No | 135 | No | 89 | No | No | 135
`nested_scroll-marker` | 135 | 135 | No | 120 | No | 135 | No | 89 | No | No | 135
## See also
* `columns`
* `::scroll-marker`
* `::scroll-marker-group`
* `:target-current`
* Creating CSS carousels
* CSS multi-column layout module
* CSS overflow module
* CSS Carousel Gallery via chrome.dev (2025)
# ::cue
Baseline Widely available *
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since January 2020.
* Some parts of this feature may have varying levels of support.
* Learn more
* See full compatibility
* Report feedback
The `::cue` CSS pseudo-element matches WebVTT cues within a selected element.
This can be used to style captions and other cues in media with VTT tracks.
## Try it
video {
width: 100%;
}
video::cue {
font-size: 1rem;
color: yellow;
}
::cue(u) {
color: red;
}
Sorry, your browser doesn't support embedded videos.
The properties are applied to the entire set of cues as if they were a single
unit. The only exception is that `background` and its longhand properties
apply to each cue individually, to avoid creating boxes and obscuring
unexpectedly large areas of the media.
In the example above, the `::cue(u)` selector selects all the `` elements
inside the cue text.
## Syntax
::cue | ::cue() {
/* ... */
}
## Permitted properties
Rules whose selectors include this element may only use the following CSS
properties:
* `background`
* `background-attachment`
* `background-clip`
* `background-color`
* `background-image`
* `background-origin`
* `background-position`
* `background-repeat`
* `background-size`
* `color`
* `font`
* `font-family`
* `font-size`
* `font-stretch`
* `font-style`
* `font-variant`
* `font-weight`
* `line-height`
* `opacity`
* `outline`
* `outline-color`
* `outline-style`
* `outline-width`
* `ruby-position`
* `text-combine-upright`
* `text-decoration`
* `text-decoration-color`
* `text-decoration-line`
* `text-decoration-style`
* `text-decoration-thickness`
* `text-shadow`
* `visibility`
* `white-space`
## Examples
### Styling WebVTT cues as white-on-black
The following CSS sets the cue style so that the text is white and the
background is a translucent black box.
::cue {
color: #fff;
background-color: rgb(0 0 0 / 60%);
}
### Styling WebVTT internal node objects
Cue text can include _internal node objects_ as the tags (similar to HTML
elements) ``, ``, ``, ``, ``, ``, ``, and ``.
The `::cue()` selector can be used to apply styles to content inside these
tags to customize how the WebVTT track is displayed. Consider the following
cue text that uses the `` tag to underline some text:
00:00:01.500 --> 00:00:02.999 line:80%
Tell me, is the lord of the universe in?
The following CSS rule customizes the text inside the `` tag with a color
and a text-decoration:
::cue(u) {
color: red;
text-decoration: wavy overline lime;
}
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::cue` | 26 | 79 | 55From Firefox 69, only allowed properties apply to the `::cue` pseudo-element with no argument. See Permitted properties for a list of the allowed properties. | 15 | 7 | 26 | 55 | 14 | 7 | 1.5 | 4.4
`selector_argument` | 26 | 79 | No | 15 | 7 | 26 | No | 14 | 7 | 1.5 | 4.4
## See also
* Web Video Tracks Format (WebVTT)
* ``, ``
# ::details-content
Limited availability
This feature is not Baseline because it does not work in some of the most
widely-used browsers.
* Learn more
* See full compatibility
* Report feedback
The `::details-content` CSS pseudo-element represents the
expandable/collapsible contents of a `` element.
## Try it
details[open]::details-content {
color: dodgerblue;
padding: 0.5em;
border: thin solid grey;
}
Example summary
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Architecto cupiditate ea optio modi quas sequi, esse libero asperiores
debitis eveniet commodi hic ad.
## Syntax
selector::details-content
## Examples
### Basic example
In this example the `::details-content` pseudo-element is used to set a
`background-color` on the content of the `` element.
#### HTML
Click me
Here is some content
#### CSS
details::details-content {
background-color: #a29bfe;
}
#### Result
### Transition example
In this example the `::details-content` pseudo-element is used to set a
`transition` on the content of the `` element so that it smoothly
fades into view when expanded, and fades out again when collapsed. To achieve
this, two separate transitions are specified inside the `transition` shorthand
property:
* The `opacity` property is given a basic transition over `600ms` to create the fade-in/fade-out effect.
* The `content-visibility` property (which is toggled between `hidden` and `visible` when the `` content is expanded/collapsed) is also given a basic `600ms` transition, but with the `transition-behavior` value `allow-discrete` specified. This opts the browser into having a transition started on `content-visibility`, the animation behavior of which is discrete. The effect is that the content is visible for the entire duration of the transition, allowing other transitions to be seen. If this transition was not included, the content would immediately disappear when the `` content was collapsed — you wouldn't see the smooth fade-out.
#### HTML
Click me
Here is some content
#### CSS
details::details-content {
opacity: 0;
transition:
opacity 600ms,
content-visibility 600ms allow-discrete;
}
details[open]::details-content {
opacity: 1;
}
#### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::details-content` | 131 | 131 | 138 | 116 | 18.4 | 131 | No | 87 | 18.4 | No | 131
## See also
* ``
* ``
# ::file-selector-button
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since April 2021.
* Learn more
* See full compatibility
* Report feedback
The `::file-selector-button` CSS pseudo-element represents the button of an
` ` of `type="file"`.
## Try it
input {
margin-top: 1rem;
}
input::file-selector-button {
font-weight: bold;
color: dodgerblue;
padding: 0.5em;
border: thin solid grey;
border-radius: 3px;
}
Choose a profile picture:
## Syntax
::file-selector-button {
/* ... */
}
## Examples
### Basic example
#### HTML
#### CSS
input[type="file"]::file-selector-button {
border: 2px solid #6c5ce7;
padding: 0.2em 0.4em;
border-radius: 0.2em;
background-color: #a29bfe;
transition: 1s;
}
input[type="file"]::file-selector-button:hover {
background-color: #81ecec;
border: 2px solid #00cec9;
}
#### Result
Note that `::file-selector-button` is a whole element, and as such matches the
rules from the UA stylesheet. In particular, fonts and colors won't
necessarily inherit from the `input` element.
### Fallback example
#### HTML
#### CSS
input[type="file"]::file-selector-button {
border: 2px solid #6c5ce7;
padding: 0.2em 0.4em;
border-radius: 0.2em;
background-color: #a29bfe;
transition: 1s;
}
input[type="file"]::-ms-browse:hover {
background-color: #81ecec;
border: 2px solid #00cec9;
}
input[type="file"]::-webkit-file-upload-button:hover {
background-color: #81ecec;
border: 2px solid #00cec9;
}
input[type="file"]::file-selector-button:hover {
background-color: #81ecec;
border: 2px solid #00cec9;
}
#### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::file-selector-button` | 891 | 897912–79 | 82 | 7515 | 14.13 | 8918 | 82 | 6314 | 14.51 | 15.01.0 | 894.4
## See also
* WebKit CSS extensions
* File and Directory Entries API
* ` `
# ::first-letter
Baseline Widely available *
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since July 2015.
* Some parts of this feature may have varying levels of support.
* Learn more
* See full compatibility
* Report feedback
The `::first-letter` CSS pseudo-element applies styles to the first letter of
the first line of a block container, but only when not preceded by other
content (such as images or inline tables).
## Try it
p::first-letter {
font-size: 1.5rem;
font-weight: bold;
color: brown;
}
Scientists exploring the depths of Monterey Bay unexpectedly encountered a
rare and unique species of dragonfish. This species is the rarest of its
species.
When Robison and a team of researchers discovered this fish, they were aboard
a week-long expedition.
The first letter of an element is not always trivial to identify:
* Punctuation that precedes or immediately follows the first letter is included in the match. Punctuation includes any Unicode character defined in the _open_ (Ps), _close_ (Pe), _initial quote_ (Pi), _final quote_ (Pf), and _other punctuation_ (Po) classes.
* Some languages have digraphs that are always capitalized together, like the `IJ` in Dutch. In these cases, both letters of the digraph should be matched by the `::first-letter` pseudo-element.
* A combination of the `::before` pseudo-element and the `content` property may inject some text at the beginning of the element. In that case, `::first-letter` will match the first letter of this generated content.
**Note:** CSS introduced the `::first-letter` notation (with two colons) to
distinguish pseudo-classes from pseudo-elements. For backward compatibility,
browsers also accept `:first-letter`, introduced earlier.
Browser support for digraphs such as `IJ` in Dutch is poor. Check the
compatibility table below to see the current state of support.
## Allowable properties
Only a small subset of CSS properties can be used with the `::first-letter`
pseudo-element:
* All font properties: `font`, `font-style`, `font-feature-settings`, `font-kerning`, `font-language-override`, `font-stretch`, `font-synthesis`, `font-variant`, `font-variant-alternates`, `font-variant-caps`, `font-variant-east-asian`, `font-variant-ligatures`, `font-variant-numeric`, `font-variant-position`, `font-weight`, `font-size`, `font-size-adjust`, `line-height` and `font-family`
* All background properties: `background`, `background-color`, `background-image`, `background-clip`, `background-origin`, `background-position`, `background-repeat`, `background-size`, `background-attachment`, and `background-blend-mode`
* All margin properties: `margin`, `margin-top`, `margin-right`, `margin-bottom`, `margin-left`
* All padding properties: `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left`
* All border properties: the shorthands `border`, `border-style`, `border-color`, `border-width`, `border-radius`, `border-image`, and the longhands properties
* The `color` property
* The `text-decoration`, `text-shadow`, `text-transform`, `letter-spacing`, `word-spacing` (when appropriate), `line-height`, `text-decoration-color`, `text-decoration-line`, `text-decoration-style`, `box-shadow`, `float`, `vertical-align` (only if `float` is `none`) CSS properties
## Syntax
::first-letter {
/* ... */
}
## Examples
### Basic drop cap
In this example we will use the `::first-letter` pseudo-element to create a
drop cap effect on the first letter of the paragraph coming right after the
``.
#### HTML
My heading
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
kasd gubergren, no sea takimata sanctus est.
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie
consequat.
#### CSS
p {
width: 500px;
line-height: 1.5;
}
h2 + p::first-letter {
color: white;
background-color: black;
border-radius: 2px;
box-shadow: 3px 3px 0 red;
font-size: 250%;
padding: 6px 3px;
margin-right: 6px;
float: left;
}
#### Result
### Effect on special punctuation and non-Latin characters
This example illustrates the effect of `::first-letter` on special punctuation
and non-Latin characters.
#### HTML
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie
consequat.
-The beginning of a special punctuation mark.
_The beginning of a special punctuation mark.
"The beginning of a special punctuation mark.
'The beginning of a special punctuation mark.
*The beginning of a special punctuation mark.
#The beginning of a special punctuation mark.
「特殊的汉字标点符号开头。
《特殊的汉字标点符号开头。
"特殊的汉字标点符号开头。
#### CSS
p::first-letter {
color: red;
font-size: 150%;
}
#### Result
### Styling first letter in SVG text element
In this example, we use the `::first-letter` pseudo-element to style the first
letter of a SVG `` element.
**Note:** At time of writing this feature has limited support.
#### HTML
First letter in <text> SVG
#### CSS
text {
font-family: sans-serif;
}
text::first-letter {
font-family: serif;
font-size: 2rem;
font-weight: 600;
fill: tomato;
stroke: indigo;
}
#### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::first-letter` | 11 | 1212 | 11 | 73.5 | 11 | 1818 | 44 | 10.110.1 | 11 | 1.01.0 | 3737
`dutch_ij_digraph` | No | No | 87 | No | No | No | 87 | No | No | No | No
`svg_text_element` | No | No | 124 | No | No | No | 124 | No | No | No | No
## See also
* `::first-line`
# ::first-line
Baseline Widely available *
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since July 2015.
* Some parts of this feature may have varying levels of support.
* Learn more
* See full compatibility
* Report feedback
The `::first-line` CSS pseudo-element applies styles to the first line of a
block container.
## Try it
p::first-line {
font-size: 1.2rem;
font-weight: bold;
text-decoration: underline;
}
In warm ocean waters around the world, you may see a strange sight: A fish
leaping from the water and soaring dozens of meters before returning to the
ocean's depths. Early Mediterranean sailors thought these flying fish returned
to the shore at night to sleep, and therefore called this family of marine
fish Exocoetidae.
The effects of `::first-line` are limited by the length and content of the
first line of text in the element. The length of the first line depends on
many factors, including the width of the element, the width of the document,
and the font size of the text. `::first-line` has no effect when the first
child of the element, which would be the first part of the first line, is an
inline block-level element, such as an inline table.
**Note:** Selectors Level 3 introduced the double-colon notation (`::`) to
distinguish pseudo-elements from the single-colon (`:`) pseudo-classes.
Browsers accept both `::first-line` and `:first-line`, which was introduced in
CSS2.
For the purposes of CSS `background`, the `::first-line` pseudo-element is
like an inline-level element meaning that in a left-justified first line, the
background may not extend all the way to the right margin.
## Allowable properties
Only a small subset of CSS properties can be used with the `::first-line`
pseudo-element:
* All font-related properties: `font`, `font-kerning`, `font-style`, `font-variant`, `font-variant-numeric`, `font-variant-position`, `font-variant-east-asian`, `font-variant-caps`, `font-variant-alternates`, `font-variant-ligatures`, `font-synthesis`, `font-feature-settings`, `font-language-override`, `font-weight`, `font-size`, `font-size-adjust`, `font-stretch`, and `font-family`
* All background-related properties: `background-color`, `background-clip`, `background-image`, `background-origin`, `background-position`, `background-repeat`, `background-size`, `background-attachment`, and `background-blend-mode`
* The `color` property
* `word-spacing`, `letter-spacing`, `text-decoration`, `text-transform`, and `line-height`
* `text-shadow`, `text-decoration`, `text-decoration-color`, `text-decoration-line`, `text-decoration-style`, and `vertical-align`.
## Syntax
::first-line {
/* ... */
}
## Examples
### Styling first line of a paragraph
#### HTML
Styles will only be applied to the first line of this paragraph. After that,
all text will be styled like normal. See what I mean?
The first line of this text will not receive special styling because it is not
a block-level element.
#### CSS
::first-line {
color: blue;
font-weight: bold;
/* WARNING: DO NOT USE THESE */
/* Many properties are invalid in ::first-line pseudo-elements */
margin-left: 20px;
text-indent: 20px;
}
### Result
### Styling the first line of a SVG text element
In this example, we style the first line of an SVG `` element using the
`::first-line` pseudo-element.
**Note:** At time of writing this feature has limited support.
#### HTML
Here is an English paragraph
that is broken into multiple lines
in the source code so that it can
be more easily read and edited
in a text editor.
#### CSS
In order to make the SVG `` element wrap to multiple lines, we use the
`white-space` CSS property. We then select the first line using the `::first-
line` pseudo-element.
text {
white-space: break-spaces;
}
text::first-line {
fill: blue;
font-weight: bold;
}
#### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::first-line` | 1Before Chrome 62, the `text-transform` property does not work on `::first-line` pseudo-elements. See bug 40214861.1Before Chrome 62, the `text-transform` property does not work on `::first-line` pseudo-elements. See bug 40214861. | 1212 | 11 | 7From Opera 15 to Opera 49 (exclusive), the `text-transform` property does not work on `::first-line` or `:first-line` pseudo-elements. See bug 40214861.3.5From Opera 15 to Opera 49 (exclusive), the `text-transform` property does not work on `::first-line` or `:first-line` pseudo-elements. See bug 40214861. | 1The `text-transform` property does not work for `::first-line` or `:first-line` pseudo-elements. See bug 3409.1The `text-transform` property does not work for `::first-line` or `:first-line` pseudo-elements. See bug 3409. | 18Before Chrome Android 62, the `text-transform` property does not work on `::first-line` pseudo-elements. See bug 40214861.18Before Chrome Android 62, the `text-transform` property does not work on `::first-line` pseudo-elements. See bug 40214861. | 44 | 10.1From Opera 15 to Opera 49 (exclusive), the `text-transform` property does not work on `::first-line` or `:first-line` pseudo-elements. See bug 40214861.10.1From Opera 15 to Opera 49 (exclusive), the `text-transform` property does not work on `::first-line` or `:first-line` pseudo-elements. See bug 40214861. | 1The `text-transform` property does not work for `::first-line` or `:first-line` pseudo-elements. See bug 3409.1The `text-transform` property does not work for `::first-line` or `:first-line` pseudo-elements. See bug 3409. | 1.0Before Samsung Internet 8.0, the `text-transform` property does not work on `::first-line` pseudo-elements. See bug 40214861.1.0Before Samsung Internet 8.0, the `text-transform` property does not work on `::first-line` pseudo-elements. See bug 40214861. | 4.4Before WebView Android 62, the `text-transform` property does not work on `::first-line` pseudo-elements. See bug 40214861.4.4Before WebView Android 62, the `text-transform` property does not work on `::first-line` pseudo-elements. See bug 40214861.
`svg_text_element` | No | No | 124 | No | No | No | 124 | No | No | No | No
## See also
* `::first-letter`
* `white-space`
# ::grammar-error
Limited availability
This feature is not Baseline because it does not work in some of the most
widely-used browsers.
* Learn more
* See full compatibility
* Report feedback
The `::grammar-error` CSS pseudo-element represents a text segment which the
user agent has flagged as grammatically incorrect.
## Allowable properties
Only a small subset of CSS properties can be used in a rule with `::grammar-
error` in its selector:
* `color`
* `background-color`
* `cursor`
* `caret-color`
* `outline` and its longhands
* `text-decoration` and its associated properties
* `text-emphasis-color`
* `text-shadow`
## Syntax
::grammar-error {
/* ... */
}
## Examples
### Basic document grammar check
In this example, eventual supporting browsers should highlight any flagged
grammatical errors with the styles shown.
#### HTML
My friends is coming to the party tonight.
#### CSS
::grammar-error {
text-decoration: underline red;
color: red;
}
#### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::grammar-error` | 121 | 121 | No | 107 | 17.4 | 121 | No | 81 | 17.4 | 25.0 | 121
## See also
* `::spelling-error`
* `text-decoration-line`
# ::highlight()
Limited availability
This feature is not Baseline because it does not work in some of the most
widely-used browsers.
* Learn more
* See full compatibility
* Report feedback
The `::highlight()` CSS pseudo-element applies styles to a custom highlight.
A custom highlight is a collection of `Range` objects and is registered on a
webpage using the `HighlightRegistry`.
## Allowable properties
Only certain CSS properties can be used with `::highlight()`:
* `color`
* `background-color`
* `text-decoration` and its associated properties
* `text-shadow`
* `-webkit-text-stroke-color`, `-webkit-text-fill-color` and `-webkit-text-stroke-width`
In particular, `background-image` is ignored.
## Syntax
::highlight(custom-highlight-name)
## Examples
### Highlighting characters
#### HTML
CSS Custom Highlight API rainbow
#### CSS
#rainbow-text {
font-family: monospace;
font-size: 1.5rem;
}
::highlight(rainbow-color-1) {
color: #ad26ad;
text-decoration: underline;
}
::highlight(rainbow-color-2) {
color: #5d0a99;
text-decoration: underline;
}
::highlight(rainbow-color-3) {
color: #0000ff;
text-decoration: underline;
}
::highlight(rainbow-color-4) {
color: #07c607;
text-decoration: underline;
}
::highlight(rainbow-color-5) {
color: #b3b308;
text-decoration: underline;
}
::highlight(rainbow-color-6) {
color: #ffa500;
text-decoration: underline;
}
::highlight(rainbow-color-7) {
color: #ff0000;
text-decoration: underline;
}
#### JavaScript
const textNode = document.getElementById("rainbow-text").firstChild;
if (!CSS.highlights) {
textNode.textContent =
"The CSS Custom Highlight API is not supported in this browser!";
}
// Create and register highlights for each color in the rainbow.
const highlights = [];
for (let i = 0; i < 7; i++) {
// Create a new highlight for this color.
const colorHighlight = new Highlight();
highlights.push(colorHighlight);
// Register this highlight under a custom name.
CSS.highlights.set(`rainbow-color-${i + 1}`, colorHighlight);
}
// Iterate over the text, character by character.
for (let i = 0; i < textNode.textContent.length; i++) {
// Create a new range just for this character.
const range = new Range();
range.setStart(textNode, i);
range.setEnd(textNode, i + 1);
// Add the range to the next available highlight,
// looping back to the first one once we've reached the 7th.
highlights[i % 7].add(range);
}
#### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::highlight` | 105 | 105 | 140Cannot yet be used with `text-decoration` and `text-shadow`. | 91 | 17.2The style is ignored when combined with `user-select: none`. See bug 278455. | 105 | 140Cannot yet be used with `text-decoration` and `text-shadow`. | 72 | 17.2The style is ignored when combined with `user-select: none`. See bug 278455. | 20.0 | 105
## See also
* CSS custom highlight API
* CSS pseudo-elements module
# ::marker
Limited availability
This feature is not Baseline because it does not work in some of the most
widely-used browsers.
* Learn more
* See full compatibility
* Report feedback
The `::marker` CSS pseudo-element selects the marker box of a list item, which
typically contains a bullet or number. It works on any element or pseudo-
element set to `display: list-item`, such as the `` and ``
elements.
## Try it
li::marker {
content: "✝ ";
font-size: 1.2em;
}
Group known as Mercury Seven:
Malcolm Scott Carpenter
Leroy Gordon (Gordo) Cooper Jr.
John Herschel Glenn Jr.
Virgil Ivan (Gus) Grissom
Walter Marty (Wally) Schirra Jr.
Alan Bartlett Shepard Jr.
Donald Kent (Deke) Slayton
## Allowable properties
The `::marker` pseudo-element supports a limited number of CSS properties,
including:
* All font properties
* The `white-space` property
* `color`
* `text-combine-upright`, `unicode-bidi`, and `direction` properties
* The `content` property
* All animation and transition properties
**Note:** The specification states that additional CSS properties may be
supported in the future.
## Syntax
::marker {
/* ... */
}
## Examples
### HTML
### CSS
ul li::marker {
color: red;
font-size: 1.5em;
}
### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::marker` | 86 | 86 | 68 | 72 | 11.1Safari support is limited to `color` and `font-size`. | 86 | 68 | 61 | 11.3Safari on iOS support is limited to `color` and `font-size`. | 14.0 | 86
`animation_and_transition_support` | 86 | 86 | 80 | 72 | No | 86 | 80 | 61 | No | 14.0 | 86
## See also
* HTML elements that have marker boxes by default: ``, ``, ``
* CSS generated content module
* CSS lists and counters module
* CSS counter styles module
# ::part()
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since July 2020.
* Learn more
* See full compatibility
* Report feedback
The `::part` CSS pseudo-element represents any element within a shadow tree
that has a matching `part` attribute.
custom-element::part(foo) {
/* Styles to apply to the `foo` part */
}
## Description
The global `part` attribute makes a shadow tree element visible to its parent
DOM. The part names declared using the `part` attribute are used as the
parameter of the `::part()` pseudo-element. In this way, you can apply CSS
styles to elements in the shadow tree from outside of it.
Part names are similar to CSS classes: multiple elements can have the same
part name, and a single element can have multiple part names. All part names
used in `::part()` pseudo-element must be present in the `part` value declared
on the shadow tree element but the order of the part names doesn't matter,
i.e., the selectors `::part(tab active)` and `::part(active tab)` are the
same.
The `::part()` pseudo-element is only visible to the parent DOM. This means
that when a shadow tree is nested, the parts are not visible to any ancestors
other than the direct parent. The `exportparts` attribute solves this
limitation by explicitly exporting already defined `part` names, making them
globally stylable.
Pseudo-classes (such as `::part(label):hover`) can be appended to the
`::part()` selector, but structural pseudo-classes that match based on tree
information, such as `:empty` and `:last-child`, cannot be appended.
Additional pseudo-elements, such as `::before`, can be appended to the
`::part()` selector, but additional `::part()` element can't be appended. For
example, `::part(confirm-button)::part(active)` never matches anything, i.e,
it is not the same as `::part(confirm-button active)`. This is because doing
so would expose more structural information than is intended.
## Syntax
::part(+) {
/* ... */
}
## Examples
### HTML
Tab A
Tab B
Tab C
### CSS
tabbed-custom-element::part(tab) {
color: blue;
border-bottom: transparent solid 4px;
}
tabbed-custom-element::part(tab):hover {
background-color: black;
color: white;
}
tabbed-custom-element::part(tab active) {
border-color: blue !important;
}
### JavaScript
const template = document.querySelector("#tabbed-custom-element");
globalThis.customElements.define(
template.id,
class extends HTMLElement {
constructor() {
super().attachShadow({ mode: "open" }).append(template.content);
}
},
);
### Result
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::part` | 73 | 79 | 72 | 60 | 13.1 | 73 | 79 | 52 | 13.4 | 11.0 | 73
## See also
* `part` attribute
* `:state()` pseudo-class function
* `exportparts` attribute
* CSS shadow parts module
# ::picker-icon
Limited availability
This feature is not Baseline because it does not work in some of the most
widely-used browsers.
* Learn more
* See full compatibility
* Report feedback
**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in
production.
The `::picker-icon` CSS pseudo-element targets the picker icon inside form
controls that have an icon associated with them. In the case of a customizable
select element, it selects the arrow icon shown on the `` element that
points down when it is closed.
## Syntax
::picker-icon {
/* ... */
}
## Description
The `::picker-icon` pseudo-element targets the picker icon of form controls,
that is, the icon shown on the control button. It is only available to target
when the originating element has a picker and has base appearance set on it
via the `appearance` property `base-select` value. Its generated box appears
after any boxes generated by the `::after` pseudo-element, with the icon
specified in default browser stylesheet; you can customize it using the
`content` property.
The `::picker-icon` selector can be used to select the down-facing arrow on
the inline-end side of a customizable select element. This is useful for
example if you want to customize the color or size of the icon, use a
different icon (using `content` or SVG), or animate it when the picker is
opened and closed.
Selecting customizable `` picker icons is the only current use case
for `::picker-icon`, but more may be added in the future.
**Note:** The `::picker-icon` pseudo-element is not included in the
accessibility tree, so any generated `content` set on it will not be announced
by assistive technologies. You should still make sure that any new icon you
set visually makes sense for its intended purpose.
## Examples
### Animating the picker icon
To opt-in to customizable select functionality, the `` element and its
picker both need to have an `appearance` value of `base-select` set on them:
select,
::picker(select) {
appearance: base-select;
}
You could then, for example, target the `::picker-icon` and give it a custom
`color` and a `transition` so that changes to its `rotate` property are
smoothly animated:
select::picker-icon {
color: #999;
transition: 0.4s rotate;
}
In the next rule, `::picker-icon` is combined with the `:open` pseudo-class —
which targets the icon only when the picker is open — transitioning it to a
`rotate` value of `180deg` when the `` is opened.
select:open::picker-icon {
rotate: 180deg;
}
See Styling the picker icon for a full example that uses this code, along with
a live example rendering.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::picker-icon` | 133 | 133 | No | 118 | No | 133 | No | 88 | No | No | 133
## See also
* ``, ``, ` `, ``, ``, ``
* `appearance`
* `::picker(select)`, `::checkmark`
* `:open`, `:checked`
* Customizable select elements
# ::picker()
Limited availability
This feature is not Baseline because it does not work in some of the most
widely-used browsers.
* Learn more
* See full compatibility
* Report feedback
**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in
production.
The `::picker()` CSS pseudo-element targets the picker part of an element, for
example the drop-down picker of a customizable select element.
## Syntax
::picker() {
/* ... */
}
### Parameters
``
A string representing the element whose picker you want to target. The
following values are available:
`select`
The drop-down picker of customizable select elements.
## Description
The `::picker()` pseudo-element targets the picker part of a form control,
that is, the pop-up part that appears to allow you to make a selection when
you press the control button. It is only available to target when the
originating element has a picker and has base appearance set on it via the
`appearance` property `base-select` value.
The `::picker(select)` selector targets all descendants of customizable
`` element except for the first `` child; these descendants
are grouped together by the browser and rendered as the picker. The first
`` child represents the control button that opens the picker when
pressed.
This allows you to target all of the picker contents as a single entity, for
example if you want to customize its border, animate it when it appears and
disappears, or position it somewhere different to the default position. Our
customizable select elements guide shows many examples of `::picker(select)`
usage.
### Picker popover behavior
The `` element and the picker have an implicit invoker/popover
relationship assigned to them automatically, as specified by the Popover API.
See Using the Popover API for more details of popover behavior, and see
Animating the picker drop-down using popover states for a typical use case
allowed by the implicit popover association.
### Picker anchor positioning
A further side-effect of the implicit invoker/popover relationship mentioned
above is that the `` element and the picker also have an implicit
anchor reference, meaning that the picker is automatically associated with the
select via CSS anchor positioning. This has several advantages, most notably:
* The browser default styles position the picker relative to the button (the anchor) and you can customize this position as explained in Positioning elements relative to their anchor. For reference, the related default styles are as follows:
inset: auto;
margin: 0;
min-inline-size: anchor-size(self-inline);
min-block-size: 1lh;
/* Go to the edge of the viewport, and add scrollbars if needed. */
max-block-size: stretch;
overflow: auto;
/* Below and span-right, by default. */
position-area: block-end span-inline-end;
* The browser default styles also define some position-try fallbacks that reposition the picker if it is in danger of overflowing the viewport. Position-try fallbacks are explained in Handling overflow: try fallbacks and conditional hiding. For reference, the related default fallback styles are as follows:
position-try-order: most-block-size;
position-try-fallbacks:
/* First try above and span-right, */
/* then below but span-left, */
/* then above and span-left. */
block-start span-inline-end,
block-end span-inline-start,
block-start span-inline-start;
## Examples
### Basic custom select usage
To opt-in to the custom select functionality and minimal browser base styles
(and remove the OS-provided styling), the `` element and its picker
both need to have an `appearance` value of `base-select` set on them:
select,
::picker(select) {
appearance: base-select;
}
You could then, for example, remove the picker's default black `border`:
::picker(select) {
border: none;
}
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`::picker` | 134 | 134 | No | 119 | No | 134 | No | 88 | No | No | 134
## See also
* ``, ``, ` `, ``, ``, ``
* `appearance`
* `::picker-icon`, `::checkmark`
* `:open`, `:checked`
* Customizable select elements
# ::placeholder
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since January 2020.
* Learn more
* See full compatibility
* Report feedback
The `::placeholder` CSS pseudo-element represents the placeholder text in an
` ` or `
### Result
The `` element that has been assigned content matched the `:has-slotted`
pseudo-class and has the `color` value of `rebeccapurple` applied.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`:has-slotted` | 134 | 134 | 136 | 119 | No | 134 | 136 | 88 | No | No | 134
## See also
* HTML `` element
* HTML `` element
* `::slotted`
# :has()
Baseline 2023
Newly available
Since December 2023, this feature works across the latest devices and browser
versions. This feature might not work in older devices or browsers.
* Learn more
* See full compatibility
* Report feedback
The functional `:has()` CSS pseudo-class represents an element if any of the
relative selectors that are passed as an argument match at least one element
when anchored against this element. This pseudo-class presents a way of
selecting a parent element or a previous sibling element with respect to a
reference element by taking a relative selector list as an argument.
/* Selects an h1 heading with a
paragraph element that immediately follows
the h1 and applies the style to h1 */
h1:has(+ p) {
margin-bottom: 0;
}
The `:has()` pseudo-class takes on the specificity of the most specific
selector in its arguments the same way as `:is()` and `:not()` do.
## Syntax
:has() {
/* ... */
}
If the `:has()` pseudo-class itself is not supported in a browser, the entire
selector block will fail unless `:has()` is in a forgiving selector list, such
as in `:is()` and `:where()`.
The `:has()` pseudo-class cannot be nested within another `:has()`.
Pseudo-elements are also not valid selectors within `:has()` and pseudo-
elements are not valid anchors for `:has()`. This is because many pseudo-
elements exist conditionally based on the styling of their ancestors and
allowing these to be queried by `:has()` can introduce cyclic querying.
## Examples
### With the sibling combinator
The `:has()` style declaration in the following example adjusts the spacing
after `` headings if they are immediately followed by an `` heading.
#### HTML
Morning Times
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
Morning Times
Delivering you news every morning
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
#### CSS
h1,
h2 {
margin: 0 0 1rem 0;
}
h1:has(+ h2) {
margin: 0 0 0.25rem 0;
}
#### Result
This example shows two similar texts side-by-side for comparison – the left
one with an `H1` heading followed by a paragraph and the right one with an
`H1` heading followed by an `H2` heading and then a paragraph. In the example
on the right, `:has()` helps to select the `H1` element that is immediately
followed by an `H2` element (indicated by the next-sibling combinator `+`) and
the CSS rule reduces the spacing after such an `H1` element. Without the
`:has()` pseudo-class, you cannot use CSS selectors to select a preceding
sibling of a different type or a parent element.
### With the :is() pseudo-class
This example builds on the previous example to show how to select multiple
elements with `:has()`.
#### HTML
Morning Times
Delivering you news every morning
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
Morning Times
Delivering you news every morning
8:00 am
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
#### CSS
h1,
h2,
h3 {
margin: 0 0 1rem 0;
}
:is(h1, h2, h3):has(+ :is(h2, h3, h4)) {
margin: 0 0 0.25rem 0;
}
#### Result
Here, the first `:is()` pseudo-class is used to select any of the heading
elements in the list. The second `:is()` pseudo-class is used to pass a list
of next-sibling selectors as an argument to `:has()`. The `:has()` pseudo-
class helps to select any `H1`, `H2`, or `H3` element that is immediately
followed by (indicated by `+`) an `H2`, `H3`, or `H4` element and the CSS rule
reduces the spacing after such `H1`, `H2`, or `H3` elements.
This selector could have also been written as:
:is(h1, h2, h3):has(+ h2, + h3, + h4) {
margin: 0 0 0.25rem 0;
}
### Logical operations
The `:has()` relational selector can be used to check if one of the multiple
features is true or if all the features are true.
By using comma-separated values inside the `:has()` relational selector, you
are checking to see if any of the parameters exist. `x:has(a, b)` will style
`x` if descendant `a` OR `b` exists.
By chaining together multiple `:has()` relational selectors together, you are
checking to see if all of the parameters exist. `x:has(a):has(b)` will style
`x` if descendant `a` AND `b` exist.
body:has(video, audio) {
/* styles to apply if the content contains audio OR video */
}
body:has(video):has(audio) {
/* styles to apply if the content contains both audio AND video */
}
## Analogy between :has() and regular expressions
Interestingly, we can relate some CSS `:has()` constructs with the lookahead
assertion in regular expressions because they both allow you to select
elements (or strings in regular expressions) based on a condition without
actually selecting the condition matching the element (or string) itself.
### Positive lookahead (?=pattern)
In the regular expression `abc(?=xyz)`, the string `abc` is matched only if it
is immediately followed by the string `xyz`. As it is a lookahead operation,
the `xyz` is not included in the match.
The analogous construct in CSS would be `.abc:has(+ .xyz)`: it selects the
element `.abc` only if there is a next sibling `.xyz`. The part `:has(+ .xyz)`
acts as a lookahead operation because the element `.abc` is selected and not
the element `.xyz`.
### Negative lookahead (?!pattern)
Similarly, for the negative lookahead case, in the regular expression
`abc(?!xyz)`, the string `abc` is matched only if it is _not_ followed by
`xyz`. The analogous CSS construct `.abc:has(+ :not(.xyz))` doesn't select the
element `.abc` if the next element is `.xyz`.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`:has` | 105 | 105 | 121 | 91 | 15.4 | 105 | 121 | 72 | 15.4 | 20.0 | 105
## See also
* `:is()`, `:where()`, `:not()`
* CSS selectors and combinators
* CSS selector structure
* Selector list
* CSS selector module
* Locating DOM elements using selectors
# :host-context()
Limited availability
This feature is not Baseline because it does not work in some of the most
widely-used browsers.
* Learn more
* See full compatibility
* Report feedback
The `:host-context()` CSS pseudo-class allows you to style elements within a
shadow DOM differently based on the selector of the shadow host (the element
that has the shadow root) and its DOM ancestors.
Normally, elements within a shadow DOM are isolated from the DOM outside of
it. The `:host-context()` allows you to "peek outside" of this Shadow DOM and
check if any of the element's ancestor elements match a certain CSS selector.
For example, applying a different text color to elements within a shadow root
when a `.dark-theme` class is applied to ``.
Think of it like this: Imagine you have a `` custom element, that
has a `` living inside. Here, the `` is the Shadow DOM
host and the `` element is within the Shadow DOM. The `:host-
context()` lets the `` change its appearance based on the
``'s environment. If the `` is in a sunny location
(has a "sunny-theme" class), the `` turns yellow. If the
`` is in a shady spot (a "shady-theme" class applied instead), the
`` turns blue.
This selector pierces through all shadow boundaries. It will look for the
sunny or shady theme applied directly to the `` or on any of the
host's ancestors and ancestor DOMs all the way up until it reaches the
document root.
To limit the selector to only the `` host directly or limit the
selection to host's DOM, use the `:host` or `:host()` pseudo-class instead.
**Note:** This has no effect when used outside a shadow DOM.
The specificity of `:host-context()` is that of a pseudo-class, plus the
specificity of the selector passed as the function's argument.
## Try it
/* Following CSS is being applied inside the shadow DOM. */
:host-context(.container) {
border: 5px dashed green;
}
:host-context(h1) {
color: red;
}
const shadowDom = init();
// add a element in the shadow DOM
const span = document.createElement("span");
span.textContent = "Inside shadow DOM";
shadowDom.appendChild(span);
// attach shadow DOM to the #shadow-dom-host element
function init() {
const host = document.getElementById("shadow-dom-host");
const shadowDom = host.attachShadow({ mode: "open" });
const cssTab = document.querySelector("#css-output");
const shadowStyle = document.createElement("style");
shadowStyle.textContent = cssTab.textContent;
shadowDom.appendChild(shadowStyle);
cssTab.addEventListener("change", () => {
shadowStyle.textContent = cssTab.textContent;
});
return shadowDom;
}
/* Selects a shadow root host, only if it is
a descendant of the selector argument given */
:host-context(h1) {
font-weight: bold;
}
/* Changes paragraph text color from black to white when
a .dark-theme class is applied to the document body */
p {
color: #000;
}
:host-context(body.dark-theme) p {
color: #fff;
}
## Syntax
:host-context() {
/* ... */
}
## Examples
### Selectively styling shadow hosts
The following snippets are taken from our host-selectors example (see it live
also).
In this example we have a basic custom element — `` — that you
can wrap around text:
Host selectors example
Inside the element's constructor, we create `style` and `span` elements, fill
the `span` with the content of the custom element, and fill the `style`
element with some CSS rules:
const style = document.createElement("style");
const span = document.createElement("span");
span.textContent = this.textContent;
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(style);
shadowRoot.appendChild(span);
style.textContent =
"span:hover { text-decoration: underline; }" +
":host-context(h1) { font-style: italic; }" +
':host-context(h1):after { content: " - no links in headers!" }' +
":host(.footer) { color : red; }" +
":host { background: rgb(0 0 0 / 10%); padding: 2px 5px; }";
The `:host-context(h1) { font-style: italic; }` and `:host-context(h1):after {
content: " - no links in headers!" }` rules style the instance of the
`` element (the shadow host in this instance) inside the ``.
We've used it to make it clear that the custom element shouldn't appear inside
the `` in our design.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`:host-context` | 54 | 79 | No | 41 | No | 54 | No | 41 | No | 6.0 | 54
## See also
* Web components
* CSS `:host` pseudo-class
* CSS `:host()` pseudo-class
* CSS `:state()` pseudo-class
* CSS `::slotted` pseudo-element
* HTML `` element
* CSS scoping module
# :host
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since January 2020.
* Learn more
* See full compatibility
* Report feedback
The `:host` CSS pseudo-class selects the shadow host of the shadow DOM
containing the CSS it is used inside — in other words, this allows you to
select a custom element from inside its shadow DOM.
**Note:** This has no effect when used outside a shadow DOM.
## Try it
/* This CSS is being applied inside the shadow DOM. */
:host {
background-color: aqua;
}
const shadowDom = init();
// add a element in the shadow DOM
const span = document.createElement("span");
span.textContent = "Inside shadow DOM";
shadowDom.appendChild(span);
// attach shadow DOM to the #shadow-dom-host element
function init() {
const host = document.getElementById("shadow-dom-host");
const shadowDom = host.attachShadow({ mode: "open" });
const cssTab = document.querySelector("#css-output");
const shadowStyle = document.createElement("style");
shadowStyle.textContent = cssTab.textContent;
shadowDom.appendChild(shadowStyle);
cssTab.addEventListener("change", () => {
shadowStyle.textContent = cssTab.textContent;
});
return shadowDom;
}
/* Selects a shadow root host */
:host {
font-weight: bold;
}
## Syntax
:host {
/* ... */
}
## Examples
### Styling the shadow host
The following snippets are taken from our host-selectors example (see it live
also).
In this example we have a basic custom element — `` — that you
can wrap around text:
Host selectors example
Inside the element's constructor, we create `style` and `span` elements, fill
the `span` with the content of the custom element, and fill the `style`
element with some CSS rules:
const style = document.createElement("style");
const span = document.createElement("span");
span.textContent = this.textContent;
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(style);
shadowRoot.appendChild(span);
style.textContent =
"span:hover { text-decoration: underline; }" +
":host-context(h1) { font-style: italic; }" +
':host-context(h1):after { content: " - no links in headers!" }' +
":host-context(article, aside) { color: gray; }" +
":host(.footer) { color : red; }" +
":host { background: rgb(0 0 0 / 10%); padding: 2px 5px; }";
The `:host { background: rgb(0 0 0 / 10%); padding: 2px 5px; }` rule styles
all instances of the `` element (the shadow host in this
instance) in the document.
## Specifications
## Browser compatibility
| Desktop | Mobile
---|---|---
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android
`:host` | 54 | 79 | 63 | 41 | 10 | 54 | 63 | 41 | 10 | 6.0 | 54
## See also
* Web components
* `:host()`
* `:host-context()`
* `::slotted`
* `:state()`
* CSS scoping module
# :host()
Baseline Widely available
This feature is well established and works across many devices and browser
versions. It’s been available across browsers since January 2020.
* Learn more
* See full compatibility
* Report feedback
The `:host()` CSS pseudo-class function selects the shadow host of the shadow
DOM containing the CSS it is used inside (so you can select a custom element
from inside its shadow DOM) — but only if the selector given as the function's
parameter matches the shadow host. `:host()` has no effect when used outside a
shadow DOM.
The most obvious use of this is to put a class name only on certain custom
element instances, and then include the relevant class selector as the
function argument. You can't use this with a descendant selector expression to
select only instances of the custom element that are inside a particular
ancestor. That's the job of `:host-context()`.
**Note:** While other functional pseudo-classes such as `:is()` and `:not()`
accept a list of selectors as their parameters, `:host()` takes a single
compound selector as its parameter. In addition, while `:is()` and `:not()`
only take into account the specificity of their argument, the specificity of
`:host()` is both the specificity of the pseudo-class **and** the specificity
of its argument.
## Try it
/* Following CSS is being applied inside the shadow DOM. */
:host(h1) {
color: red;
}
:host(#shadow-dom-host) {
border: 2px dashed blue;
}
const shadowDom = init();
// add a element in the shadow DOM
const span = document.createElement("span");
span.textContent = "Inside shadow DOM";
shadowDom.appendChild(span);
// attach shadow DOM to the #shadow-dom-host element
function init() {
const host = document.getElementById("shadow-dom-host");
const shadowDom = host.attachShadow({ mode: "open" });
const cssTab = document.querySelector("#css-output");
const shadowStyle = document.createElement("style");
shadowStyle.textContent = cssTab.textContent;
shadowDom.appendChild(shadowStyle);
cssTab.addEventListener("change", () => {
shadowStyle.textContent = cssTab.textContent;
});
return shadowDom;
}
/* Selects a shadow root host, only if it is
matched by the selector argument */
:host(.special-custom-element) {
font-weight: bold;
}
## Syntax
:host() {
/* ... */
}
## Examples
### Selectively styling shadow hosts
The following snippets are taken from our host-selectors example (see it live
also).
In this example we have a custom element — `` — that you can
wrap around text:
Host selectors example
Inside the element's constructor, we create `style` and `span` elements, fill
the `span` with the content of the custom element, and fill the `style`
element with some CSS rules:
const style = document.createElement("style");
const span = document.createElement("span");
span.textContent = this.textContent;
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(style);
shadowRoot.appendChild(span);
style.textContent =
"span:hover { text-decoration: underline; }" +
":host-context(h1) { font-style: italic; }" +
':host-context(h1):after { content: " - no links in headers!" }' +
":host-context(article, aside) { color: gray; }" +
":host(.footer) { color : red; }" +
":host { background: rgb(0 0 0 / 10%); padding: 2px 5px; }";
The `:host(.footer) { color : red; }` rule styles all instances of the
`` element (the shadow host in this instance) in the document
that have the `footer` class set on them — we've used it to give instances of
the element inside the `