CSS ::scroll-marker Pseudo-Element

The ::scroll-marker pseudo-element creates navigation markers for individual items inside a scroll container. These markers can function like pagination dots, allowing users to navigate directly to specific content without JavaScript.

Syntax

selector::scroll-marker {
  content: "";
  property: value;
}

The selector identifies an element associated with a scroll container.

The ::scroll-marker pseudo-element creates a navigation marker for that element.

The content property generates the marker and determines its content.

For example:

.slide::scroll-marker {
  content: "";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background-color: #ccc;
}

This rule creates a circular navigation marker for each element with the slide class.

The markers must be collected into a scroll marker group to function as navigation controls.

The ::scroll-marker pseudo-element does not accept arguments.

Unlike ::scroll-button(), it does not use parentheses or directional keywords.

How It Works

The ::scroll-marker pseudo-element represents a navigation control associated with a particular element in a scroll container.

When a user activates a marker, the browser scrolls the associated content into view.

Scroll markers are commonly used in carousels, horizontally scrolling card collections, and other interfaces with multiple scroll targets.

Creating a scroll marker navigation system involves four steps:

  1. Create a scroll container containing multiple items.
  2. Set the scroll-marker-group property on the scroll container.
  3. Use ::scroll-marker to generate markers for individual items.
  4. Style the marker group and individual markers.

For example:

.carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-marker-group: after;
}
.carousel-item {
  flex: 0 0 100%;
  scroll-snap-align: start;
}
.carousel-item::scroll-marker {
  content: "";
}

The browser generates a marker for each carousel item and places the markers in the associated scroll marker group.

The markers provide direct navigation to their corresponding items.

CSS scroll snapping helps align the items when the scroll position changes.

JavaScript is not required for the basic navigation behavior in supporting browsers.

Creating Scroll Markers

Scroll markers are generated using the content property.

For example:

.carousel-item::scroll-marker {
  content: "";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background-color: #ccc;
}

The empty string generates a marker without visible text.

The width, height, border radius, and background color create a circular navigation dot.

Markers can also display text or symbols:

.carousel-item::scroll-marker {
  content: "\2022";
  color: #666;
  font-size: 24px;
}

The \2022 CSS escape represents a bullet character.

For numbered markers, CSS counters can be used:

.carousel {
  counter-reset: slide;
}
.carousel-item::scroll-marker {
  counter-increment: slide;
  content: counter(slide);
}

This creates numbered navigation markers associated with the carousel items.

Markers should have a clear visual appearance and a sufficiently large interactive area.

Setting content: none prevents the marker from being generated.

The ::scroll-marker-group Pseudo-Element

The ::scroll-marker-group pseudo-element provides a container for scroll markers.

The scroll container must use the scroll-marker-group property to generate this group.

For example:

.carousel {
  scroll-marker-group: after;
}
.carousel::scroll-marker-group {
  display: flex;
  justify-content: center;
  gap: 10px;
}

The scroll-marker-group: after declaration generates a marker group after the scroll container.

The ::scroll-marker-group selector styles the generated group.

The display: flex declaration arranges the markers in a row.

The justify-content: center declaration centers the markers.

The gap property adds space between individual markers.

The scroll-marker-group property accepts the following values:

Value Description
none Does not generate a scroll marker group.
before Generates the group before the scroll container.
after Generates the group after the scroll container.

The marker group is associated with the scroll container, while individual markers are generated from its scroll targets.

For additional information, see the CSS ::scroll-marker-group Pseudo-Element reference.

Styling Scroll Markers

Scroll markers can be styled using CSS properties commonly used for interactive controls.

For example:

.carousel-item::scroll-marker {
  content: "";
  width: 14px;
  height: 14px;
  border: 2px solid #0066cc;
  border-radius: 50%;
  background-color: #fff;
  cursor: pointer;
}
.carousel-item::scroll-marker:hover {
  background-color: #cce5ff;
}

This example creates circular markers with blue borders and white backgrounds.

The :hover pseudo-class changes the background color when the pointer moves over a marker.

Keyboard focus can be styled using :focus-visible:

.carousel-item::scroll-marker:focus-visible {
  outline: 2px solid #0066cc;
  outline-offset: 3px;
}

A visible focus indicator helps keyboard users identify the currently focused marker.

Markers can also be styled with different sizes, colors, borders, and backgrounds to match the design of the page.

Styling the Active Marker

The :target-current pseudo-class identifies the scroll marker associated with the currently active scroll target.

For example:

.carousel-item::scroll-marker {
  content: "";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background-color: #ccc;
}
.carousel-item::scroll-marker:target-current {
  background-color: #0066cc;
}

Inactive markers appear gray, while the active marker appears blue.

The browser updates the active marker as the user navigates through the scroll container.

This behavior does not require JavaScript.

The :target-current pseudo-class is different from :target.

The :target pseudo-class identifies an element matching the URL fragment identifier.

The :target-current pseudo-class is designed for the currently active target within scroll marker navigation.

Use ::scroll-marker:target-current when styling the active marker in a CSS carousel.

Example

The following example creates a horizontal carousel with circular navigation markers below the content.

HTML:

<div class="scroll-marker-demo">
  <div class="scroll-marker-slide">HTML</div>
  <div class="scroll-marker-slide">CSS</div>
  <div class="scroll-marker-slide">JavaScript</div>
  <div class="scroll-marker-slide">Flexbox</div>
</div>

CSS:

.scroll-marker-demo {
  display: flex;
  width: 300px;
  max-width: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-marker-group: after;
  anchor-name: --marker-demo;
}
.scroll-marker-slide {
  flex: 0 0 100%;
  box-sizing: border-box;
  padding: 35px 15px;
  background-color: #eef5ff;
  border: 1px solid #ccc;
  text-align: center;
  font-weight: bold;
  scroll-snap-align: start;
}
.scroll-marker-demo::scroll-marker-group {
  position: absolute;
  position-anchor: --marker-demo;
  position-area: bottom;
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 15px;
}
.scroll-marker-slide::scroll-marker {
  content: "";
  display: block;
  width: 14px;
  height: 14px;
  border: 2px solid #0066cc;
  border-radius: 50%;
  background-color: #fff;
  cursor: pointer;
}
.scroll-marker-slide::scroll-marker:target-current {
  background-color: #0066cc;
}
.scroll-marker-slide::scroll-marker:focus-visible {
  outline: 2px solid #0066cc;
  outline-offset: 3px;
}
Browser Result
HTML
CSS
JavaScript
Flexbox

In supporting browsers, four navigation markers appear below the carousel.

Click a marker to scroll directly to its corresponding item.

The active marker changes to blue as the selected content becomes current.

CSS scroll snapping aligns each item with the beginning of the scroll container.

In browsers without scroll marker support, the content remains horizontally scrollable.

Scroll Markers vs. Scroll Buttons

The ::scroll-marker and ::scroll-button() pseudo-elements both provide navigation controls for scroll containers.

However, they work differently.

Feature ::scroll-marker ::scroll-button()
Purpose Navigate to an associated scroll target. Scroll in a specified direction.
Arguments None. Requires a direction.
Typical appearance Pagination dots or numbered markers. Directional arrows.
Navigation Directly selects associated content. Moves the scroll position.
Marker group Requires a scroll marker group. Does not require a scroll marker group.

For example:

.carousel-item::scroll-marker {
  content: "";
}
.carousel::scroll-button(right) {
  content: "\2192";
}

The first rule creates a navigation marker for each carousel item.

The second rule creates a directional button that scrolls the carousel to the right.

Both types of controls can be combined in the same carousel.

Supported CSS Properties

The ::scroll-marker pseudo-element can be styled using CSS properties that control generated content and visual appearance.

Property Purpose
content Generates the marker and defines its content.
background-color Changes the marker background.
color Changes the marker text or symbol color.
border Defines the marker border.
border-radius Rounds the marker corners.
width Controls the marker width.
height Controls the marker height.
font-size Changes the size of text-based markers.
opacity Controls marker transparency.
cursor Changes the pointer appearance.
outline Provides a visible keyboard focus indicator.

For example:

.carousel-item::scroll-marker {
  content: "";
  width: 16px;
  height: 16px;
  border: 2px solid #0066cc;
  border-radius: 50%;
  background-color: #fff;
}
.carousel-item::scroll-marker:target-current {
  background-color: #0066cc;
}

This creates outlined circular markers with a filled appearance for the active marker.

Limitations

The ::scroll-marker pseudo-element has several limitations.

  • It is a newer CSS feature with limited browser support.
  • It requires an associated scroll marker group.
  • It needs generated content to create a visible marker.
  • Its navigation behavior depends on the associated scroll target.
  • It does not create directional scrolling buttons.
  • Complex carousel layouts may require additional positioning rules.
  • Unsupported browsers ignore the pseudo-element.

For broader compatibility, keep the scroll container usable without generated navigation markers.

Do not rely on scroll markers as the only way to access important content.

Accessibility Considerations

Scroll markers provide interactive navigation and should remain accessible to keyboard and assistive technology users.

Follow these accessibility practices:

  • Ensure each marker has a meaningful accessible name.
  • Provide a visible keyboard focus indicator.
  • Use sufficient contrast between active and inactive markers.
  • Make markers large enough to activate comfortably.
  • Do not rely on color alone to communicate the current selection.
  • Keep the scrollable content accessible without the markers.
  • Test keyboard navigation and assistive technology behavior.
  • Respect reduced-motion preferences when using smooth scrolling.

Supporting browsers provide built-in navigation semantics for scroll marker groups and their markers.

When a marker uses only a visual symbol, its accessible name should still identify the associated content.

For example, the content property can include alternative text:

.carousel-item:first-child::scroll-marker {
  content: "\2022" / "HTML slide";
}

This provides a text alternative for the marker's visible bullet symbol.

Always test the resulting accessible names in the browsers you support.

Browser Support

The ::scroll-marker pseudo-element has limited browser availability.

It is supported in newer Chromium-based browsers, including recent versions of Chrome and Edge.

Availability in Firefox, Safari, and other browsers may differ.

Unsupported browsers ignore the pseudo-element and its associated scroll marker styling.

Use a feature query to conditionally apply scroll marker styles:

@supports selector(::scroll-marker) {
  .carousel {
    scroll-marker-group: after;
  }
  .carousel-item::scroll-marker {
    content: "";
  }
}

This approach applies the marker-related CSS only when the browser recognizes the selector.

The underlying scroll container should remain usable without the generated controls.

For current compatibility information, visit Can I Use? and search for ::scroll-marker or CSS carousel features.

Specifications

The ::scroll-marker pseudo-element is defined in the CSS Overflow Module Level 5 .

The specification describes scroll marker navigation, scroll marker groups, and their relationship to scroll containers.

Related features include ::scroll-marker-group, the scroll-marker-group property, and the :target-current pseudo-class.