@svelte-put/dragscroll

GitHub Github

action to add "drag-to-scroll" behavior

@svelte-put/dragscroll @svelte-put/dragscroll @svelte-put/dragscroll @svelte-put/dragscroll

Still on Svelte 4? See the old docs site here.

Installation

npm install --save-dev @svelte-put/dragscroll
pnpm add -D @svelte-put/dragscroll
yarn add -D @svelte-put/dragscroll

Quick Start

Typically, use:dragscroll should be placed on the scroll container.

Below is a minimal demo of dragscroll with default options. Try scrolling horizontally by pressing and dragging your mouse within the chessboard-patterned box.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<script>
	import { dragscroll } from '@svelte-put/dragscroll';

	const classesForOddRows = 'odd:bg-white odd:text-black even:bg-black even:text-white';
	const classesForEvenRows = 'odd:bg-black odd:text-white even:bg-white even:text-black';
</script>

<div class="mx-auto max-w-4xl overflow-x-auto border-2 border-violet-500 p-4" use:dragscroll>
	{#each new Array(10) as _, row}
		<div class="grid grid-cols-[repeat(10,1fr)]">
			{#each new Array(10) as _, col}
				<div
					class="
						grid h-10 w-32 select-none place-items-center
						{row % 2 === 0 ? classesForEvenRows : classesForOddRows}
          "
				>
					{row * 10 + col + 1}
				</div>
			{/each}
		</div>
	{/each}
</div>

Specifying the Scroll Axis

dragscroll supports both axes. you can specifying one or both scrolling axes using the axis option. By default, axis is set to x.

Select the scroll axis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<script lang="ts">
	import { dragscroll, type DragScrollParameters } from '@svelte-put/dragscroll';

	let axis: DragScrollParameters['axis'] = 'both';

	const classesForOddRows = 'odd:bg-white odd:text-black even:bg-black even:text-white';
	const classesForEvenRows = 'odd:bg-black odd:text-white even:bg-white even:text-black';
</script>

<div class="not-prose mx-auto grid max-w-4xl place-items-center">
	<div class="flex items-center space-x-4">
		<p>Select the scroll axis</p>
		<label class="flex cursor-pointer items-center gap-2">
			<input class="c-input" type="radio" name="axis" value="x" id="x" bind:group={axis} />
			x
		</label>
		<label class="flex cursor-pointer items-center gap-2">
			<input class="c-input" type="radio" name="axis" value="y" id="y" bind:group={axis} />
			y
		</label>
		<label class="flex cursor-pointer items-center gap-2">
			<input class="c-input" type="radio" name="axis" value="both" id="both" bind:group={axis} />
			both
		</label>
	</div>
	<div
		class="mt-4 max-h-[300px] max-w-[300px] overflow-x-auto border-2 border-violet-500 md:max-h-[400px] md:max-w-[400px]"
		use:dragscroll={{ axis }}
	>
		{#each new Array(10) as _, row}
			<div class="grid grid-cols-[repeat(10,1fr)]">
				{#each new Array(10) as _, col}
					<div
						class="
							grid h-20 w-20 select-none place-items-center
              {row % 2 === 0 ? classesForEvenRows : classesForOddRows}
            "
					>
						{row * 10 + col + 1}
					</div>
				{/each}
			</div>
		{/each}
	</div>
</div>

mouse vs pointer

By default, dragscroll assumes PointerEvent, i.e pointerup, pointerdown, pointermove, pointerleave. You can switch to MouseEvent equivalents by setting the event option to mouse.

<div use:dragscroll={{ event: 'pointer' }}>...</div>
<div use:dragscroll={{ event: 'mouse' }}>...</div>

Disable Cursor Handling

By default, dragscrolladds cursor: grab to the node the action is placed on, and similarly, cursor: grabbing on mousedown. This can be disabled by setting the cursor option to false (default is true).

<div use:dragscroll={{ cursor: false }}>...</div>

Limitation

There is a known issue when dragscroll is used with scroll-snap-align, where the scroll container tends to be unresponsive to dragscroll and requires a great mousemove length to snap to the next box.

In the example below, try using the scrollbar to confirm scroll-snap-align has been set up. Then, try dragging with mouse and notice that it only works when the mouse is dragged over almost the entire width of the container.

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

If you find a solution or workaround to the above, please consider open a PR or discussion thread. Thank you!

Happy dragging! 👨‍💻

Edit this page on Github