Scroll Marker Group

Create accessible, CSS-native navigation for scrollable content without JavaScript. Learn to build carousels and tab interfaces that work across devices.

What Scroll Marker Group Does

The scroll-marker-group CSS property controls whether a scroll container generates a ::scroll-marker-group pseudo-element, which serves as a container for scroll markers associated with the scrollable content. When you apply this property to a scroll container, the browser automatically creates a dedicated area where scroll markers are displayed and organized.

These markers act as navigation anchors, allowing users to click and jump to specific scroll targets within the container. The feature is part of the CSS Overflow Module Level 5 specification, representing the web platform's continued evolution toward more interactive, CSS-driven interfaces.

For modern web development teams, scroll marker group addresses a common pain point: creating accessible navigation controls for scrollable content. Traditionally, building features like carousel pagination or section navigation required JavaScript for state management, click handling, and keyboard accessibility. Scroll markers eliminate this complexity entirely, letting you declare what you want and letting the browser handle the implementation. This means fewer lines of code, fewer opportunities for bugs, and faster performance since the browser's native scroll handling is already highly optimized.

Key Benefits

  • JavaScript-free navigation - Create carousel and tab interfaces using only CSS, reducing bundle size and eliminating state synchronization issues
  • Built-in accessibility - Keyboard navigation and screen reader support come automatically, following WAI-ARIA patterns without requiring manual implementation
  • Progressive enhancement - Works seamlessly with scroll-snap and other modern CSS features, providing an enhanced experience in supporting browsers while maintaining full functionality elsewhere
  • Declarative approach - Focus on what you want to achieve, not how to implement it--the browser handles interaction mechanics, state changes, and scroll animation

Beyond these core benefits, scroll markers promote consistency across your codebase. When multiple components use the same CSS-based navigation pattern, users develop familiarity with the interaction model, reducing the learning curve for new features. The browser-managed state also eliminates common bugs like markers showing the wrong active state or becoming desynchronized from the scroll position.

Syntax and Values

The scroll-marker-group property accepts three values that control both the generation and placement of the scroll marker group.

Property Values

  • before - Places the scroll marker group at the start of the scroll container's tab order and visual layout. This is ideal when markers appear above or to the left of your scroll content.
  • after - Places the scroll marker group at the end of the tab order, following the scroll container's content. Use this when markers appear below or to the right of your content.
  • none - Default value, prevents any scroll marker group from being generated, effectively disabling scroll markers for that container.

Accessibility Implications

The choice between before and after has direct accessibility consequences. For keyboard users, the tab order must match the visual layout to prevent confusion. If your markers appear visually at the top of a carousel, users expect to encounter them first when pressing Tab. Using before ensures this natural flow. Conversely, if your markers appear below the content (like pagination dots at the bottom of a slideshow), after maintains the expected navigation sequence.

This alignment between visual and keyboard navigation helps users with cognitive disabilities understand the interface more easily. When the tab order matches what they see, there's no mental translation required between what they can reach via keyboard and what they see on screen. Screen readers also benefit from this consistency, as the accessibility tree reflects the expected navigation order.

scroll-marker-group Syntax
1/* Single values */2scroll-marker-group: before;3scroll-marker-group: after;4scroll-marker-group: none;5 6/* Global values */7scroll-marker-group: inherit;8scroll-marker-group: initial;9scroll-marker-group: revert;10scroll-marker-group: revert-layer;11scroll-marker-group: unset;12 13/* Feature detection */14@supports selector(::scroll-marker-group) {15 .carousel {16 scroll-marker-group: after;17 }18}

How Scroll Markers Work

The ::scroll-marker Pseudo-Element

The ::scroll-marker pseudo-element represents an individual scroll marker associated with a scroll target. Each scroll target within a scroll container can have a ::scroll-marker that appears within the ::scroll-marker-group pseudo-element. When users interact with these markers--clicking them with a pointer or activating through keyboard input--the browser scrolls the corresponding target into view using scroll-snapping behavior.

