My Case for ::scroll-button()
Writing a scroll-button web component was, and still is, a very sobering experience for me. I thought this kind of “little helper” would be easy in theory—just two arrows to move a scrollable container, right? In practice, it turned into a mess of detecting overflow, accounting for scroll-snap-type
, handling keyboard input, and making sure everything was accessible.
I read Sarah Soueidan’s piece on CSS carousels and accessibility, along with the related commentary by David Bushell and Vale Štefančík. They argue that scroll controls like this should be explicit DOM elements, designed and wired up by authors, because it preserves separation of concerns and gives developers direct control over semantics and accessibility. It is a well-reasoned position, and one many front-end developers share, but after investing a lot of time in this approach, I have to weigh in on the side of interactive scroll buttons as css pseudo-elements.
Scroll Buttons as Browser UI
Scroll buttons are as old as scrollbars themselves. Browsers and operating systems displayed them alongside the scroll track and scroll thumb on most platforms. They worked, and they were accessible. The problem was that they were often unattractive, or at least very opinionated in design, and they did not integrate well into our neatly designed web applications. While we gained the ability to style the track and thumb with CSS, we somehow lost the scroll buttons along the way.
From this perspective, the proposal by Robert Flack to treat interactive scroll buttons as pseudo-elements makes a lot of sense. The browser decides if and when to provide the button. The stylesheet helps the browser align its UI elements with the overall appearance of our website.
This approach aligns with a whole category of elements that the browser provides and is slowly making available to designers to style, matching the needs of their sites and applications. Like scrollbars, the ::marker
of a <select>
or <details>
element is part of this family. That family is about to grow considerably with the upcoming CSS Form Control Styling Level 1.
It was easy for browser vendors to drop the scroll button. Screen readers did not need them because keyboard commands for scrolling an area are separate from the elements that are clicked. It is widely understood that you can scroll through an element using the arrow keys, and, if available, the page keys. Some input devices provide a scroll wheel or similar mechanism. Touch devices use swipe gestures. Only pointer-based input relies on the buttons themselves, and that group seems to have been dismissed, which is why scroll buttons quietly disappeared from OS scrollbars.
It is good to see the web platform starting to address this oversight, and it is good that we are doing so in a way that keeps us flexible, avoids clutter in the DOM, and will hopefully soon allow me to retire my web component attempt as quickly as I created it.
Scrolling is Very Context Dependent
Scrolling is one of those things that are highly context dependent. Whether or not an element overflows and becomes a scrolling container depends on factors like device size, amount of content, container dimensions, and even user preferences. Check out this short video by Kevin Powell demonstrating this exact situation.
With the rise of responsive design, and the introduction of media queries and now even container queries, we began using CSS to control layout and even scrolling behavior in these situations.
To me, it feels wrong to drop scroll buttons into the DOM as elements. If it is not HTML’s concern whether a container is large enough to hold all its content without scrolling, why should it be HTML’s concern to provide the control elements for the rare case that the content overflows?
In the principle of separation of concerns, we often focus too much on CSS versus HTML versus JavaScript, ignoring the silent fourth party: the browser. The browser does a lot of the heavy lifting and provides the user with the tools to interact with our content, even if we did not explicitly include them. Take, for example, an old fixed-width and fixed-height website being displayed on a much smaller device than existed when it was created. It might not be a delightful experience, but we can still scroll in all directions, even though the authors never added a <scroll-bar>
element.
Summary
Of course, I will still have to improve and use button elements, especially in horizontal scrolls, for quite some time. In user testing, people actually use them, even though many browsers and OS versions ignore them.
I would really appreciate it if browsers would widely adopt ::scroll-button()
as soon as possible. It would declutter the DOM and help us stay flexible while still allowing us to design a pleasant UI.
For me, the experience of building a robust fallback only reinforced the idea that this kind of elements belongs in the browser, not in the DOM. Overflow is highly context-dependent, especially in responsive layouts, and the logic for whether a container can scroll, where it should stop, and how it should respect snapping is already built into the rendering engine. Just as with scrollbars, the browser should provide these controls automatically when needed, and CSS should be the layer where we style them, not where we reinvent them.
Resources
Mentioned in the article:
- Scroll-button web component: https://github.com/g12n/scroll-button
- Sarah Soueidan’s article on CSS carousels and accessibility: https://www.sarasoueidan.com/blog/css-carousels-accessibility/#conclusion-and-closing-thoughts
- David Bushell’s article on pseudo-elements: https://dbushell.com/2025/05/23/pseudo-elements/
- Vale Štefančík’s coment: https://vale.rocks/micros/20250524-1145
- Robert Flack’s scroll-button proposal: https://github.com/flackr/carousel/tree/main/scroll-button
- CSS Form Control Styling Level 1 spec: https://drafts.csswg.org/css-forms/
- Kevin Powell’s video on responsive scrolling: https://youtube.com/shorts/G7bKldPwBmk?si=jwVfcRxIo_emVHhD
- CSS Scroll Snap documentation: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll_snap
::scroll-button()
documentation: https://developer.mozilla.org/en-US/docs/Web/CSS/::scroll-button
Further reading:
- “Designing Intrinsic Layouts” by Jen Simmons: Designing Intrinsic Layouts