scrollLock
Prevent page scrolling while dragging
The scrollLock plugin prevents page or container scrolling during drag operations. Essential for mobile devices and touch interfaces where dragging triggers unwanted scrolling.
scrollLock(); // Lock all scrolling
scrollLock({ lockAxis: 'x' }); // Only horizontal scrolling
scrollLock({ container: myContainer }); // Lock specific container
scrollLock({ allowScrollbar: true }); // Keep scrollbars clickable
Basic Usage
<script setup>
import { ref } from 'vue';
import { scrollLock, vDraggable } from '@neodrag/vue';
const scrollContainer = ref();
</script>
<template>
<div>
<div v-draggable="[scrollLock()]">
Drag me - page won't scroll
</div>
<div v-draggable="[scrollLock({ lockAxis: 'x' })]">
Vertical scrolling still works
</div>
<div ref="scrollContainer" class="scroll-area">
<div
v-draggable="[
scrollLock({ container: () => scrollContainer }),
]"
>
Lock specific container
</div>
</div>
</div>
</template>Dynamic Configuration
<script setup>
import { ref } from 'vue';
import { scrollLock, vDraggable, useCompartment } from '@neodrag/vue';
const lockMode = ref('both');
const allowScrollbar = ref(false);
const targetContainer = ref();
const scrollLockComp = useCompartment(() => {
if (lockMode.value === 'none') return null;
return scrollLock({
lockAxis: lockMode.value,
allowScrollbar: allowScrollbar.value,
container: () => targetContainer.value,
});
});
</script>
<template>
<div>
<div ref="targetContainer" class="scroll-container">
<div v-draggable="() => [scrollLockComp]">
Lock Mode: {{ lockMode }}
<br />
Scrollbar: {{ allowScrollbar ? 'visible' : 'hidden' }}
</div>
</div>
<div class="controls">
<label>
Lock Mode:
<select v-model="lockMode">
<option value="both">Both Axes</option>
<option value="x">X-Axis Only</option>
<option value="y">Y-Axis Only</option>
<option value="none">Disabled</option>
</select>
</label>
<label>
<input v-model="allowScrollbar" type="checkbox" />
Allow Scrollbar
</label>
</div>
</div>
</template>Common Use Cases
Mobile-Friendly Dragging
// Prevent mobile bounce scrolling
scrollLock({
lockAxis: 'both',
allowScrollbar: false, // Hide scrollbars on mobile
});
Modal/Overlay Dragging
// Lock body scrolling when dragging modal
scrollLock({
container: document.body,
lockAxis: 'both',
});
Horizontal Slider
// Allow vertical scrolling, prevent horizontal
scrollLock({
lockAxis: 'x',
allowScrollbar: true, // Keep vertical scrollbar
});
Canvas/Editor Tools
// Lock scrolling within canvas container
scrollLock({
container: () => document.getElementById('canvas-container'),
lockAxis: 'both',
});
Combining with Other Plugins
With Bounds
const plugins = [scrollLock(), bounds(BoundsFrom.viewport())];
Touch-Optimized Setup
const plugins = [
scrollLock({ lockAxis: 'both' }),
threshold({ distance: 5, delay: 100 }), // Prevent accidental drags
touchAction('none'), // Disable browser touch behaviors
];
Conditional ScrollLock
// Only lock on touch devices
const isTouchDevice = 'ontouchstart' in window;
const plugins = [
isTouchDevice ? scrollLock() : null,
bounds(BoundsFrom.parent()),
].filter(Boolean);
Platform Considerations
iOS Safari
// iOS requires specific handling
scrollLock({
lockAxis: 'both',
allowScrollbar: false, // Important for iOS
container: document.body,
});
Desktop vs Mobile
const isMobile = /Mobi|Android/i.test(navigator.userAgent);
scrollLock({
lockAxis: isMobile ? 'both' : 'y', // More aggressive on mobile
allowScrollbar: !isMobile, // Keep scrollbars on desktop
});
How It Works
The scrollLock plugin prevents scrolling by temporarily modifying CSS properties:
During drag start:
- Stores original styles -
user-select,touch-action,overflow - Applies lock styles:
user-select: none- Prevents text selectionoverflow: hidden- Hides scrollbars (ifallowScrollbar: false)touch-action: pan-x/pan-y/none- Controls touch scrolling direction
During drag end:
- Restores original styles - Everything returns to normal
Target selection:
- If
containerspecified, applies to that element - If
containerisdocument.documentElementor not specified, applies todocument.body - Function containers are called dynamically each time
API Reference
function scrollLock(
options?: {
lockAxis?: 'x' | 'y' | 'both';
container?: HTMLElement | (() => HTMLElement);
allowScrollbar?: boolean;
} | null,
): Plugin;
Options:
lockAxis- Which scrolling to prevent ('both'default)'x'- Only horizontal scrolling locked'y'- Only vertical scrolling locked'both'- All scrolling locked
container- Where to apply scroll lock (document.documentElementdefault)HTMLElement- Specific element() => HTMLElement- Dynamic element selection
allowScrollbar- Keep scrollbars clickable (falsedefault)true- Scrollbars remain visible and functionalfalse- Scrollbars hidden viaoverflow: hidden
Returns: A plugin object for use with draggable.
Browser Support: All modern browsers, with special handling for iOS Safari touch behaviors.