Sync Scroll

Keep several scroll containers locked to the same position. A SyncScrollProvider registers every pane mounted beneath it; a master broadcasts its scrollTop / scrollLeft to all the slaves, so scrolling one moves the others in lockstep. Slaves never drive the group — they only follow — which keeps the sync loop one-directional and free of feedback.

Each pane is a plain div you style yourself: give it a fixed height (or width) and an overflow so it actually scrolls. The components just attach the right ref and event listener.

Master / slave panes

Two side-by-side panes inside one provider. The left pane is the SyncScroll master; the right is a SyncScrollSlave. Scroll the master and the slave tracks it. By default sync is vertical.

master · row 1
master · row 2
master · row 3
master · row 4
master · row 5
master · row 6
master · row 7
master · row 8
master · row 9
master · row 10
master · row 11
master · row 12
master · row 13
master · row 14
master · row 15
master · row 16
master · row 17
master · row 18
master · row 19
master · row 20
master · row 21
master · row 22
master · row 23
master · row 24
master · row 25
master · row 26
master · row 27
master · row 28
master · row 29
master · row 30
master · row 31
master · row 32
master · row 33
master · row 34
master · row 35
master · row 36
master · row 37
master · row 38
master · row 39
master · row 40
master · row 41
master · row 42
master · row 43
master · row 44
master · row 45
master · row 46
master · row 47
master · row 48
master · row 49
master · row 50
master · row 51
master · row 52
master · row 53
master · row 54
master · row 55
master · row 56
master · row 57
master · row 58
master · row 59
master · row 60
slave · row 1
slave · row 2
slave · row 3
slave · row 4
slave · row 5
slave · row 6
slave · row 7
slave · row 8
slave · row 9
slave · row 10
slave · row 11
slave · row 12
slave · row 13
slave · row 14
slave · row 15
slave · row 16
slave · row 17
slave · row 18
slave · row 19
slave · row 20
slave · row 21
slave · row 22
slave · row 23
slave · row 24
slave · row 25
slave · row 26
slave · row 27
slave · row 28
slave · row 29
slave · row 30
slave · row 31
slave · row 32
slave · row 33
slave · row 34
slave · row 35
slave · row 36
slave · row 37
slave · row 38
slave · row 39
slave · row 40
slave · row 41
slave · row 42
slave · row 43
slave · row 44
slave · row 45
slave · row 46
slave · row 47
slave · row 48
slave · row 49
slave · row 50
slave · row 51
slave · row 52
slave · row 53
slave · row 54
slave · row 55
slave · row 56
slave · row 57
slave · row 58
slave · row 59
slave · row 60

Drag to scroll

SyncDragX / SyncDragY (and SyncDrag for both axes) add click-and-drag panning and act as a master, so paired SyncDragSlave* panes follow along. Drag either track below horizontally.

drag 1
drag 2
drag 3
drag 4
drag 5
drag 6
drag 7
drag 8
drag 9
drag 10
drag 11
drag 12
drag 13
drag 14
drag 15
drag 16
drag 17
drag 18
drag 19
drag 20
drag 21
drag 22
drag 23
drag 24
drag 25
drag 26
drag 27
drag 28
drag 29
drag 30
drag 31
drag 32
drag 33
drag 34
drag 35
drag 36
drag 37
drag 38
drag 39
drag 40
slave 1
slave 2
slave 3
slave 4
slave 5
slave 6
slave 7
slave 8
slave 9
slave 10
slave 11
slave 12
slave 13
slave 14
slave 15
slave 16
slave 17
slave 18
slave 19
slave 20
slave 21
slave 22
slave 23
slave 24
slave 25
slave 26
slave 27
slave 28
slave 29
slave 30
slave 31
slave 32
slave 33
slave 34
slave 35
slave 36
slave 37
slave 38
slave 39
slave 40

Exports

ExportKindRole
SyncScrollProviderComponentContext boundary that registers panes and relays the master's scroll position to slaves. Wrap every group in one.
SyncScrollComponentMaster pane (overflow-y-auto). Its scroll position drives all slaves in the group.
SyncScrollSlaveComponentSlave pane (overflow-y-auto). Follows the master; its own scrolling does not drive others.
SyncDragComponentDrag-to-scroll master on both axes. Behaves like a master for syncing.
SyncDragXComponentHorizontal-only drag-to-scroll master.
SyncDragYComponentVertical-only drag-to-scroll master.
SyncDragSlaveComponentDrag-to-scroll slave on both axes. Follows a master.
SyncDragSlaveXComponentHorizontal-only drag-to-scroll slave.
useSyncScrollHookReturns a ref registering the element as a master. Backs SyncScroll.
useScrollSlaveHookReturns a ref registering the element as a slave. Backs the slave components.
useSyncDragHookReturns a ref registering the element with the drag role (acts as a master). Backs the drag components.

All components accept the standard div props plus asChild — pass asChild to merge the scroll ref onto your own single child element instead of rendering a wrapper div.

Hook options

The hooks accept an options object:

OptionTypeDefaultDescription
enabledbooleantrueToggle registration and listeners off without unmounting.
axis'vertical' | 'horizontal' | 'both''vertical'Which scroll axes are tracked and synced.
refRefObject<HTMLDivElement>Provide your own element ref instead of the internal one.