Requires GSAP. Hover or click to pause depending on settings. Multiple marquees are supported.
Pass an options object to gsapMarquee(selector, options)
or use the jQuery plugin API.
Option | Type | Default | Description |
---|---|---|---|
speed | number | 100 | Pixels per second. |
direction | string | 'ltr' | 'ltr' or 'rtl'. Controls movement direction. |
pauseOnHover | boolean | true | Pause when mouse enters the marquee. |
pauseOnClick | boolean | false | Toggle pause when marquee is clicked. |
variableSpeed | boolean | false | On hover, slow down instead of pausing. (pauseOnHover must be true to variableSpeed work.) |
startPaused | boolean | false | Start the marquee paused. |
responsive | boolean | true | Rebuild clones and widths on window resize. |
loop | boolean | true | Continuous looping (set false to run once). |
containerSelector | string | '.customMarquee' | Selector for the inner wrapper containing items. |
itemsSelector | string | '.marquee-item' | Selector for item nodes within the container. |
onComplete | function | null | Callback when a non-looping marquee completes a cycle. Receives cycle count. |
Each initialized marquee instance exposes the following methods:
Method | Args | Description |
---|---|---|
pause() | — | Pause animation. |
resume() | — | Resume animation. |
isPaused() | — | Returns true if paused. |
rebuild() | — | Recalculate widths and clones (call after DOM/content changes). |
reverse() | — | Toggle direction between ltr and rtl . |
destroy() | — | Cleanup event listeners and stop ticker for that instance. |
$('#yourMarquee').gsapMarquee({
speed: 100, // pixels per second
direction: "ltr", // "ltr" or "rtl"
pauseOnHover: true, // pause on hover
pauseOnClick: false, // pause/resume on click
variableSpeed: false, // on hover, slow instead of pause
startPaused: false, // start paused
responsive: true, // auto recalc on resize
loop: true, // infinite loop
containerSelector: '.marqueeInner',
itemsSelector: '.marquee-item',
onComplete: function(cycle){ // callback each loop
console.log("Cycle:", cycle);
}
});
let instance = gsapMarquee('#m1', {
speed: 140,
direction: 'ltr',
pauseOnHover: true,
pauseOnClick: false,
variableSpeed: false,
startPaused: false,
responsive: true,
loop: true,
containerSelector: '.marqueeInner',
itemsSelector: '.marquee-item',
onComplete: function(cycle) { console.log('cycle', cycle); }
});
let instance = $('#yourMarquee').gsapMarquee();
// Pause / Resume
instance.pause();
instance.resume();
// Reverse direction at runtime
instance.reverse();
// Rebuild (recalculate widths, clones)
instance.rebuild();
// Destroy (cleanup)
instance.destroy();
Important: Always ensure images are fully loaded before initializing image marquees — use imagesLoaded
and a short setTimeout
to guarantee correct widths.
imagesLoaded('#imageMarquee', function() {
setTimeout(function() {
$('#imageMarquee').gsapMarquee({
speed: 100,
containerSelector: '.marqueeInner',
itemsSelector: '.marquee-img-item'
});
}, 0);
});
will-change: transform
on .marqueeInner
for smoother animation and better compositing performance.imagesLoaded
or font loading APIs, then call a short setTimeout
and initialize to ensure correct widths.focus
so keyboard users can interact safely.rebuild()
so widths and clones are recalculated.Copy and paste these small helpers into your project where appropriate.
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
// honor reduced motion: start paused or reduce speed
opts = opts || {};
opts.startPaused = true; // or opts.speed = 0
}
let instance = gsapMarquee('#m', opts);
// Pause when any item receives keyboard focus
instance.items.forEach(function(el){
el.addEventListener('focus', function(){ instance.pause(); }, true);
el.addEventListener('blur', function(){ instance.resume(); }, true);
});
// Instance must be in scope
let instance = gsapMarquee('#m1', {speed: 140});
// After images or content change, give layout a moment then rebuild
setTimeout(function(){
instance.rebuild();
}, 50);