Individual ::scroll-marker pseudo-elements can be styled to reflect their state, including whether their associated target is currently visible. The :target-current pseudoclass specifically targets the scroll marker whose corresponding scroll target is currently in view, enabling patterns like highlighting the current page in a pagination control or emphasizing the visible section in a carousel.

.carousel-item::scroll-marker:target-current {
 background: #333;
 transform: scale(1.2);
}

Scroll Target Groups

Scroll targets are elements within a scroll container that have associated scroll markers. For an element to become a scroll target, it must either have an ID that is referenced by an anchor link within the scroll container, or it must explicitly opt-in to being a scroll target using the scroll-target property. This flexibility allows you to control which elements receive markers, enabling scenarios where not every section needs a navigation marker.

The scroll-target property provides explicit control over which elements generate scroll markers. By default, elements with IDs that are linked to from within the same scroll container become scroll targets automatically. However, scroll-target allows you to override this behavior--either enabling markers for elements without IDs or disabling markers for elements that would otherwise qualify. This granular control is useful when you want to group related content under a single marker or when automatic detection would create too many navigation points. For more details on scroll-target, see our guide on Scroll Target Group.

/* Explicitly enable scroll target */
.section-no-id {
 scroll-target: auto;
}

/* Explicitly disable scroll target */
.ignore-target {
 scroll-target: none;
}

Safari Tab Groups and Scroll Markers

Safari has been actively implementing scroll-related CSS features, with Safari 26 bringing significant enhancements to the web platform. While scroll marker group support continues to expand across browsers, Safari's implementation of related features like anchor positioning and scroll-driven animations demonstrates the browser's commitment to modern CSS interaction capabilities.

The Safari tab groups feature provides native UI for organizing multiple tabs within the browser, and while it's a browser UI feature rather than a CSS feature, it shares conceptual similarities with scroll markers in providing organized navigation through content collections. Both features help users manage and navigate through multiple pieces of content efficiently.

Integration with Modern CSS Features

Scroll markers work seamlessly with other modern CSS scroll features, creating powerful combinations:

  • Scroll-snap - Provides smooth, controlled scrolling with precise target alignment. When combined with markers, users can click to navigate and experience satisfying snap animations to each section.
  • Scroll-driven animations - Links animations to scroll position, enabling effects like progress bars that fill as users scroll through carousel slides marked by scroll markers.
  • Anchor positioning - Enables precise marker group placement using position-anchor, allowing you to position markers relative to the scroll container or viewport with pixel-perfect control.

These integrations demonstrate how modern CSS provides powerful primitives for building sophisticated interfaces declaratively. Rather than writing JavaScript to coordinate between scroll position, animation state, and marker appearance, you combine CSS features that work together natively.

Target Optical Center

Understanding Target Positioning

When a user clicks a scroll marker, the browser determines where to scroll the target element within the scroll container. The target optical center concept refers to ensuring that meaningful content appears where users expect it--typically centered or prominently visible. This becomes especially important when scroll targets have varying heights or when the scroll container has specific aspect ratios that affect visibility.

Scroll-snap's scroll-snap-align property provides the primary mechanism for controlling target positioning:

  • start - Aligns the target's start edge with the scroll container's start edge. Ideal for section-based navigation where headings should appear at the top.
  • end - Aligns the target's end edge with the scroll container's end edge. Useful when content should anchor to the bottom of the view.
  • center - Centers the target within the scroll container. The most common choice for carousel slides and equal-height content sections.

Best Practices for Target Positioning

  • For carousels, snap each slide to be fully visible using center alignment to maximize content prominence
  • For long-form content sections, position headings near the top using start alignment to maintain clear context
  • Use scroll-padding on the container for fine-tuned control around fixed headers or navigation bars
  • Test edge cases like first and last targets, which may snap differently at container boundaries
.carousel {
 scroll-snap-type: x mandatory;
 scroll-padding: 20px; /* Breathing room around edges */
}

