
gpuslider is a dependency-free JavaScript carousel library for image and video sliders with GPU-rendered shader effects. Slides can stretch, bend, split into color channels, or switch through liquid and glitch transitions.
It keeps real HTML slides on the page and falls back to browser-rendered media when GPU rendering is unavailable. A CDN entry initializes sliders from HTML attributes, and modular JavaScript imports are available for custom projects.
Features
- A 4.7 KB gzipped core with optional plugins.
- 20+ GPU effects driven by motion, position, and pointer input.
- 20+ transitions for stacked slides and multi-pane galleries.
- Mouse dragging, touch swiping, wheel input, and keyboard navigation.
- Horizontal and vertical movement, looping, and free scrolling.
- Optional autoplay, thumbnail navigation, pagination, and lightbox.
- Responsive sizing and spacing through CSS custom properties.
- Loading-screen and adaptive canvas-quality plugins.
- TypeScript declarations and React components for server-rendered pages.
- Reduced-motion behavior and ARIA-aware navigation controls.
- Custom GLSL effects shared by WebGPU and WebGL 2 renderers.
How To Use It
Installation
Load the stylesheet and the module-based auto initializer from a CDN. This initializes elements with data-gs and loads the GPU renderer only when required.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gpuslider@1/dist/style.css"> <script type="module" src="https://cdn.jsdelivr.net/npm/gpuslider@1/dist/auto.js"></script>
Or install the package via npm.
npm install gpuslider
For a lightbox or loading screen, import the extra stylesheet for the feature that is enabled. A standard carousel only needs style.css.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gpuslider@1/dist/lightbox.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gpuslider@1/dist/loading.css">
Basic Usage
The CDN method accepts slider options as JSON in data-gs. The data-gs-canvas attribute activates the GPU canvas and selects its effects.
<div class="gs" aria-label="Photo gallery"
data-gs='{"loop":true}'
data-gs-canvas="stretch waves">
<div class="gs-track">
<div class="gs-slide">
<img class="gs-media" src="photo-1.jpg" alt="Mountain lake">
</div>
<div class="gs-slide">
<img class="gs-media" src="photo-2.jpg" alt="Coastal cliffs">
</div>
<div class="gs-slide">
<img class="gs-media" src="photo-3.jpg" alt="Forest trail">
</div>
<div class="gs-slide">
<img class="gs-media" src="photo-4.jpg" alt="Sunset beach">
</div>
<div class="gs-slide">
<img class="gs-media" src="photo-5.jpg" alt="Desert dunes">
</div>
</div>
<button data-gs-prev aria-label="Previous slide">‹</button>
<button data-gs-next aria-label="Next slide">›</button>
<div data-gs-dots></div>
</div>
Give the slides a defined height or aspect ratio to reserve space before media loading. The number of visible slides and the gap between them come from CSS.
.gs {
--gs-per-view: 1.2;
--gs-gap: 12px;
}
.gs-slide { aspect-ratio: 16 / 9; }
@media (min-width: 960px) {
.gs { --gs-per-view: 3; }
}
Initialize With JavaScript
Use the core entry when you want to import only the features your carousel needs. The canvas plugin accepts an ordered array of shader effects.
import { createSlider } from 'gpuslider';
import { controls, keyboard } from 'gpuslider/plugins';
import { canvas } from 'gpuslider/canvas';
import { stretch, split } from 'gpuslider/effects';
import 'gpuslider/style.css';
const slider = createSlider(document.querySelector('.gs'), {
loop: true,
plugins: [
controls(),
keyboard(),
canvas({ effects: [stretch(), split()] })
]
});
The gpuslider/full entry includes controls, keyboard and wheel input, autoplay, auto height, and stacked layouts through additional options. For mode: 'stack', place gs-stack on the HTML root before JavaScript loads. Use the stacked markup in the next example.
import { createSlider } from 'gpuslider/full';
import { canvas } from 'gpuslider/canvas';
import { liquid } from 'gpuslider/effects';
import 'gpuslider/style.css';
createSlider(document.querySelector('.gs-stack'), {
mode: 'stack',
loop: true,
autoplay: 4000,
plugins: [canvas({ effects: [liquid()] })]
});
Create Shader Transitions
Transitions operate on stacked slides. Reserve slide space with CSS or image dimensions before initialization. A stacked slider displays its first slide when JavaScript is disabled; the other slides are not available through native scrolling.
<div class="gs gs-stack" aria-label="Featured photos">
<div class="gs-track">
<div class="gs-slide"><img class="gs-media" src="one.jpg" alt="Photo one"></div>
<div class="gs-slide"><img class="gs-media" src="two.jpg" alt="Photo two"></div>
<div class="gs-slide"><img class="gs-media" src="three.jpg" alt="Photo three"></div>
</div>
</div>
For a modular setup, use stack() and a transition such as burn(). A stack fades between slides when no GPU transition is active.
import { createSlider } from 'gpuslider';
import { stack, controls } from 'gpuslider/plugins';
import { canvas } from 'gpuslider/canvas';
import { burn } from 'gpuslider/effects';
import 'gpuslider/style.css';
createSlider(document.querySelector('.gs-stack'), {
loop: true,
plugins: [stack(), controls(), canvas({ effects: [burn()] })]
});
Include Video Slides
The canvas handles images and videos. For automatic inline video playback, use muted and playsinline. The videos() plugin starts and stops media as its slide enters or leaves view. This example assumes the video slide is inside the existing .gs-track.
<div class="gs-slide"> <video class="gs-media" src="demo.mp4" muted playsinline loop preload="none"></video> </div>
import { createSlider } from 'gpuslider';
import { videos } from 'gpuslider/plugins';
import { canvas } from 'gpuslider/canvas';
import 'gpuslider/style.css';
createSlider(document.querySelector('.gs'), {
plugins: [videos(), canvas()]
});
Enable a Lightbox
lightbox() opens images when slides are clicked. An image can specify a larger source through data-gs-full, and open(index) also opens the lightbox programmatically.
import { createSlider } from 'gpuslider';
import { canvas } from 'gpuslider/canvas';
import { lightbox } from 'gpuslider/lightbox';
import 'gpuslider/style.css';
import 'gpuslider/lightbox.css';
const slider = createSlider(document.querySelector('.gs'), {
plugins: [canvas(), lightbox()]
});
slider.plugins.lightbox.open(0);
// Later: slider.plugins.lightbox.close();
React Integration
React projects can import <Slider> and <Slide> from gpuslider/react. The package works with React 18+ and exposes the core slider options and canvas plugins.
import { Slider, Slide } from 'gpuslider/react';
import { controls, stack } from 'gpuslider/plugins';
import { canvas } from 'gpuslider/canvas';
import { liquid } from 'gpuslider/effects';
import 'gpuslider/style.css';
export function Gallery({ photos }) {
return (
<Slider
className="gs-stack"
loop
plugins={[controls(), stack(), canvas({ effects: [liquid()] })]}
aria-label="Photo gallery"
>
{photos.map(photo => (
<Slide key={photo.src}>
<img className="gs-media" src={photo.src} alt={photo.alt} />
</Slide>
))}
</Slider>
);
}
Server Rendering and Plugin Updates
gpuslider/react is a client component entry for Next.js. The server-rendered markup retains native HTML slides. Load the stylesheet during server rendering and reserve slide dimensions with CSS to avoid a layout shift. The plugins prop is read at creation; use remake when a change requires a new plugin configuration.
Core Configuration Options
| Option | Default and behavior |
|---|---|
perView | CSS value; number of visible slides, including fractions, or 'auto' for intrinsic widths. |
gap | CSS value; space between slides in pixels. |
axis | 'x'; use 'y' for a vertical slider. |
loop | false; continuous cycling requires more slides than fit in view, plus one. |
align | 'start'; also accepts 'center' and 'end'. |
group | 1; number of slides advanced per step. |
contain | true; avoids empty space at the ends. |
free | false; lets dragging settle between snap positions when enabled. |
duration | 600; slide movement duration in milliseconds. |
ease | Optional easing function from 0 to 1 over duration, in place of the snapping spring. |
start | 0; initial slide position. |
drag | true; enables pointer dragging. |
on | Optional object of event listeners, keyed by event name. |
plugins | []; plugin instances used by this slider. |
Additional Options in gpuslider/full and data-gs
These options enable built-in plugins automatically in the full and declarative entries.
| Option | Default and behavior |
|---|---|
mode | 'row'; 'stack' enables stacked slide transitions. |
autoHeight | false; adjusts slider height to the visible media. |
autoplay | 0; playback interval in milliseconds, or 0 to disable. |
keyboard | true; enables keyboard navigation. |
wheel | true; enables wheel or trackpad navigation. |
prev | Optional navigation element, collection, or selector. |
next | Optional navigation element, collection, or selector. |
pause | Optional autoplay pause control element, collection, or selector. |
dots | Optional pagination element, collection, or selector. |
Built-in Plugins
Core plugins are imported from gpuslider/plugins. Canvas and lightbox use their own entry points. Plugin parameters are included here as part of the configuration reference.
| Plugin | Purpose and parameters |
|---|---|
controls({ prev, next, dots }) | Connects previous/next controls, pagination, and buttons with data-gs-to. |
keyboard() | Enables Arrow, Home, and End key navigation and a focusable slider. |
wheel() | Navigates with the mouse wheel or trackpad. |
autoplay(3500) | Advances on a timer; also accepts { delay, hover, left }. hover: false disables pointer-hover pausing. |
marquee({ speed, hover, scroll, turn }) | Continuous ticker; controls speed, hover slowdown, scrolling response, and reverse direction on upward scrolling. Requires loop: true. |
thumbs(other) | Uses the slides of another slider as thumbnails. |
videos() | Manages playback for video slides in view. |
autoHeight() | Tracks the height of visible slides. |
stack() | Stacks slides for canvas transitions. |
panes({ order, stagger }) | Transitions individual slide positions. order: 'start', 'end', 'center', or 'random'; stagger: 0 to 1. |
progress() | Writes slide-progress variables for CSS animations. |
loading({ screen, min, timeout, also }) | Manages media loading and optional loading UI. |
quality({ late, frames, steps }) | Reduces pixel density after slow frames. Defaults: late: 25 ms, frames: 3, and steps: [1, 0.75]. |
canvas({ effects, eager, density, maxSize, perspective, stage, layer }) | Adds GPU rendering and shader effects. |
lightbox({ punch }) | Opens slide media in an overlay and optionally carries opening speed into shader effects. |
Plugin Methods and Properties
| Plugin member | Usage |
|---|---|
slider.plugins.autoplay.play() | Resumes autoplay. |
slider.plugins.autoplay.pause() | Pauses autoplay. |
slider.plugins.autoplay.paused | Current paused status. |
slider.plugins.quality.density | Current canvas pixel density. |
slider.plugins.loading.state | Loading counts and progress. |
slider.plugins.loading.done | Whether loading has finished. |
slider.plugins.loading.ready | Promise resolved when loading finishes. |
slider.plugins.lightbox.open(index) | Opens a selected image. |
slider.plugins.lightbox.close() | Closes the lightbox. |
slider.plugins.canvas.draw(hook) | Registers a canvas drawing hook and returns its cleanup function. |
slider.plugins.panes.order | Transition order, writable at runtime. |
slider.plugins.hit.at(x, y) | Finds the displayed slide at a page coordinate. |
slider.plugins.hit.where(index) | Gets the displayed position around a slide. |
Canvas Configuration
canvas() selects WebGPU or WebGL 2 automatically. Set layer when a project needs a particular backend. The canvas begins loading on user interaction or when an active effect requires it; eager: true initializes it immediately.
| Option | Description |
|---|---|
effects | Array of shader effects, applied in the declared order. |
eager | Initializes the canvas immediately when true. |
density | Device-pixel density for canvas rendering. |
maxSize | Maximum canvas texture size. |
perspective | Perspective distance for depth-based effects. |
stage | Positioned parent element that defines a larger canvas drawing area. |
layer | 'gpu' or 'gl' to select a rendering backend. |
Direct Renderer Imports
gpuslider/gpu exports the WebGPU renderer and its effects. gpuslider/gl exports the WebGL 2 renderer and its effects. Explicit renderer imports do not select a second backend when the chosen one is unavailable. For layout effects, hit() keeps clicking aligned with GPU-drawn slide positions.
import { gl, hit, coverflow } from 'gpuslider/gl';
import { createSlider } from 'gpuslider';
import 'gpuslider/style.css';
const effects = [coverflow()];
createSlider(document.querySelector('.gs'), {
align: 'center',
plugins: [gl({ effects }), hit({ effects })]
});
Shader Effects
Effects are imported from gpuslider/effects and passed to the canvas plugin. Each function accepts an optional settings object. Only their public parameter names are included below.
| Effect | Behavior and parameters |
|---|---|
stretch({ amount }) | Stretches media as sliding speed changes. |
split({ amount }) | Separates image color channels during movement. |
parallax({ amount, zoom }) | Offsets media inside its slide. |
bend({ amount, speed }) | Curves the moving slide row. |
magnify({ size, strength }) | Pointer-following magnification lens. |
cells({ size, zoom, reach }) | Pointer-driven magnification grid. |
spotlight({ size, dim }) | Dims the image outside the pointer area. |
reveal({ size }) | Reveals color around the pointer. |
glass({ size, lines, amount }) | Fluted glass distortion near the pointer. |
pixels({ size, cells }) | Enlarged pixels around the pointer. |
ascii({ size, cells }) | Converts media near the pointer into character-like shapes. |
tilt({ angle }) | Tilts a slide toward the pointer. |
waves({ size, amount, speed }) | Animated circular waves near the pointer. |
smear({ size, amount }) | Drags media along pointer movement. |
shift({ size, amount }) | Splits color channels with pointer velocity. |
jelly({ amount, across }) | Elastic slide distortion during movement. |
slab({ edge, bend, spread, shine, zoom }) | Thick glass refraction, bevel, and lighting. |
loupe({ size, strength }) | Lens applied across the entire slider, including the gaps. |
Layout Effects
Layout effects change where the GPU draws each slide. Use padding when cards extend outside their original positions. Hit testing follows the displayed image when the canvas manages a layout effect.
| Layout effect | Behavior and parameters |
|---|---|
coverflow({ angle, depth, range }) | Rotates surrounding slides away from the active one. |
pile({ offset, turn }) | Overlapping cards that move out from the top. |
fan({ angle, radius }) | Fan or circular card arrangement. |
wave({ height, length, slope }) | Moves the row along a wave. |
unweave({ amount, threads, start, gap, split, lift }) | Disperses slides into strips near the edge of the view. |
dome({ amount, centre, size }) | Creates a curved arrangement with smaller edge slides. |
Transition Effects
Transitions apply to stack() and panes() layouts. Individual transitions are imported from gpuslider/effects.
liquid(),ripple(),glitch(),burn(),pixelate(),swirl().lens(),fluted(),warp(),zoom(),mosaic(),blocks().fold(),signal(),push(),chroma(),kaleido(),displace().datamosh(),wind(),distance(),glyphs(),weave(),lightning().
Transition Helpers
| Helper | Description |
|---|---|
choose([effectA, effectB]) | Creates a selectable group of transitions; pick(index) selects a transition for subsequent moves. |
sweep(transition) | Runs a transition across all visible panes as one continuous image. Use with panes({ stagger: 0 }). |
edges(transition, { from, to }) | Runs an effect where ordinary row slides enter and leave the viewport. from and to are measured in slide widths. |
glyphs({ cells, tint }) | Character-based scramble; cells defines vertical grid rows and tint ranges from 0 to 1. |
weave({ threads, tint }) | Woven transition; threads defines density and tint ranges from 0 to 1. |
lightning({ bolts, tint }) | Electric strike transition; bolts sets strike count and tint ranges from 0 to 1. |
CSS Variables and Public Classes
Set --gs-per-view, --gs-gap, and --gs-focus on .gs. The progress() plugin writes per-slide values during motion, and loading() exposes loading-screen state.
| CSS variable | Purpose |
|---|---|
--gs-per-view | Number of slides in view; fractions are valid. |
--gs-gap | Gap between slides. |
--gs-focus | Media focal point, similar to object-position. |
--gs-p | Signed slide distance from its active position, emitted by progress(). |
--gs-away | Absolute slide distance, emitted by progress(). |
--gs-share | Portion of a slide currently visible, emitted by progress(). |
--gs-loading-back | Loading-screen background. |
--gs-loading-color | Loading-screen foreground color. |
--gs-loaded | Loading progress from 0 to 1. |
| Class | Usage |
|---|---|
.gs | Slider root. |
.gs-track | Container holding all slides. |
.gs-slide | Individual slide. |
.gs-media | Media element used for canvas rendering. |
.gs-content | HTML content over slide media. |
.gs-stack | Predefined stacked layout for transitions. |
.gs-loading | Custom loading-screen element. |
.gs-loaded | Loading finished state. |
.gs-is-loading | Slider loading state. |
Styling Notes
The canvas reads border-radius and corner-shape from the page. Shader effects apply to images and videos, not text, links, or buttons in .gs-content. For axis: 'y', set an explicit slider height. Reduced-motion preferences make slide moves immediate and disable speed-driven and pointer-driven effects.
HTML Data Attributes
The CDN auto initializer uses these declarative attributes. Controls can sit inside a slider or in another element associated with it through data-gs-for.
| Attribute | Function |
|---|---|
data-gs | Activates automatic initialization; accepts a JSON options object. |
data-gs-canvas | Activates automatic canvas rendering with space-delimited effect names or JSON effect options. |
data-gs-gpu | Requests the WebGPU renderer with the specified effects. |
data-gs-gl | Requests the WebGL 2 renderer with the specified effects. |
data-gs-lightbox | Activates a lightbox; also requires lightbox.css. |
data-gs-loading | Activates loading UI; also requires loading.css. |
data-gs-prev | Previous-slide control. |
data-gs-next | Next-slide control. |
data-gs-pause | Autoplay pause control. |
data-gs-dots | Pagination container. |
data-gs-to | Button that navigates to a specific snap index. |
data-gs-for | Associates controls outside the slider with its root element ID. |
data-gs-full | Larger image URL for the lightbox. |
data-gs-loaded | Displays numeric loading progress in a custom screen. |
Dynamic Sliders and Declarative Events
For dynamically inserted declarative sliders, the auto() function initializes new elements and sliders.get(element) retrieves their instances from gpuslider/auto. The gs:ready DOM event bubbles when the slider is initialized and provides the instance in event.detail.
import { auto, sliders } from 'gpuslider/auto';
document.addEventListener('gs:ready', (event) => {
console.log('Slider ready:', event.detail);
});
auto();
const instance = sliders.get(document.querySelector('.gs'));
Slider API Methods and Properties
createSlider(element, options) returns the instance. Its first parameter is the slider root element and its second parameter is the core configuration object. These methods and properties apply to the returned slider unless marked as plugin-specific.
| Method or property | Function |
|---|---|
next() | Moves to the next snap. |
prev() | Moves to the previous snap. |
to(index, { instant }) | Goes to a snap index; instant skips the animation. |
toSlide(index, { instant }) | Goes to the snap containing a given slide. |
count() | Returns the number of snap positions. |
visible() | Returns indexes of visible slides. |
set(options) | Updates options on the existing slider. |
update() | Recalculates layout after changes the slider cannot detect. |
use(plugin) | Registers another plugin on the existing slider. |
on(name, fn) | Subscribes to an event and returns an unsubscribe function. |
once(name, fn) | Subscribes once and returns an unsubscribe function. |
off(name, fn) | Removes an event listener. |
emit(name, detail) | Emits a custom event with a value. |
grab() | Begins a programmatic drag. |
drag(position) | Updates a programmatic drag. |
release(velocity) | Ends a programmatic drag with velocity. |
shift(by, push) | Offsets the current and destination positions; push contributes movement speed. |
wake() | Requests a rendering frame. |
layout() | Returns measured slider layout for plugins. |
destroy() | Destroys the instance and restores page markup behavior. |
index | Current snap index. |
previous | Previous snap index. |
canNext, canPrev | Whether navigation is possible in either direction. |
progress | Position through the slides from 0 to 1. |
resting | Indicates that movement has stopped. |
plugins | Plugin instances keyed by their plugin names. |
root, track, slides | Root element, track, and slide elements. |
options | Current slider configuration. |
motion | Motion state for plugins. |
view | Per-frame view state for plugins. |
win | Slider window state for plugins. |
signal | Abort signal that ends with the slider instance. |
slider.on('change', (index, instance) => {
console.log('Current snap:', index);
});
slider.to(2);
slider.update();
Events
The standard event callback signature is (detail, slider). The wildcard listener receives (eventName, detail, slider). Plugin events fire only when their corresponding features are active.
| Event | When it fires or what it returns |
|---|---|
ready | Slider initialization is complete; detail is the slider. |
change | Destination snap changes; detail is the index. |
settle | Slider comes to rest at a snap; detail is the index. |
visible | Visible slide indexes change; detail is the index array. |
dragstart | Dragging starts; detail is motion state. |
dragend | Drag ends; detail includes release velocity. |
click | A slide receives a click; detail is { index, event }. |
measure | Layout is measured; detail is the layout. |
slides | Slides enter or leave the track; detail is the slide collection. |
frame | A motion frame is drawn; detail is the view. |
destroy | The slider is destroyed; detail is the slider. |
autoplay:play | Autoplay starts or resumes. |
autoplay:pause | Autoplay pauses. |
autoplay:run | Slide timer starts; detail is { delay, left }. |
autoplay:wait | Slide timer ends early or stops waiting. |
marquee:play | Continuous ticker starts. |
marquee:pause | Continuous ticker pauses. |
canvas:ready | Canvas selects a backend; 'gpu' or 'gl'. |
gpu:on | WebGPU canvas takes over drawing. |
gpu:off | WebGPU returns drawing to page media. |
gl:on | WebGL canvas takes over drawing. |
gl:off | WebGL returns drawing to page media. |
loading:start | Media loading begins; detail includes total. |
loading:progress | Media loading advances; detail includes loaded, failed, total, progress, and media. |
loading:done | Loading completes; detail includes loaded, failed, total, time, and late. |
lightbox:open | Lightbox opens; detail is slide index. |
lightbox:close | Lightbox closes; detail is slide index. |
quality:lower | Canvas density decreases; detail is its new pixel density. |
React Props and Hooks
The React component exposes the core slider options as props. It also has these component-specific props and hooks.
| Prop or hook | Function |
|---|---|
loop, align, axis, free, duration, and other core options | Updates the live slider when changed. |
plugins | Plugins installed when the slider is created. |
remake | Dependency array that recreates the slider when relevant plugin values change. |
index | Updates the chosen snap when the prop changes. |
onChange(index, slider) | Called when the snap changes. |
onSettle(index, slider) | Called when movement settles. |
on | Object mapping other slider event names to callbacks. |
onSlider | Receives the slider instance on creation and null on cleanup. |
around | Extra React elements inside the slider beside the slide track. |
as | Element type for <Slider> or <Slide>, default div. |
className, style, id, aria-label, other DOM attributes | Applied to the rendered slider element. |
useSliderContext() | Retrieves slider context inside a <Slider> child. |
useSlider(options, dependencies) | Hook returning [ref, slider] for custom markup; dependency changes remake the slider. |
Loading Plugin Options and State
The loading plugin waits for images and the first frame of each video. Import gpuslider/loading.css for its default screen or use a .gs-loading element of your own. screen: false turns off the overlay but retains progress events. A custom screen present in the initial HTML needs a <noscript> fallback to hide it when scripts are disabled. Failed media count toward completion, and loading() starts images marked loading="lazy" immediately. This behavior suits first-screen galleries and full-page sliders.
| Option | Default and behavior |
|---|---|
screen | Optional screen element, or false to disable the screen. |
min | 0 milliseconds minimum display time. |
timeout | 10000 milliseconds before completion with late: true; 0 waits indefinitely. |
also | []; extra promises to include in loading progress. |
Extending gpuslider
Custom plugins are functions that receive a slider instance and return an object. They can register event listeners, modify the measured layout, or request additional animation frames. Plugin registration uses plugins during initialization or slider.use(plugin) later.
| Plugin member | Purpose |
|---|---|
name | Plugin identifier used in slider.plugins. |
layout(measured) | Runs before the measured layout is used and can modify it. |
measure(view) | Runs after a layout measurement. |
slides() | Reacts when the slide collection changes. |
frame(view, dt, now) | Runs on each animation frame. |
busy() | Returns true when the plugin needs more frames. |
destroy() | Cleans up when the slider is destroyed. |
| Other returned members | Exposed by the plugin under its own name. |
Plugin View State
A plugin reads view.places[index] for x (pixels), p (relative slide position), share (visible portion), and visible (visibility state).
Custom GPU effects accept params, head, vertex, uv, color, transition, post, place, and animated. The shader hooks have distinct purposes:
| Effect hook | Purpose |
|---|---|
params | Numeric or 1-to-4-value array uniforms. |
head | Shared GLSL declarations. |
vertex | vec3(vec3 p, vec2 uv); moves a slide’s mesh in 3D. |
uv | vec2(vec2 uv); changes texture sampling coordinates. |
color | vec4(vec4 color, vec2 uv); changes media color. |
transition | GLSL body of vec4 transition(vec2 uv) between stack images. |
post | vec4(vec4 color, vec2 uv); operates across the composite canvas. |
place(p, about) | JavaScript hit-test placement corresponding to changed GPU layout. |
animated | true for autonomous animation or 'pointer' for pointer-driven frames. |
Shader Uniforms
The available shader uniforms are uProgress, uVelocity, uPointer, uPointerSpeed, uPointerIn, uTime, uSize, uView, and uQuad. The uv and color hooks can also read uRadius.
Shader Compatibility
The GPU translation supports a restricted GLSL subset. Avoid struct types, GLSL #define, array declarations, out or inout parameters, and partial vector assignments when an effect needs WebGPU rendering. An effect that fails compilation returns the affected slider to HTML media.
Canvas Draw Hook
slider.plugins.canvas.draw(hook) receives (index, quad) before drawing each slide and returns a function that removes the hook. It lets custom code adjust placement, size, visibility, and effects for GPU-drawn slides.
| Quad field | Description |
|---|---|
x, y, w, h | Draw position and dimensions in pixels. |
p | Relative position in slides from the resting position. |
radius | Corner radius in pixels. |
dim | Color multiplier from 0 to 1. |
fx | Effect intensity from 0 to 1. |
speed | Additional motion speed used by shader effects. |
clip | Whether rendering is clipped to the view. |
top | Draw priority above other slides. |
a | Image placement/crop data; null prevents image drawing. |
Alternatives & Related Resources
- Touch-enabled Carousel With RGB Split And Liquid Distortion Effects – rgbKineticSlider
- Cool Slideshow JavaScript Library With WebGL Based Effects – GLSlideshow.js
- Fast, Extensible, Touch-enabled Carousel & Slider JS Library – Smooothy
- Native Scroll Carousel Web Component with Drag – Blossom Carousel
FAQs
Q: Why do remote images appear in HTML but not in the GPU effects?
A: Cross-origin images and videos require CORS response headers and a crossorigin attribute on each media element. A media file that the GPU cannot use as a texture can display through the original HTML element.
Q: Why does the first shader effect appear only after I interact with the slider?
A: The canvas normally initializes when the first interaction or motion requires it. Use canvas({ eager: true }) when the gallery must initialize its GPU canvas immediately.
Q: Can a canvas drawing hook move buttons and links inside a slide?
A: No. draw() changes the GPU rendering position, but interactive HTML stays where the page lays it out. Use a layout effect with a matching place() hook and hit() for accurate slide-level hit testing.







