@svelte-put/dragscroll GitHub

action to add "drag-to-scroll" behavior

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

Migrating to Svelte 5? See the new 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';
</script>

<div class="overflow-x-auto" 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 place-items-center
            {row % 2 === 0
            ? 'odd:bg-black odd:text-white even:bg-white even:text-black'
            : 'odd:bg-white odd:text-black even:bg-black even:text-white'}
          "
        >
          {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';
</script>

<div class="grid place-items-center">
  <div class="flex items-center space-x-4">
    <p>Select the scroll axis</p>
    <label class="cursor-pointer flex items-center gap-2">
      <input class="c-input" type="radio" name="axis" value="x" id="x" bind:group={axis} />
      x
    </label>
    <label class="cursor-pointer flex items-center gap-2">
      <input class="c-input" type="radio" name="axis" value="y" id="y" bind:group={axis} />
      y
    </label>
    <label class="cursor-pointer flex items-center gap-2">
      <input class="c-input" type="radio" name="axis" value="both" id="both" bind:group={axis} />
      both
    </label>
  </div>
  <div
    class="max-h-[300px] max-w-[300px] overflow-x-auto md:max-h-[400px] md:max-w-[400px] mt-4"
    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 place-items-center
              {row % 2 === 0
              ? 'odd:bg-black odd:text-white even:bg-white even:text-black'
              : 'odd:bg-white odd:text-black even:bg-black even:text-white'}
            "
          >
            {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