Web component · zero dependencies · GPL-2.0

<flex-slider>

Drop plain images inside an element and it becomes a slider. No jQuery, no stylesheet to load, no icon font, no build step — the markup and styles live in a shadow root, so nothing leaks in or out.

Live

This page is the demo

The slider below is the real component running here — not a screenshot and not an iframe. Hover it to pause; drag it on a touch device.

River Valley Coastal Cliffs Resting Pug Waterfall Forest Path
animation="slide" nav pager autoplay interval="4500" pause-on-hover theme="dark"

That is the whole markup — one import, then plain images:

<!-- one import; the component is a single file -->
<script type="module" src="flex-slider.js"></script>

<!-- plain images are the whole API -->
<flex-slider animation="slide" nav pager autoplay
             interval="4500" pause-on-hover theme="dark">
  <img src="slide-1.jpg" alt="First slide">
  <img src="slide-2.jpg" alt="Second slide">
  <img src="slide-3.jpg" alt="Third slide">
</flex-slider>

Variants

One element, every mode

Three independent instances, each configured by attributes alone. They share no state — paging one leaves the others where they were.

Snowy Peaks Coastline Ocean Sunrise Tall Grass Strawberries Breaching Whale City Bikes Country Road Vintage Camera Lighthouse
Left: animation="fade" pager  ·  Middle: pager thumbs  ·  Right: direction="vertical"

Scripting

Methods, properties and events

The element is the API. Every button drives the slider, and each slide-start and slide-end is written to the panel underneath — the same events you would listen for in your own page.

Foggy Valley Sunset Pier Desert Road Green Hills
listening for slide-start…

Theming

Restyled without touching the component

Both sliders are driven by CSS custom properties and shadow parts from this page's own stylesheet. The component's internals are untouched — that is the point of the shadow boundary.

Sailboat Mountain Lake Pine Forest River Bridge Waterfall Canoe Trip
Left: warm custom properties. Right: square arrows and a pill pager via ::part().
/* custom properties, set on the host */
#theme-warm {
  --fs-accent: #ff9f45;
  --fs-arrow-bg: rgba(255, 159, 69, .92);
  --fs-arrow-fg: #201603;
  --fs-dot: rgba(255, 159, 69, .45);
  --fs-dot-active: #ff9f45;
  --fs-radius: 16px;
}

/* or reach inside by shadow part */
#theme-square::part(arrow-prev),
#theme-square::part(arrow-next) { border-radius: 6px; width: 46px; height: 46px; }

Live updates

Add an image, the slider adapts

The component watches its own children. Appending an image adds a slide and leaves the current position alone — no re-init call needed.

Strawberries Breaching Whale

Reference

Attributes

AttributeValuesNotes
animationslide, fadeHow slides change. Default slide.
durationmsTransition length. Default 700.
easingany CSS timing functionDefault ease.
autoplaypresentStarts a slideshow on load.
intervalmsTime between slides. Default 5000.
pause-on-hoverpresentPauses while the pointer is over it.
navpresentShows the previous/next arrows.
pagerpresentShows the dot or thumbnail pager.
thumbspresentPager renders thumbnails instead of dots.
slide-show-atindex, 0-basedSlide to start on.
directionhorizontal, verticalAxis the track moves along.
reversepresentAnimates the other way.
rtlpresentMirrors arrows and layout.
swipeon, offDrag and swipe. On by default.
keyboardon, offArrow keys, Home and End. On by default.
smooth-heightpresentAnimates the height between slides.
heightCSS lengthFixed box; images crop with object-fit: cover.
themelight, darkArrow and pager colours.
loopon, offWraps by default; off stops at the ends.
labelstringAccessible name for the region.

Methods & events

// methods
slider.next();            slider.prev();
slider.goTo(2);           slider.play();
slider.pause();           slider.refresh();   // re-read the images
slider.reset();           slider.currentIndex = 0;

// events — carry { index, slide, count }, and cross the shadow boundary
slider.addEventListener('slide-start', (e) => console.log(e.detail.index));
slider.addEventListener('slide-end',   (e) => console.log(e.detail.slide));

Install

# one file, no dependencies
curl -O https://squidjam.github.io/FlexSlider/flex-slider.js

References

Where to go next

No dependencies

No jQuery, no polyfills, no bundler. One module a browser loads directly.

Nothing to configure

Slide widths are measured, not assumed, so any image size and container width works.

Accessible by default

Labelled region, slide positions, named controls and keyboard support.