Snap
Manages carousel-like behavior. Supports
- Tracks slide progress
- Numerous callbacks for event handling
- Snapping
- Wheel interaction
- Swipe/Drag events
- Custom gaps with css units supported
- Smooth transitions
- and more...
- Snap does not apply any styles to the container or slides, it only provides logic, which allows you building custom carousels.
Demo
Explore a basic demo on CodePen:
More demos
To explore more demos, click here.
Props
Static Props
Static properties are set during initialization and cannot be modified later.
container
- Type:
HTMLElement - Default: none
- HTML container element where listeners are attached.
eventsEmitter
- Type:
HTMLElement | null - Default:
null - HTML element used to emit events.
activeIndex
- Type:
number - Default:
0 - Default active index.
Mutable Props
Mutable properties can be updated at runtime using .updateProps().
slides
- Type: (
HTMLElement| SnapSlide)[] |false; - Default:
false - Slides instances. If
false, all container's children will be considered as slides.
direction
- Type:
'horizontal' | 'vertical' - Default:
'horizontal' - Sliding direction.
See demo
centered
- Type:
boolean - Default:
false - Centered slides.
See demo
loop
- Type:
boolean - Default:
false - Detects if need to loop the slides.
See demo
gap
- Type:
number | string - Default:
0 - The gap between slides. Supports css units like
px,rem,vw,vh,svh.
See demo
lerp
- Type:
number - Default:
vevet.mobile ? 1 : 0.2 - Linear interpolation factor for smooth animation.
See demo
freemode
- Type:
boolean | 'sticky' - Default:
false - Enables freemode, with or without sticky magnets.
Note that you may need to disableshortSwipeswhen usingstickyfreemode.
See demo
stickOnResize
- Type:
boolean - Default:
true - Stick to the nearest slide on window resize.
friction
- Type:
number - Default:
0 - Friction that makes the slides tend to the nearest slide magnet. The value is a number between
0 and 1which is multiplied by thelerpvalue.0disables friction.
See demo
edgeFriction
- Type:
number - Default:
0.85 - Maximum friction between the final slide and the maximum translation value. From
0 to 1. The higher value the more resistance is applied.
See demo
duration
- Type:
number | ((distance: number) => number) - Default:
500 - Slide animation duration.
See demo
easing
- Type:
TEasingType - Default:
EaseOutCubic - Easing type for smoother animation. Accepts standard easing types or an array of bezier values.
See easing types for more information
See demo
slideSize
- Type:
'auto' | 'stretch' | number | string - Default:
'auto' - Default slide size. Supported values:
autodetects slide size depending on the element or container size.stretchdetects slide size as the container size.numberdefines the slide size in pixels.- CSS units like
px,rem,vw,vh,svh.
- Note that this property does not change real slide sizes. It is used for virtual slides & custom logic.
swipe
- Type:
boolean - Default:
true - Enable or disable swipe events.
grabCursor
- Type:
boolean - Default:
false - User will see the "grab" cursor when hovering and "grabbing" when swiping.
See demo
swipeSpeed
- Type:
number - Default:
1 - Speed factor for swipe movements.
See demo
swipeAxis
- Type:
'x' | 'y' | 'auto' - Default:
'auto' - Swipe axis. If
auto, the axis will be automatically detected depending ondirection.
followSwipe
- Type:
boolean - Default:
false - If
false, then slider will be animated only when you release the finger, it will not move while you hold your finger on it.
See demo
shortSwipes
- Type:
boolean - Default:
true - When
true, swipes shorter thanshortSwipeDurationcan trigger slide change. Short swipes work only whenfollowSwipeistrue.
shortSwipesDuration
- Type:
number - Default:
300 - Short swipe maximum duration.
shortSwipesThreshold
- Type:
number - Default:
30 - Minimum distance in pixels to trigger slide change for short swipes.
swipeFriction
- Type:
boolean - Default:
false - Defines if
frictionis allowed when swiping. Doesn't work with short swipes or whenfollowSwipeisfalse.
See demo
swipeThreshold
- Type:
number - Default:
5 - Length in pixels that must be swiped to trigger swipe start.
swipeMinTime
- Type:
number - Default:
0 - Minimum time in milliseconds to trigger swipe move.
swipeInertiaDuration
- Type:
(distance: number) => number - Default:
(distance) => clamp(distance, 500, 2000) - Inertia duration.
swipeInertiaRatio
- Type:
number - Default:
0.3 - Inertia strength.
wheel
- Type:
boolean - Default:
false - Enable or disable mouse wheel control.
See demo
wheelSpeed
- Type:
number - Default:
1 - Speed factor for mouse wheel control.
wheelAxis
- Type:
'x' | 'y' | 'auto' - Default:
'auto' - Wheel axis. If
auto, the axis will be automatically detected depending ondirection.
See demo
followWheel
- Type:
boolean - Default:
true - If
false, disables smooth, continuous scrolling behavior from the mouse wheel and instead updates the snap position in discrete steps (like pagination).
See demo
wheelThrottle
- Type:
number| 'auto' - Default:
auto - Throttle wheel events, value in milliseconds. Works only if
followWheelis disabled.
stickOnWheelEnd
- Type:
boolean - Default:
true - Enable snapping on wheel stop. Works with
followWheelenabled.
See demo
stickOnWheelEndThreshold
- Type:
number - Default:
30 - Snapping threshold for
stickOnWheelEnd.
Accessors
All Module's accessors are available in this class.
activeIndex
Type: number
Active slide index
activeSlide
Type: SnapSlide
Active slide
axis
Type: "x" | "y"
Get axis name depending on direction
container
Type: HTMLElement
Get container
domSize
Type: number
Container size depending on direction (width or height)
eventsEmitter
Type: HTMLElement
Get events emitter
firstSlideSize
Type: number
Get first slide size
isEmpty
Type: boolean
Defines if there's nothing to animate
isTransitioning
Type: boolean
If transition in progress
scrollableSlides
Type: SnapSlide[]
Scrollable slides (which size is larger than the container)
slides
Type: SnapSlide[]
All slides
track.canLoop
Type: boolean
If can loop
track.current
Type: number
Gets/sets the current track value.
track.isEnd
Type: boolean
If the end has been reached
track.isInterpolated
Type: boolean
Whether the track is interpolated
track.isSlideScrolling
Type: boolean
Check if the active slide is larger than the container and is being scrolled
track.isStart
Type: boolean
If the start has been reached
track.loopCount
Type: number
Get loop count
track.loopedCurrent
Type: number
Get looped current value
track.max
Type: number
Get maximum track value
track.min
Type: number
Get minimum track value
track.offset
Type: number
Get track offset
track.progress
Type: number
Get track progress. From 0 to 1 if not loop. From -Infinity to Infinity if loop
track.target
Type: number
Gets/sets the target track value
track.influence
Type: number
Gets/sets current->target influence caused by swipe or wheel input.
Methods
All Module's methods are available in this class.
cancelTransition
Cancel sticky behavior
instance.cancelTransition();
next
Go to next slide
instance.next({ duration: 500, skip: 1 });
prev
Go to previous slide
instance.prev({ duration: 500, skip: 1 });
render
Force slides rendering
instance.render();
resize
Request resize (handled with debounce timeout)
instance.resize(true);
stick
Stick to the nearest magnet
instance.stick();
toCoord
Go to a definite coordinate
instance.toCoord(1365, { duration: 250 });
toSlide
Go to a slide by index
instance.toSlide(1, { direction: 'next', duration: 500 });
track.clampTarget
Clamp target value between min and max values
instance.track.clampTarget();
track.iterateTarget
Iterate track target value
instance.track.iterateTarget(50);
track.loopCoord
Loop a coordinate if can loop
instance.track.loop(1234);
track.lerp
Interpolate the current track value
instance.track.lerp(0.1);
track.set
Set current & target value instantly
instance.track.set(1350);
getNearestMagnet
Get nearest magnet to the current position
const magnet = instance.getNearestMagnet(1234);
Callbacks
All Module's callbacks are available in this class.
activeSlide
Triggered on active slide change
const destruct = instance.on('activeSlide', (slide) => console.log(slide.index));
// Cancel the callback
destruct();
rafPause
Triggered on requestAnimationFrame pause
const destruct = instance.on('rafPause', () => console.log('pause'));
// Cancel the callback
destruct();
rafPlay
Triggered on requestAnimationFrame play
const destruct = instance.on('rafPlay', () => console.log('play'));
// Cancel the callback
destruct();
reflow
Triggered on carousel calculation
const destruct = instance.on('reflow', () => console.log('reflow'));
// Cancel the callback
destruct();
### `resize`
Triggered on carousel resize
```ts
const destruct = instance.on('resize', () => console.log('resize'));
// Cancel the callback
destruct();
swipe
Triggered on swipe move
const destruct = instance.on('swipe', (coord) => console.log(coord));
// Cancel the callback
destruct();
swipeEnd
Triggered on swipe end
const destruct = instance.on('swipeEnd', (coord) => console.log(coord));
// Cancel the callback
destruct();
swipeStart
Triggered on swipe start
const destruct = instance.on('swipeStart', (coord) => console.log(coord));
// Cancel the callback
destruct();
timelineEnd
Triggered on timeline animation end
const destruct = instance.on('timelineEnd', () => console.log('end'));
// Cancel the callback
destruct();
timelineStart
Triggered on timeline animation start
const destruct = instance.on('timelineStart', () => console.log('start'));
// Cancel the callback
destruct();
timelineUpdate
Triggered on timeline animation progress update
const destruct = instance.on('timelineUpdate', ({ progress, eased }) => {
console.log(progress, eased);
});
// Cancel the callback
destruct();
update
Triggered on carousel coords update
const destruct = instance.on('update', () => console.log('update'));
// Cancel the callback
destruct();
wheel
Triggered on wheel event
const destruct = instance.on('wheel', (evt) => console.log(evt));
// Cancel the callback
destruct();
wheelEnd
Triggered on wheel events end
const destruct = instance.on('wheelEnd', () => console.log('end'));
// Cancel the callback
destruct();
wheelStart
Triggered on wheel events start
const destruct = instance.on('wheelStart', () => console.log('start'));
// Cancel the callback
destruct();
swipeInertiaStart
Triggered on swipe inertia start
const destruct = instance.on('swipeInertiaStart', () => console.log('start'));
// Cancel the callback
destruct();
swipeInertiaEnd
Triggered on swipe inertia end
const destruct = instance.on('swipeInertiaEnd', () => console.log('end'));
// Cancel the callback
destruct();
swipeInertiaCancel
Triggered on swipe inertia cancel
const destruct = instance.on('swipeInertiaCancel', () => console.log('cancel'));
// Cancel the callback
destruct();
swipeInertiaFail
Triggered on swipe inertia fail
const destruct = instance.on('swipeInertiaFail', () => console.log('fail'));
// Cancel the callback
destruct();
Parallax
Snap does not modify element styles by default, but it provides a set of optional parallax utilities for DOM elements.
Parallax effects are enabled using data- attributes.
Parallax Effects
Each parallax attribute maps directly to a corresponding CSS transform (or opacity):
data-snap-parallax-x->translateX()data-snap-parallax-y->translateY()data-snap-parallax-z->translateZ()data-snap-parallax-scale->scale()- value is added to1data-snap-parallax-scale-x->scaleX()- value is added to1data-snap-parallax-scale-y->scaleY()- value is added to1data-snap-parallax-skew->skew()data-snap-parallax-skew-x->skewX()data-snap-parallax-skew-y->skewY()data-snap-parallax-rotate->rotate()data-snap-parallax-rotate-x->rotateX()data-snap-parallax-rotate-y->rotateY()data-snap-parallax-rotate-z->rotateZ()data-snap-parallax-opacity->opacity- should contain negative values only, decreasing the current opacity.
All effect attributes accept numbers or any supported CSS unit.
Parallax Timeline
By default, parallax values are applied while the slide transition progress is between -1 and 1.
You can inspect slide progress in this demo.
To change the active range, use the data-snap-parallax-scope attribute:
- numeric range like
data-snap-parallax-scope="-2, 2" - infinite range like
data-snap-parallax-scope="-Infinity, Infinity"
The scope applies to all parallax effects inside a slide unless overridden per effect:
data-snap-parallax-y-scope="-2, 2"
Parallax Strength
Use data-snap-parallax-[effect]-influence to apply the effect only during dragging or wheeling.
The parallax value will smoothly increase or decrease based on interaction intensity, producing more "organic" motion.
Positive Values
data-snap-parallax-[effect]-abs forces the effect to use absolute (non-negative) values.
This is useful for properties like scale() where negative values are undesirable.
Parallax example
Organic Gap:
<div className="slide">
<div
className="wrap"
data-snap-parallax-x="-200%"
data-snap-parallax-x-scope="-Infinity, Infinity"
data-snap-parallax-x-influence
>
Slide Info
</div>
</div>
Scale:
<div className="slide">
<div
className="wrap"
data-snap-parallax-opacity="-0.33"
data-snap-parallax-opacity-scope="-4,4"
>
Slide Info
</div>
</div>