Docs/API
Modifiers and collision
Functions that change where the dragged item goes, and those that choose the target under it.
Loading the demo…
<script setup lang="ts">
import { ref } from 'vue';
import { DnDProvider, closestCenter, closestCorners, pointerFirst, pointerWithin, rectIntersection } from '@vue-dnd-kit/core';
import ModifierLab from './ModifierLab.vue';
// Collision detection is the provider's: it picks the target, here one of the two pads.
const COLLISIONS = { pointerFirst, pointerWithin, rectIntersection, closestCenter, closestCorners };
const collision = ref<keyof typeof COLLISIONS>('pointerFirst');
</script>
<template>
<DnDProvider :collision="COLLISIONS[collision]">
<div class="demo">
<code class="call"><DnDProvider :collision="{{ collision }}"></code>
<div class="collisions" role="radiogroup" aria-label="collision">
<label v-for="name in Object.keys(COLLISIONS)" :key="name" :class="{ on: collision === name }">
<input v-model="collision" type="radio" :value="name" />
{{ name }}
</label>
</div>
<ModifierLab />
</div>
</DnDProvider>
</template>
<style scoped>
.demo {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.collisions {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 2px;
max-width: 100%;
padding: 3px;
border-radius: 9px;
background: color-mix(in srgb, currentColor 7%, transparent);
}
.call {
font: 11px/1.4 ui-monospace, Menlo, Consolas, monospace;
color: #42b883;
}
label {
padding: 4px 8px;
border-radius: 6px;
font: 11px/1.3 ui-monospace, Menlo, Consolas, monospace;
cursor: pointer;
}
label.on {
background: Canvas;
box-shadow: 0 1px 3px rgb(0 0 0 / 0.25);
font-weight: 600;
}
label:has(input:focus-visible) {
outline: 2px solid #42b883;
}
input {
position: absolute;
opacity: 0;
pointer-events: none;
}
</style>Modifiers
import { restrictToParent, snapToGrid } from '@vue-dnd-kit/core';
makeSortableList(list, { items, modifiers: [restrictToParent] });
makeDragArea(board, { modifiers: [snapToGrid({ x: 24, y: 24, smooth: true })] });
A modifier takes the drag's offset and returns a new one. They run in order: the provider's
modifiers, a drag area's, the draggable's own (or its list's), then the area's bounds
(restrictToArea), and the axis lock last. See Axes, bounds and grids.
ModifierMoves only vertically: horizontally it stays with the content it started in (containerShift), however the page scrolls. The axis: 'y' option does the same, last.
ModifierMoves only horizontally: vertically it stays with the content it started in (containerShift), however the page scrolls. The axis: 'x' option does the same, last.
ModifierKeeps the overlay inside the window.
ModifierKeeps the overlay inside the container the drag started in: the sortable list (not its DOM parent) or, for plain draggables, the parent element.
(target: MaybeElementRef) => ModifierKeeps the overlay inside an element: the element, a ref or a getter.
ModifierKeeps the overlay inside the first scrollable ancestor of the dragged element.
(size: number | SnapToGridOptions) => ModifierSnaps the overlay to a grid, to the nearest cell: a number is the size of square cells; options set each axis, where the grid starts and a glide between cells (SnapToGridOptions).
ModifierCenters the overlay under the pointer instead of keeping the grab offset.
Options of snapToGrid.
numberThe cell's width in px. Without one (or 0), the drag moves freely along x.
numberThe cell's height in px. Without one (or 0), the drag moves freely along y: { y: 15 } snaps the time of a calendar event only.
'container' | 'delta''container' (default): the overlay's top-left lands on grid lines drawn from the container's top-left (containerRect: the sortable list or the parent element). 'delta': the drag offset is rounded, keeping where the item started off-grid.
boolean | AnimationOptionsGlide the overlay between snapped positions (default 80ms). Collision still uses the snapped position at once.
Changes where the dragged item goes: takes the drag's offset (transform) and returns a new one.
type Modifier = (args: ModifierArgs) => CoordinatesWhat a modifier gets, on every move of the drag.
CoordinatesOffset from the drag start, as modified by the previous modifiers.
ActiveThe drag.
RectRect of the dragged element at drag start.
RectRect of the overlay box if it were moved by transform, at the size it has now. With overlayFit: 'slot' the box resizes around the pointer, so it isn't always activeRect moved by transform.
CoordinatesPointer position at drag start.
Rect | nullSortable list container (or parent element) of the dragged item, where it is now (it follows scrolling).
CoordinatesHow far the content the drag started in has moved on screen since the start: the container moved (the page or a container around it scrolled, the layout shifted), and its content scrolled inside it. Axis locks hold the other axis there, so the drag stays on its row or column of that content.
RectRect of the window (the viewport).
Over | nullThe drop target under the drag, as last found; null over nothing.
Collision detection
import { closestCorners } from '@vue-dnd-kit/core';
<DnDProvider :collision="closestCorners" />
The provider's collision picks the target; the best candidate comes first.
CollisionDetectionDefault: what is under the pointer, else what the overlay overlaps.
CollisionDetectionTargets under the pointer, from hit-testing: respects z-order, overlays and shadow roots.
CollisionDetectionTargets overlapping the overlay: higher priority, then deeper nesting, then intersection over union.
CollisionDetectionEvery target, by distance between centers.
CollisionDetectionEvery target, by summed distance between corners (good for stacked targets such as kanban columns).
Returns candidate ids, best first.
type CollisionDetection = (args: CollisionArgs) => Key[]What a collision detection gets, on every move of the drag.
CoordinatesPointer in viewport coordinates, after modifiers.
Rect | nullRect of the dragged box (the overlay, or the element itself with overlay: false) where the drag has moved it.
CollisionCandidate[]Every drop target the drag could go to, whether its accept rule takes the drag or not.
Key[]Drop targets under the pointer from hit-testing (respects z-order and shadow roots), best first.
A drop target a collision detection can pick: enabled, on the page and not fully clipped.
KeyId of the drop target.
RectVisible part of the target: clipped by its scroll containers and the viewport.
numberThe target's priority (default 0): higher wins when targets overlap without nesting. Sortable items beat containers.
numberNesting level among drop targets: 0 at the top, deeper targets have higher values.