Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.
Experimental: Check browser support before using this in production.
The scroll-marker-group
CSS property determines if the ::scroll-marker-group
pseudo-element is generated within the scroll container that the property is set on, and where. When creating scroll markers, you’re required to set scroll-marker-group
to either before
or after
, although there are other requirements, too.
Scroll markers can be used to create CSS carousels, tabs, scroll-snapping components, and other scroll-based components. While by no means a fully-functioning component, a scroll container with overflow content would look something like this:
<ul class="scroll-container">
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
</ul>
.scroll-container {
scroll-marker-group: before;
&::scroll-marker-group {
/* ... */
}
.scroll-target::scroll-marker {
/* ... */
}
}
And then the resulting HTML (if you were to inspect it in DevTools) would look something like this:
<ul class="scroll-container">
<::scroll-marker-group>
<!-- Five scroll markers -->
<::scroll-marker>
<::scroll-marker>
<::scroll-marker>
<::scroll-marker>
<::scroll-marker>
</::scroll-marker-group>
<!-- Five scroll targets -->
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
</ul>
If you were to click on the third scroll marker, you’d be scrolled to the third scroll target in a scroll-snapping manner, all-in-all providing users with an additional way to navigate overflow content. Scroll markers are fully accessible, too. Users can navigate them using keyboards and assistive technologies, and screen readers are also able to decipher them quite easily.
Syntax
scroll-marker-group: <position>;
- Values:
none
|before
|after
- Initial:
none
- Applies to: scroll containers
- Inherited: no
- Computed value: as specified
- Animation type: discrete
Values
The <position>
can be one of the following values:
none
(default): Don’t generate::scroll-marker-group
.before
: Generate::scroll-marker-group
at the beginning of the scroll container (has the same effect as::before
).after
: Generate::scroll-marker-group
at the end of the scroll container (has the same effect as::after
).
The before
and after
values determine the tab order of the scroll markers that get generated within ::scroll-marker-group
. The before
value ensures that the scroll markers come before the scroll container’s content in the tab order, and after
ensures that they come after. They also determine the ::scroll-marker-group
’s layout box order, but this hardly matters as you’ll likely be anchor-positioning it relative to the scroll container anyway.
Basic usage
To use scroll markers, start with a scroll container with overflow content inside (e.g., a carousel where only one slide is shown at a time and the rest are “cut off”). The overflow
property must be set to anything other than visible
; otherwise the ::scroll-marker-group
pseudo-element simply won’t show up.
And, of course, you’ll need to set scroll-marker-group
to either before
or after
depending on the desired tab order.
Finally, each scroll target’s ::scroll-marker
must have a valid content
property.
If these requirements have been met, you’ll have a fully-functional scroll container with accessible scroll markers.
<ul class="scroll-container">
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
<li class="scroll-target"></li>
</ul>
.scroll-container {
overflow-x: hidden; /* Anything but visible */
scroll-marker-group: after; /* before | after */
&::scroll-marker-group {
/* ... */
}
.scroll-target::scroll-marker {
content: ""; /* Any valid value */
}
}
Example: Carousel
In the carousel example below, the ::scroll-marker-group
pseudo-element uses anchor positioning to position itself relative to the scroll container, which is probably the best way to go about it, but any method of alignment should work fine. And since the scroll markers are positioned at the bottom, the scroll-marker-group
property is set to after
, ensuring that the tab order matches this visual order.
In addition, Flexbox is used to lay out the scroll markers.
<ul class="carousel">
<li style="background:hsl(10 70% 50%)"></li>
<li style="background:hsl(30 70% 50%)"></li>
<li style="background:hsl(50 70% 50%)"></li>
<li style="background:hsl(70 70% 50%)"></li>
<li style="background:hsl(90 70% 50%)"></li>
</ul>
.carousel {
/* The width */
--carousel-width: 100vw;
width: var(--carousel-width);
/* The height is half the width */
aspect-ratio: 1 / 0.5;
/* Implies flex-direction: row */
display: flex;
li {
/* Give carousel items the same width */
width: var(--carousel-width);
/* Prevent flexbox from overwriting said width */
flex-shrink: 0;
}
/* Show only one carousel item */
overflow: hidden;
/* Turn the carousel into an anchor */
anchor-name: --carousel;
/* Enable smooth scrolling */
scroll-behavior: smooth;
/* Place after the content */
scroll-marker-group: after;
&::scroll-marker-group {
/* Space the markers apart */
display: flex;
gap: 10px;
/* Anchor it to the carousel */
position: fixed;
position-anchor: --carousel;
/* Anchor it horizontally */
justify-self: anchor-center;
/* Anchor it near the bottom */
bottom: calc(anchor(bottom) + 10px);
}
li::scroll-marker {
/* Stylized markers */
content: "";
width: 10px;
height: 10px;
border-radius: 10px;
border: 1px solid black;
}
/* The currently selected marker */
li::scroll-marker:target-current {
background: black;
}
}
Example: Tabs
In the example below, scroll-marker-group
is set to before
this time, because the scroll markers (presented as tabs) appear before the scroll container’s content.
Knowing when to use before
and when to use after
is very clear-cut. In the example below where ::scroll-marker-group
is aligned to the right, it’s still quite obvious that scroll-marker-group: after
is correct (if the writing mode is left-to-right, that is).
Browser support
We can detect browser support for it, if needed:
@supports (scroll-marker-group: before) {
/* scroll-marker-group supported */
}
@supports not (scroll-marker-group: before) {
/* scroll-marker-group not supported */
}
The same thing in JavaScript:
if (CSS.supports("scroll-marker-group: before")) {
/* scroll-marker-group supported */
}
if (!CSS.supports("scroll-marker-group: before")) {
/* scroll-marker-group not supported */
}
Specification
The scroll-marker-group
property is defined in the CSS Overflow Module Level 5 specification, which is currently in Working Draft status. This means that the information can change between now and the time when it becomes adopted as a formal Candidate Recommendation for browsers to implement.