Pause on hover

The marquee() plugin keeps the strip moving forever, like the old <marquee> tag, at a speed in pixels per second. By default it stops under the cursor and while something inside has focus. It also pauses off screen, and stays still if the visitor prefers reduced motion.

Fast
Small
Typed
Accessible
Plugins
WebGL
Open source
Yours
View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-pill" style="background:#005345">Fast</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0F766E">Small</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#115E59">Typed</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#00221A">Accessible</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#134E4A">Plugins</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0B7A70">WebGL</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#003A30">Open source</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0D9488">Yours</div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-pill {
  height: 90px;
  padding: 0 40px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #fff;
  font: 700 1.4rem/1 var(--font-head, system-ui);
  letter-spacing: -0.02em;
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-pill {
  height: 90px;
  padding: 0 40px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #fff;
  font: 700 1.4rem/1 var(--font-head, system-ui);
  letter-spacing: -0.02em;
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 50 })],
})

Speeds up when you scroll

scrollBoost adds speed while the page scrolls: 1.5 px/s for every px/s you scroll. It follows how fast you scroll, eases in and out, and settles back to its own speed when you stop. Scroll the page up and down to see it.

Build sliders →
that actually work •
in about 10 KB →
with no dependencies •
View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-text">Build sliders <b>→</b></div></div>
  <div class="marquee-slide"><div class="marquee-text">that actually work <b>•</b></div></div>
  <div class="marquee-slide"><div class="marquee-text">in about 10 KB <b>→</b></div></div>
  <div class="marquee-slide"><div class="marquee-text">with no dependencies <b>•</b></div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-text {
  color: #00221A;
  white-space: nowrap;
  font: 700 clamp(2rem, 6vw, 4rem)/1.1 var(--font-head, system-ui);
  letter-spacing: -0.03em;
  padding-right: .5em;
}
.marquee-text b { color: #14B8A6; font-weight: 700; }
.marquee-slide {
  padding: 0 8px;
}
.marquee-text {
  color: #00221A;
  white-space: nowrap;
  font: 700 clamp(2rem, 6vw, 4rem)/1.1 var(--font-head, system-ui);
  letter-spacing: -0.03em;
  padding-right: .5em;
}
.marquee-text b { color: #14B8A6; font-weight: 700; }
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 40, scrollBoost: 1.5 })],
})

Speed up on hover

hoverSpeed sets the speed under the cursor: 300 px/s here against 50 px/s normally. It eases in and out, so there is no jump. Use 0 to stop, or a lower number to slow down.

Fast
Small
Typed
Accessible
Plugins
WebGL
Open source
Yours
View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-pill" style="background:#005345">Fast</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0F766E">Small</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#115E59">Typed</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#00221A">Accessible</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#134E4A">Plugins</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0B7A70">WebGL</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#003A30">Open source</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0D9488">Yours</div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-pill {
  height: 90px;
  padding: 0 40px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #fff;
  font: 700 1.4rem/1 var(--font-head, system-ui);
  letter-spacing: -0.02em;
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-pill {
  height: 90px;
  padding: 0 40px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #fff;
  font: 700 1.4rem/1 var(--font-head, system-ui);
  letter-spacing: -0.02em;
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 50, hoverSpeed: 300 })],
})

Marquee + draggable

draggable: true lets you grab it and drag in either direction. It follows the pointer, keeps its momentum when you let go and eases back to its own speed.

Fast
Small
Typed
Accessible
Plugins
WebGL
Open source
Yours
View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-pill" style="background:#005345">Fast</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0F766E">Small</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#115E59">Typed</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#00221A">Accessible</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#134E4A">Plugins</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0B7A70">WebGL</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#003A30">Open source</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0D9488">Yours</div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-pill {
  height: 90px;
  padding: 0 40px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #fff;
  font: 700 1.4rem/1 var(--font-head, system-ui);
  letter-spacing: -0.02em;
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-pill {
  height: 90px;
  padding: 0 40px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #fff;
  font: 700 1.4rem/1 var(--font-head, system-ui);
  letter-spacing: -0.02em;
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 50, draggable: true })],
})

With images

The slides can be anything: here, placeholder photos. It runs on its own and you can still drag it.

