Demos
Simple Marqueeβ
A basic example with scrollable text in a custom marquee element.
HTML
<div class="fullpage-center">
<div id="marquee">Breaking Newsπ₯</div>
</div>
JavaScript
import {
Marquee
} from "vevet";
new Marquee({
container: document.getElementById("marquee")
});
Vertical Marqueeβ
Vertical scrolling with direction: 'vertical'.
HTML
<div class="fullpage-center">
<div id="marquee">
<span>Vertical Marquee</span>
<span>Is so easy</span>
</div>
</div>
CSS
#marquee {
white-space: nowrap;
min-height: 100svh;
}
JavaScript
import {
Marquee
} from "vevet";
new Marquee({
container: document.getElementById("marquee"),
direction: "vertical",
gap: "5svh"
});
Pause on Hoverβ
Use pauseOnHover: true to pause the animation while the element is hovered.
HTML
<div class="fullpage-center">
<div id="marquee">Pause on Hover </div>
</div>
JavaScript
import {
Marquee
} from "vevet";
new Marquee({
container: document.getElementById("marquee"),
pauseOnHover: true
});
Reverse Marqueeβ
The speed prop accepts negative values for reverse motion. Example: speed: -1.
HTML
<div class="fullpage-center">
<div id="marquee">This is a reverse marqueeπ₯</div>
</div>
JavaScript
import {
Marquee
} from "vevet";
new Marquee({
container: document.getElementById("marquee"),
speed: -1
});
Controllable Marqueeβ
Programmatic control examples:
marquee.updateProps({ enabled: true, speed: 1.25 })β toggle playback and change speedmarquee.render(10)β scroll contents manually by 10px
HTML
<div class="fullpage-center">
<div id="marquee">You can control me π </div>
<div class="double-grid">
<button type="button" class="btn" id="play">Play</button>
<button type="button" class="btn" id="pause">Pause</button>
</div>
<div class="double-grid">
<button type="button" class="btn" id="faster">Faster</button>
<button type="button" class="btn" id="slower">Slower</button>
</div>
<div class="double-grid">
<button type="button" class="btn" id="render">Render</button>
<button type="button" class="btn" id="render10">Render 10</button>
</div>
</div>
JavaScript
import {
Marquee
} from "vevet";
const instance = new Marquee({
container: document.getElementById("marquee")
});
const play = document.getElementById("play");
play.addEventListener("click", () => {
instance.updateProps({
enabled: true
});
});
const pause = document.getElementById("pause");
pause.addEventListener("click", () => {
instance.updateProps({
enabled: false
});
});
const faster = document.getElementById("faster");
faster.addEventListener("click", () => {
instance.updateProps({
speed: instance.props.speed * 1.5
});
});
const slower = document.getElementById("slower");
slower.addEventListener("click", () => {
instance.updateProps({
speed: instance.props.speed / 1.5
});
});
const render = document.getElementById("render");
render.addEventListener("click", () => {
instance.render(1);
});
const render10 = document.getElementById("render10");
render10.addEventListener("click", () => {
instance.render(10);
});
With CSS unitsβ
Both gap and speed accept CSS length strings such as px, rem, vw, vh, and svh.
Examples:
gap: "10vw"speed: "0.1vw"
HTML
<div class="fullpage-center">
<div id="marquee">The gap & speed are set with css units</div>
</div>
JavaScript
import {
Marquee
} from "vevet";
new Marquee({
container: document.getElementById("marquee"),
gap: "10vw",
speed: "0.1vw"
});
With speed adjustmentβ
Linear requestAnimationFrame animations can look faster on high-refresh displays (120 Hz and above).
Marquee compensates by adjusting speed based on the user's FPS. Enabled by default: adjustSpeed: true.
This keeps motion consistent across 60 Hz and 120+ Hz displays.
HTML
<div class="fullpage-center">
<div id="marquee">The speed is adjustable depending on users's fps. </div>
<div class="double-grid">
<button type="button" class="btn" id="enable">Enable</button>
<button type="button" class="btn" id="disable">Disable</button>
</div>
</div>
JavaScript
import {
Marquee
} from "vevet";
const instance = new Marquee({
container: document.getElementById("marquee")
});
const enable = document.getElementById("enable");
enable.addEventListener("click", () => {
instance.updateProps({
adjustSpeed: true
});
});
const disable = document.getElementById("disable");
disable.addEventListener("click", () => {
instance.updateProps({
adjustSpeed: false
});
});
Adaptive Marqueeβ
Like any other Vevet component, Marquee supports viewport- and device-based customization via responsive props.
In this demo, speed and gap change at responsive breakpoints.
HTML
<div class="fullpage-center">
<div id="marquee">Resize the window to see changes</div>
</div>
JavaScript
import {
Marquee,
Responsive
} from "vevet";
const instance = new Marquee({
container: document.getElementById("marquee"),
gap: 20
});
new Responsive(instance, [{
at: "@media (min-width: 350px)",
props: {
speed: 4
}
},
{
at: "@media (min-width: 768px)",
props: {
speed: -4
}
},
{
at: "@media (min-width: 1000px)",
props: {
gap: 100
}
}
]);
Draggable Marqueeβ
A combination of Swipe and Marquee.
Shows how to control a marquee with drag/swipe gestures.
HTML
<div class="fullpage-center">
<div id="marquee">
<img src="https://picsum.photos/id/199/300/200" width="300" height="200" alt="">
<img src="https://picsum.photos/id/201/300/200" width="300" height="200" alt="">
<img src="https://picsum.photos/id/203/300/200" width="300" height="200" alt="">
<img src="https://picsum.photos/id/206/300/200" width="300" height="200" alt="">
</div>
</div>
CSS
#marquee {
img {
width: 300px !important;
min-width: 30vw;
height: auto;
border-radius: 1rem;
}
}
JavaScript
import {
Marquee,
Swipe
} from "vevet";
const container = document.getElementById("marquee");
const marquee = new Marquee({
container,
speed: "0.25vw",
gap: "2vw"
});
const swipe = new Swipe({
container,
grabCursor: true,
inertia: true,
onMove: ({
step
}) => marquee.render(-step.x),
onStart: () => marquee.updateProps({
enabled: false
}),
onEnd: ({
diff
}) => {
marquee.updateProps({
enabled: true,
speed: diff.x > 0 ? "-0.25vw" : "0.25vw"
});
}
});
Scrollable Marqueeβ
Combines Marquee with ScrollProgress.
The marquee position follows the section's scroll progress.
HTML
<div class="fullpage-center">
<div class="gap">Scroll The Page</div>
<div class="container">
<div id="marquee">
<img src="https://picsum.photos/id/199/300/200" width="300" height="200" alt="">
<img src="https://picsum.photos/id/201/300/200" width="300" height="200" alt="">
<img src="https://picsum.photos/id/203/300/200" width="300" height="200" alt="">
<img src="https://picsum.photos/id/206/300/200" width="300" height="200" alt="">
</div>
</div>
<div class="gap">Scroll The Page</div>
</div>
CSS
.gap {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: 100%;
height: 50vh;
text-align: center;
}
.container {
margin: 10rem 0;
width: 100%;
}
#marquee {
img {
width: 200px !important;
min-width: 30vw;
height: auto;
display: block;
border-radius: 1rem;
}
}
JavaScript
import {
Marquee,
ScrollProgress
} from "vevet";
const marquee = new Marquee({
container: document.getElementById("marquee"),
gap: "2vw",
enabled: false
});
let prevProgress = 0;
const scrollable = new ScrollProgress({
section: document.querySelector(".container"),
onUpdate: (data, {
progress
}) => {
let step = progress.y - prevProgress;
marquee.render(step * marquee.totalWidth);
prevProgress = progress.y;
}
});
No clonesβ
By default, Marquee clones child nodes for seamless looping. Disable with cloneNodes: false.
HTML
<div class="fullpage-center">
<div id="marquee">This text will not be cloned </div>
</div>
JavaScript
import {
Marquee
} from "vevet";
new Marquee({
container: document.getElementById("marquee"),
cloneNodes: false,
centered: true,
speed: "0.5vw"
});