::scroll-marker-group

Limited availability

This feature is not Baseline because it does not work in some of the most widely-used browsers.

The ::scroll-marker-group CSS pseudo-element is a container generated inside a scroll container, which contains any ::scroll-marker pseudo-elements generated on the descendants of the scroll container.

Syntax

css
::scroll-marker-group {
  /* ... */
}

Description

A scroll container's ::scroll-marker-group pseudo-element automatically contains any ::scroll-marker pseudo-elements generated on its descendants. This allows them to be positioned and laid out as a group, and is typically used when creating a CSS carousel, to create a scroll position indicator. The individual scroll markers can also be used to navigate to their associated content items.

The scroll-marker-group property must be set to a non-none value on the scroll container for a ::scroll-marker-group pseudo-element to be generated; the chosen value determines where the scroll marker group appears in the carousel's tab order and layout box order (but not DOM structure) — before puts it at the start, while after puts it at the end.

It is a best practice to match the visual rendering position of the scroll marker group with the tab order. When placing the group at the start of the content, put it at the beginning of the tab order using before. When placing the group at the end of the content, put it at the end of the tab order using after.

Accessibility-wise, the scroll marker group and contained scroll markers are rendered with tablist/tab semantics. When you Tab to the group, it behaves like a single item (that is, another press of the Tab key will move past the group to the next item), and you can move between the different scroll markers using the left and right (or up and down) cursor keys.

Examples

Note: You can find a full example walkthough featuring the below code snippets in our Creating CSS carousels guide.

Generating and positioning a scroll marker group

In the below snippet, a scrolling <ul> element's scroll-marker-group property is set to after, so the ::scroll-marker-group pseudo-element is generated after the list's DOM content:

css
ul {
  scroll-marker-group: after;
}

Next, the list's ::scroll-marker-group pseudo-element is positioned relative to the container using CSS anchor positioning. First of all, a reference anchor-name is set on the list. Next, each scroll button has its position set to absolute, and its position-anchor property set to the same reference name defined on the list, to associate the two together. To position the group, we set a value on its top property that uses an anchor() function to position its top edge relative to the container's bottom edge, and horizontally center it on the container using a justify-self value of anchor-center.

The group is laid out using flexbox, with a justify-content value of of center and a gap of 20px so that its children (the ::scroll-marker pseudo-elements) are centered inside the ::scroll-marker-group with a gap between each one.

css
ul {
  anchor-name: --myCarousel;
}

/* ... */

ul::scroll-marker-group {
  position: absolute;
  position-anchor: --myCarousel;
  top: calc(anchor(bottom) - 70px);
  justify-self: anchor-center;

  display: flex;
  justify-content: center;
  gap: 20px;
}

Styling the scroll markers

The ::scroll-marker pseudo-elements representing the scroll markers are generated on the <li> chidren of the scrolling list, but are automatically placed inside the ::scroll-marker-group pseudo-element.

The look of each one is handled by setting width, height, background-color, border, and border-radius, but we also need to set a non-none value for the content property so they are actually generated. We also set an interactive value of auto so that all the markers will be interactive (by default, they are set to inert, and only the one corresponding to the currently visible "page" is interactive).

css
li::scroll-marker {
  width: 16px;
  height: 16px;
  background-color: transparent;
  border: 2px solid black;
  border-radius: 50%;
  content: "";
  interactivity: auto;
}

Next, the :target-current pseudo-class is used to select whichever scroll marker corresponds to the currently visible "page", highlighting how far the user has scrolled through the content. In this case, we set the background-color to black so it is styled as a filled-in circle.

css
li::scroll-marker:target-current {
  background-color: black;
}

Specifications

Specification
CSS Overflow Module Level 5
# scroll-marker-group-pseudo

Browser compatibility

See also