View code
<div id="my-slider">
  <div class="marquee-slide"><img class="marquee-img" src="/webgl/slide-1.jpg" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-img" src="/webgl/slide-2.jpg" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-img" src="/webgl/slide-3.jpg" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-img" src="/webgl/slide-4.jpg" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-img" src="/webgl/slide-5.jpg" alt="" /></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-img {
  display: block;
  width: 100%;
  height: 200px;
  object-fit: cover;
  border-radius: 12px;
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-img {
  display: block;
  width: 100%;
  height: 200px;
  object-fit: cover;
  border-radius: 12px;
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  items: 2,
  responsive: { 700: { items: 3 }, 1100: { items: 4 } },
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 40, draggable: true })],
})

Images of different widths

A gallery with the same height and a different width for every photo. autoWidth: true takes each width from the image itself, so portrait, square and panoramic shots sit side by side.

View code
<div id="my-slider">
  <div class="marquee-slide"><img class="marquee-photo" src="/webgl/slide-1.jpg" width="200" height="220" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-photo" src="/webgl/slide-2.jpg" width="340" height="220" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-photo" src="/webgl/slide-3.jpg" width="260" height="220" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-photo" src="/webgl/slide-4.jpg" width="400" height="220" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-photo" src="/webgl/slide-5.jpg" width="300" height="220" alt="" /></div>
  <div class="marquee-slide"><img class="marquee-photo" src="/webgl/slide-3.jpg" width="220" height="220" alt="" /></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-photo {
  display: block;
  height: 220px;
  border-radius: 12px;
  object-fit: cover;
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-photo {
  display: block;
  height: 220px;
  border-radius: 12px;
  object-fit: cover;
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 45, draggable: true })],
})

Wide slides

items: 1 makes each slide as wide as the strip (two on larger screens). Big cards with a caption, draggable.

Mountains
Coast
Forest
City
Desert
View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-card"><img src="/webgl/slide-1.jpg" alt="" /><span>Mountains</span></div></div>
  <div class="marquee-slide"><div class="marquee-card"><img src="/webgl/slide-2.jpg" alt="" /><span>Coast</span></div></div>
  <div class="marquee-slide"><div class="marquee-card"><img src="/webgl/slide-3.jpg" alt="" /><span>Forest</span></div></div>
  <div class="marquee-slide"><div class="marquee-card"><img src="/webgl/slide-4.jpg" alt="" /><span>City</span></div></div>
  <div class="marquee-slide"><div class="marquee-card"><img src="/webgl/slide-5.jpg" alt="" /><span>Desert</span></div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-card {
  height: 240px;
  border-radius: 16px;
  overflow: hidden;
  position: relative;
}
.marquee-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
.marquee-card span {
  position: absolute; left: 16px; bottom: 14px;
  color: #fff; font: 700 1.2rem/1 var(--font-head, system-ui);
  text-shadow: 0 1px 8px rgba(0,0,0,.5);
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-card {
  height: 240px;
  border-radius: 16px;
  overflow: hidden;
  position: relative;
}
.marquee-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
.marquee-card span {
  position: absolute; left: 16px; bottom: 14px;
  color: #fff; font: 700 1.2rem/1 var(--font-head, system-ui);
  text-shadow: 0 1px 8px rgba(0,0,0,.5);
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  items: 1,
  responsive: { 700: { items: 2 } },
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 60, draggable: true })],
})

Narrow slides

autoWidth: true lets every slide be as wide as its content, so short and long labels sit side by side with no gaps and no overlap. Slow and quiet, like a tag cloud.

TypeScript
Accessible
Tree-shakeable
Plugins
WebGL
Effects
Smooth drag
Marquee
Autoplay
Thumbs
Keyboard
Hooks
View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-chip">TypeScript</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Accessible</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Tree-shakeable</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Plugins</div></div>
  <div class="marquee-slide"><div class="marquee-chip">WebGL</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Effects</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Smooth drag</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Marquee</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Autoplay</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Thumbs</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Keyboard</div></div>
  <div class="marquee-slide"><div class="marquee-chip">Hooks</div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-chip {
  padding: 10px 20px;
  border-radius: 999px;
  background: #E6F6F3;
  color: #005345;
  white-space: nowrap;
  font: 600 .9rem/1 var(--font-body, system-ui);
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-chip {
  padding: 10px 20px;
  border-radius: 999px;
  background: #E6F6F3;
  color: #005345;
  white-space: nowrap;
  font: 600 .9rem/1 var(--font-body, system-ui);
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 35 })],
})