.carousel-item {
 scroll-snap-align: center; /* Center slides in view */
}

Practical Implementation: Carousel Example

Building a carousel with scroll markers demonstrates the feature's practical application. The HTML structure consists of a scroll container with multiple child elements representing slides, and scroll markers are automatically generated for each slide. Here's a complete example:

<div class="carousel" role="region" aria-label="Product Gallery">
 <div class="carousel-item" id="slide-1">
 <img src="slide1.jpg" alt="Product view 1">
 </div>
 <div class="carousel-item" id="slide-2">
 <img src="slide2.jpg" alt="Product view 2">
 </div>
 <div class="carousel-item" id="slide-3">
 <img src="slide3.jpg" alt="Product view 3">
 </div>
 <div class="carousel-item" id="slide-4">
 <img src="slide4.jpg" alt="Product view 4">
 </div>
</div>

How It Works Together

The carousel container enables horizontal scrolling with overflow-x: auto and establishes snapping behavior with scroll-snap-type: x mandatory. Each item takes full width with flex: 0 0 100% and snaps to the center of the container. When scroll-marker-group: after is applied, the browser generates a ::scroll-marker-group pseudo-element containing markers for each carousel item.

Styling the marker group uses flexbox to center the pagination dots, while individual markers are styled as circles with border-radius: 50%. The :target-current pseudoclass provides visual feedback by changing the active marker's background color, giving users clear indication of their current position in the slideshow.

The implementation requires no JavaScript for navigation functionality--clicking markers, keyboard navigation, and scroll-snapping all work natively. This approach reduces bundle size, eliminates client-side state management code, and provides consistent behavior across devices and input methods. For more advanced carousel techniques, explore our CSS Scroll Snap guide.

Building Tab Interfaces

Tab interfaces represent another common use case for scroll markers. By using a vertical scroll container with scroll-snap and scroll markers, you can create tab-like navigation where clicking markers scrolls to reveal different content sections. This pattern is particularly useful for long-form content that benefits from both continuous scrolling and section-based navigation.

Complete HTML Structure

<nav class="tabs" role="tablist" aria-label="Feature sections">
 <section class="tab-content" id="overview" data-tab-name="Overview">
 <h2>Product Overview</h2>
 <p>Introduction to our product features...</p>
 </section>
 <section class="tab-content" id="features" data-tab-name="Features">
 <h2>Key Features</h2>
 <p>Detailed feature breakdown...</p>
 </section>
 <section class="tab-content" id="pricing" data-tab-name="Pricing">
 <h2>Pricing Plans</h2>
 <p>Cost and subscription options...</p>
 </section>
 <section class="tab-content" id="faq" data-tab-name="FAQ">
 <h2>Frequently Asked</h2>
 <p>Answers to common questions...</p>
 </section>
</nav>

Mobile Considerations

For mobile devices, ensure markers meet touch target size guidelines--minimum 44x44 pixels for comfortable tapping. Increase marker spacing on smaller screens to prevent accidental clicks. Consider hiding markers on very narrow viewports and relying on native swipe gestures instead, using CSS media queries:

@media (max-width: 480px) {
 .tabs::scroll-marker-group {
 /* Larger touch targets on mobile */
 padding: 1.5rem;
 gap: 1rem;
 }
 
 .tab-content::scroll-marker {
 min-width: 44px;
 min-height: 44px;
 }
}

Responsive Behavior

The fixed marker group at the top of the viewport provides persistent navigation as users scroll through long content. Marker labels adapt to the content structure--using the data-tab-name attribute lets you define custom labels separate from the section heading text. This approach creates a navigation experience that feels like native app tabs while remaining entirely CSS-driven. Our UI/UX design services can help you implement these patterns effectively.

