TrademarkTrademarkDocs
Ctrl k
Search docs...
Components

ScrollContainer

Updated: September 22, 2026
View on GitHub
The ScrollContainer component moves a track of items horizontally, with navigation buttons, pointer drag, optional wrap-around, optional proximity scaling, optional markers, and an index you can drive from outside. It moves a track with a transform rather than scrolling a box. That is what lets tiles paint past the container's edges — the items either side of the ones in front stay visible, so the run reads as something continuous rather than a window with two hard cuts in it. Pass clip to keep everything inside the component's own box instead. Because the browser is no longer doing the scrolling, a trackpad's horizontal gesture does not move the track. draggable is on by default and the controls are always shown, so there is never an invisible affordance. Past the last item the track continues into the first, in the same direction, with no rewind. Both controls stay enabled. Markers show how many items there are and which one is in front, and jump to one when pressed. markers takes true to put them opposite the controls, or "top" / "bottom" to name the side. The track follows a pointer — mouse, pen or finger. A gesture is claimed for one axis on its first movement and never reassigned, so a vertical swipe still scrolls the page. Let go past a fifth of a tile, or flick, and the track advances; anything shorter settles back. Without infinite the track resists being pulled past either end and springs back. A drag that ends on a tile does not also open it — the click is swallowed before it reaches the item. proximity scales each tile by how far it is from the one in front, so the run has a focus that moves with it. It is continuous rather than stepped: halfway through a drag the outgoing and incoming tiles are the same size, so the emphasis crosses between them as the pointer moves instead of snapping when the track settles. Pass true for a gentle default, or a number for how much smaller each whole step away is, as a fraction — 0.08 makes the immediate neighbour 92%. Tiles stop shrinking at 72%, so a long run does not trail off into nothing. active brings an item to the front by its index, and onActiveChange reports the item that arrived there, however it got there — a control, a marker or a drag. Together they let something outside the component stand in for the markers: a row of names, a set of thumbnails, a table of contents. active is a command, not a lock. The run still moves on its own, and it is onActiveChange that keeps the caller's own state level with it. An active that never changes does not pin the run in place. Position navigation controls at the top or bottom with different horizontal alignments. Every prop other than the ones listed below is applied to each tile, so a tile is styled from out here. Tiles carry no appearance of their own: no border, no radius, no aspect ratio. The only sizing they arrive with is a minWidth floor, so a carousel of anything that fills its parent has something to fill. Give them whatever shape the content needs.
Prop
Type
Default
itemsrequired
The items in the scroll area.
React.ReactNode[]—
controlPlacement
Where the controls sit relative to the content.
top-starttop-endbottom-startbottom-endtop-centertop-betweenbottom-centerbottom-between
top-start
infinite
Wrap around: past the last item the track continues into the first.
booleanfalse
markers
Show markers for the item count and the one in front. true puts them opposite the controls.
booleantopbottom
false
draggable
Drag the track with a pointer. On by default.
booleantrue
step
Items moved per control press.
number1
clip
Clip the track at its edges instead of letting tiles paint past them.
booleanfalse
proximity
Scale tiles by their distance from the one in front. true is a gentle default; a number is the drop per whole step.
booleannumber
false
active
Bring this item to the front. A command, not a lock — the run still moves on its own.
number—
onActiveChange
Called with the index of the item that came to the front, however it got there.
(index: number) => void—
…and every FlexProps propinherited—
Edit this page on GitHub
TrademarkTrademark
Built with curiosity by Lorant One and the Design Engineers Club