Text ticker

Big headlines in a ticker. With autoWidth: true each slide is exactly as wide as its text, whatever its length.

Build sliders →
that actually work •
in about 10 KB →
with no dependencies •
View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-text">Build sliders <b>→</b></div></div>
  <div class="marquee-slide"><div class="marquee-text">that actually work <b>•</b></div></div>
  <div class="marquee-slide"><div class="marquee-text">in about 10 KB <b>→</b></div></div>
  <div class="marquee-slide"><div class="marquee-text">with no dependencies <b>•</b></div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-text {
  color: #00221A;
  white-space: nowrap;
  font: 700 clamp(2rem, 6vw, 4rem)/1.1 var(--font-head, system-ui);
  letter-spacing: -0.03em;
  padding-right: .5em;
}
.marquee-text b { color: #14B8A6; font-weight: 700; }
.marquee-slide {
  padding: 0 8px;
}
.marquee-text {
  color: #00221A;
  white-space: nowrap;
  font: 700 clamp(2rem, 6vw, 4rem)/1.1 var(--font-head, system-ui);
  letter-spacing: -0.03em;
  padding-right: .5em;
}
.marquee-text b { color: #14B8A6; font-weight: 700; }
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 90, pauseOnHover: false })],
})

Logos that stop on hover

The classic logo wall, with logos of different widths: slow, and hoverSpeed: 0 stops it under the cursor so people can read or click.

View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-logo">ACME</div></div>
  <div class="marquee-slide"><div class="marquee-logo">NORTHWIND</div></div>
  <div class="marquee-slide"><div class="marquee-logo">ATLAS</div></div>
  <div class="marquee-slide"><div class="marquee-logo">PIXELFORGE</div></div>
  <div class="marquee-slide"><div class="marquee-logo">ORBIT</div></div>
  <div class="marquee-slide"><div class="marquee-logo">LUMEN LABS</div></div>
  <div class="marquee-slide"><div class="marquee-logo">VERTEX</div></div>
  <div class="marquee-slide"><div class="marquee-logo">NOVA</div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-logo {
  height: 70px;
  padding: 0 28px;
  border-radius: 12px;
  border: 1px solid #E2E8F0;
  display: flex; align-items: center; justify-content: center;
  color: #4F6560;
  white-space: nowrap;
  font: 700 1rem/1 var(--font-head, system-ui);
  letter-spacing: .04em;
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-logo {
  height: 70px;
  padding: 0 28px;
  border-radius: 12px;
  border: 1px solid #E2E8F0;
  display: flex; align-items: center; justify-content: center;
  color: #4F6560;
  white-space: nowrap;
  font: 700 1rem/1 var(--font-head, system-ui);
  letter-spacing: .04em;
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 30, hoverSpeed: 0 })],
})

Left to right, never pauses

direction: 'right' reverses it, and pauseOnHover: false keeps it going under the pointer.

Fast
Small
Typed
Accessible
Plugins
WebGL
Open source
Yours
View code
<div id="my-slider">
  <div class="marquee-slide"><div class="marquee-pill" style="background:#005345">Fast</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0F766E">Small</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#115E59">Typed</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#00221A">Accessible</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#134E4A">Plugins</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0B7A70">WebGL</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#003A30">Open source</div></div>
  <div class="marquee-slide"><div class="marquee-pill" style="background:#0D9488">Yours</div></div>
</div>
.marquee-slide {
  padding: 0 8px;
}
.marquee-pill {
  height: 90px;
  padding: 0 40px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #fff;
  font: 700 1.4rem/1 var(--font-head, system-ui);
  letter-spacing: -0.02em;
}
.marquee-slide {
  padding: 0 8px;
}
.marquee-pill {
  height: 90px;
  padding: 0 40px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  color: #fff;
  font: 700 1.4rem/1 var(--font-head, system-ui);
  letter-spacing: -0.02em;
}
import { Slider } from '@andresclua/sliderkit'
import { marquee } from '@andresclua/sliderkit-plugins'

new Slider('#my-slider', {
  autoWidth: true,
  loop: true,
  touch: false,
  mouseDrag: false,
  speed: 0,
  plugins: [marquee({ speed: 120, direction: 'right', pauseOnHover: false })],
})