Tabs CSS Example
1.tabs {2 scroll-snap-type: y mandatory;3 scroll-marker-group: before;4}5 6.tab-content {7 min-height: 100vh;8 scroll-snap-align: start;9}10 11.tabs::scroll-marker-group {12 position: fixed;13 top: 0;14 left: 0;15 display: flex;16 gap: 1rem;17 padding: 1rem;18 background: white;19 z-index: 100;20}21 22.tab-content::scroll-marker {23 content: attr(data-tab-name);24 padding: 0.5rem 1rem;25 background: #eee;26 border-radius: 4px;27 cursor: pointer;28}29 30.tab-content::scroll-marker:target-current {31 background: #333;32 color: white;33}

Accessibility Considerations

Keyboard Navigation

Scroll markers are designed with accessibility as a core principle, providing keyboard-accessible navigation out of the box:

  • Tab order respects scroll-marker-group value - Markers placed at beginning or end of sequence based on before or after
  • Arrow key navigation - Users can navigate through markers using keyboard, moving between sections without scrolling
  • Activation - Enter or Space activates a marker, scrolling to the associated target

Screen Reader Support

  • Automatic labeling - Browser generates accessible names from target content, including heading text and data attributes
  • ARIA integration - Works with existing accessibility tree, no additional ARIA attributes required
  • No manual ARIA needed - Built-in support eliminates custom workarounds and potential accessibility mistakes

Testing Accessibility

When implementing scroll markers, test with actual assistive technologies:

  1. Keyboard-only testing - Navigate using only Tab, Enter, and arrow keys
  2. Screen reader testing - Use NVDA, VoiceOver, or JAWS to verify announcements
  3. Focus visible testing - Ensure focus states are clearly visible on all markers
  4. Reduced motion testing - Verify behavior when prefers-reduced-motion is enabled
@media (prefers-reduced-motion: reduce) {
 .carousel {
 scroll-behavior: auto;
 }
 
 .carousel::scroll-marker-group {
 transition: none;
 }
}

Progressive Enhancement

A key advantage of scroll markers is their progressive enhancement nature. In browsers that don't support the feature, the markers simply don't appear, leaving the scrollable content fully functional through traditional scrolling. The core content remains accessible and usable, with scroll markers serving as an enhancement for browsers that support them.

Best Practices

Design Guidelines

  1. Keep markers visually distinct but not distracting - Simple shapes in neutral colors work well, with more prominent styling reserved for the active state via :target-current
  2. Provide clear active state feedback - Use :target-current to highlight current position with color, size, or opacity changes
  3. Ensure adequate spacing - Prevent accidental clicks, especially on touch devices. Aim for 44px minimum touch targets
  4. Consider placement carefully - Fixed positioning for persistent navigation, inline for content-integrated markers like carousel pagination

Common Pitfalls to Avoid

  • Overloading with too many markers - If you have more than 7-8 scroll targets, consider grouping related sections or using a different navigation pattern
  • Ignoring the before/after choice - The placement affects tab order, which impacts keyboard users. Match visual placement to logical navigation sequence
  • Forgetting scroll-padding - Without proper padding, content may snap behind fixed headers, creating poor user experience
  • Neglecting focus styles - Ensure keyboard users can see which marker has focus

Performance Considerations

  • Pseudo-element implementation - No DOM nodes added, minimal layout impact compared to JavaScript-based navigation
  • Native scroll handling - Browser optimizes scroll performance, avoiding janky animations from JavaScript scroll manipulation
  • Test on target devices - Complex configurations with multiple scroll features may affect scroll performance on lower-powered devices

Feature Detection Pattern

@supports selector(::scroll-marker-group) {
 .scroll-container {
 scroll-marker-group: after;
 }
}

/* Fallback for older browsers - consider a simple indicator */
@supports not selector(::scroll-marker-group) {
 .scroll-container {
 /* Alternative: CSS scroll-snap still works */
 scroll-snap-type: x mandatory;
 }
}

Frequently Asked Questions

Ready to Build Modern CSS Interfaces?

Our UI/UX team specializes in leveraging modern CSS features to create performant, accessible web interfaces that work across all devices and browsers.