DEV Community

Patrick Moore
Patrick Moore

Posted on

Advanced Touch Sliders with Keen Slider in React

Keen Slider is a lightweight, performant slider and carousel library for React applications. It provides native touch/swipe behavior, excellent performance, and extensive customization options for creating professional sliders and carousels. This guide walks through advanced usage of Keen Slider with React, including React hooks integration, plugins, and complex slider configurations. Keen Slider with React.

Demo animation

Demo animation

Prerequisites

Before you begin, make sure you have:

  • Node.js version 14.0 or higher installed
  • npm, yarn, or pnpm package manager
  • A React project (version 16.8 or higher) or create-react-app setup
  • Basic knowledge of React hooks (useState, useRef, useEffect)
  • Familiarity with JavaScript/TypeScript
  • Understanding of touch events and gestures

Installation

Install Keen Slider using your preferred package manager:

npm install keen-slider
Enter fullscreen mode Exit fullscreen mode

Or with yarn:

yarn add keen-slider
Enter fullscreen mode Exit fullscreen mode

Or with pnpm:

pnpm add keen-slider
Enter fullscreen mode Exit fullscreen mode

After installation, your package.json should include:

{
  "dependencies": {
    "keen-slider": "^6.0.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Project Setup

Import the CSS file in your main entry file:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import 'keen-slider/keen-slider.min.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

First Example / Basic Usage

Let's create a simple slider. Create a new file src/SliderExample.jsx:

// src/SliderExample.jsx
import React from 'react';
import { useKeenSlider } from 'keen-slider/react';
import 'keen-slider/keen-slider.min.css';

function SliderExample() {
  const [sliderRef, instanceRef] = useKeenSlider({
    loop: true,
    slideChanged() {
      console.log('slide changed');
    }
  });

  const images = [
    'https://via.placeholder.com/800x400/007bff/ffffff?text=Slide+1',
    'https://via.placeholder.com/800x400/28a745/ffffff?text=Slide+2',
    'https://via.placeholder.com/800x400/ffc107/000000?text=Slide+3',
    'https://via.placeholder.com/800x400/dc3545/ffffff?text=Slide+4'
  ];

  return (
    <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
      <h2>Basic Keen Slider Example</h2>
      <div ref={sliderRef} className="keen-slider">
        {images.map((image, index) => (
          <div key={index} className="keen-slider__slide">
            <img
              src={image}
              alt={`Slide ${index + 1}`}
              style={{ width: '100%', height: '100%', objectFit: 'cover' }}
            />
          </div>
        ))}
      </div>
    </div>
  );
}

export default SliderExample;
Enter fullscreen mode Exit fullscreen mode

Update your App.jsx:

// src/App.jsx
import React from 'react';
import SliderExample from './SliderExample';
import './App.css';

function App() {
  return (
    <div className="App">
      <SliderExample />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This creates a basic slider with loop functionality and touch support.

Understanding the Basics

Keen Slider provides a React hook for integration:

  • useKeenSlider hook: React hook for creating sliders
  • sliderRef: Ref callback for the slider container
  • instanceRef: Ref to access slider API methods
  • Options object: Configure slider behavior
  • Plugins: Extend functionality with plugins
  • CSS classes: Use keen-slider and keen-slider__slide classes

Key concepts for advanced usage:

  • Hook usage: Use useKeenSlider hook with options and plugins
  • Ref assignment: Assign sliderRef to the container element
  • Slide structure: Use keen-slider__slide class for slides
  • API access: Use instanceRef to control slider programmatically
  • Event callbacks: Use callbacks like slideChanged, created, etc.

Here's an example with navigation and autoplay:

// src/AdvancedSliderExample.jsx
import React, { useState } from 'react';
import { useKeenSlider } from 'keen-slider/react';
import 'keen-slider/keen-slider.min.css';

function AdvancedSliderExample() {
  const [currentSlide, setCurrentSlide] = useState(0);
  const [loaded, setLoaded] = useState(false);

  const [sliderRef, instanceRef] = useKeenSlider({
    initial: 0,
    slideChanged(slider) {
      setCurrentSlide(slider.track.details.rel);
    },
    created() {
      setLoaded(true);
    },
    loop: true
  });

  const images = [
    'https://via.placeholder.com/800x400/007bff/ffffff?text=Slide+1',
    'https://via.placeholder.com/800x400/28a745/ffffff?text=Slide+2',
    'https://via.placeholder.com/800x400/ffc107/000000?text=Slide+3',
    'https://via.placeholder.com/800x400/dc3545/ffffff?text=Slide+4'
  ];

  return (
    <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
      <h2>Advanced Keen Slider</h2>
      <div style={{ position: 'relative' }}>
        <div ref={sliderRef} className="keen-slider">
          {images.map((image, index) => (
            <div key={index} className="keen-slider__slide">
              <img
                src={image}
                alt={`Slide ${index + 1}`}
                style={{ width: '100%', height: '400px', objectFit: 'cover' }}
              />
            </div>
          ))}
        </div>
        {loaded && instanceRef.current && (
          <>
            <button
              onClick={(e) => {
                e.stopPropagation();
                instanceRef.current?.prev();
              }}
              disabled={currentSlide === 0}
              style={{
                position: 'absolute',
                left: '10px',
                top: '50%',
                transform: 'translateY(-50%)',
                padding: '10px 15px',
                backgroundColor: 'rgba(255,255,255,0.9)',
                color: '#333',
                border: 'none',
                borderRadius: '50%',
                cursor: 'pointer',
                zIndex: 1
              }}
            ></button>
            <button
              onClick={(e) => {
                e.stopPropagation();
                instanceRef.current?.next();
              }}
              disabled={currentSlide === instanceRef.current.track.details.slides.length - 1}
              style={{
                position: 'absolute',
                right: '10px',
                top: '50%',
                transform: 'translateY(-50%)',
                padding: '10px 15px',
                backgroundColor: 'rgba(255,255,255,0.9)',
                color: '#333',
                border: 'none',
                borderRadius: '50%',
                cursor: 'pointer',
                zIndex: 1
              }}
            ></button>
          </>
        )}
      </div>
      {loaded && (
        <div style={{ textAlign: 'center', marginTop: '20px' }}>
          {Array.from({ length: images.length }).map((_, idx) => (
            <button
              key={idx}
              onClick={() => instanceRef.current?.moveToIdx(idx)}
              style={{
                width: '12px',
                height: '12px',
                borderRadius: '50%',
                border: 'none',
                backgroundColor: currentSlide === idx ? '#007bff' : '#ccc',
                cursor: 'pointer',
                margin: '0 5px'
              }}
            />
          ))}
        </div>
      )}
    </div>
  );
}

export default AdvancedSliderExample;
Enter fullscreen mode Exit fullscreen mode

Practical Example / Building Something Real

Let's build a comprehensive image gallery with thumbnails:

// src/ImageGalleryKeenSlider.jsx
import React, { useState } from 'react';
import { useKeenSlider } from 'keen-slider/react';
import 'keen-slider/keen-slider.min.css';

function ImageGalleryKeenSlider() {
  const [currentSlide, setCurrentSlide] = useState(0);
  const [loaded, setLoaded] = useState(false);

  const images = [
    {
      full: 'https://via.placeholder.com/1200x800/007bff/ffffff?text=Image+1',
      thumb: 'https://via.placeholder.com/150x100/007bff/ffffff?text=1',
      title: 'Image 1'
    },
    {
      full: 'https://via.placeholder.com/1200x800/28a745/ffffff?text=Image+2',
      thumb: 'https://via.placeholder.com/150x100/28a745/ffffff?text=2',
      title: 'Image 2'
    },
    {
      full: 'https://via.placeholder.com/1200x800/ffc107/000000?text=Image+3',
      thumb: 'https://via.placeholder.com/150x100/ffc107/000000?text=3',
      title: 'Image 3'
    },
    {
      full: 'https://via.placeholder.com/1200x800/dc3545/ffffff?text=Image+4',
      thumb: 'https://via.placeholder.com/150x100/dc3545/ffffff?text=4',
      title: 'Image 4'
    },
    {
      full: 'https://via.placeholder.com/1200x800/6c757d/ffffff?text=Image+5',
      thumb: 'https://via.placeholder.com/150x100/6c757d/ffffff?text=5',
      title: 'Image 5'
    }
  ];

  const [mainSliderRef, mainInstanceRef] = useKeenSlider({
    initial: 0,
    slideChanged(slider) {
      setCurrentSlide(slider.track.details.rel);
      thumbInstanceRef.current?.moveToIdx(slider.track.details.rel);
    },
    created() {
      setLoaded(true);
    }
  });

  const [thumbSliderRef, thumbInstanceRef] = useKeenSlider({
    initial: 0,
    slides: {
      perView: 4,
      spacing: 10
    },
    created() {
      setLoaded(true);
    }
  });

  return (
    <div style={{ padding: '20px', maxWidth: '1000px', margin: '0 auto' }}>
      <h1>Image Gallery with Keen Slider</h1>
      <div style={{ marginBottom: '20px' }}>
        <div ref={mainSliderRef} className="keen-slider">
          {images.map((image, index) => (
            <div key={index} className="keen-slider__slide">
              <img
                src={image.full}
                alt={image.title}
                style={{
                  width: '100%',
                  height: '600px',
                  objectFit: 'cover',
                  borderRadius: '8px'
                }}
              />
            </div>
          ))}
        </div>
      </div>
      <div ref={thumbSliderRef} className="keen-slider">
        {images.map((image, index) => (
          <div
            key={index}
            className="keen-slider__slide"
            onClick={() => {
              mainInstanceRef.current?.moveToIdx(index);
            }}
            style={{
              cursor: 'pointer',
              opacity: currentSlide === index ? 1 : 0.6,
              border: currentSlide === index ? '3px solid #007bff' : '1px solid #ddd',
              borderRadius: '4px',
              overflow: 'hidden'
            }}
          >
            <img
              src={image.thumb}
              alt={`Thumbnail ${index}`}
`}
              style={{
                width: '100%',
                height: '100px',
                objectFit: 'cover'
              }}
            />
          </div>
        ))}
      </div>
      {loaded && (
        <div style={{ textAlign: 'center', marginTop: '20px', color: '#666' }}>
          Image {currentSlide + 1} of {images.length}
        </div>
      )}
    </div>
  );
}

export default ImageGalleryKeenSlider;
Enter fullscreen mode Exit fullscreen mode

Now create a product carousel with multiple slides:

// src/ProductCarouselKeenSlider.jsx
import React from 'react';
import { useKeenSlider } from 'keen-slider/react';
import 'keen-slider/keen-slider.min.css';

function ProductCarouselKeenSlider() {
  const [sliderRef] = useKeenSlider({
    loop: true,
    mode: 'free-snap',
    slides: {
      perView: 1,
      spacing: 15
    },
    breakpoints: {
      '(min-width: 640px)': {
        slides: { perView: 2, spacing: 15 }
      },
      '(min-width: 1024px)': {
        slides: { perView: 3, spacing: 20 }
      }
    }
  });

  const products = [
    { id: 1, name: 'Product 1', price: '$99', image: 'https://via.placeholder.com/300x300/007bff/ffffff?text=Product+1' },
    { id: 2, name: 'Product 2', price: '$149', image: 'https://via.placeholder.com/300x300/28a745/ffffff?text=Product+2' },
    { id: 3, name: 'Product 3', price: '$199', image: 'https://via.placeholder.com/300x300/ffc107/000000?text=Product+3' },
    { id: 4, name: 'Product 4', price: '$249', image: 'https://via.placeholder.com/300x300/dc3545/ffffff?text=Product+4' },
    { id: 5, name: 'Product 5', price: '$299', image: 'https://via.placeholder.com/300x300/6c757d/ffffff?text=Product+5' }
  ];

  return (
    <div style={{ padding: '20px', maxWidth: '1200px', margin: '0 auto' }}>
      <h2>Product Carousel</h2>
      <div ref={sliderRef} className="keen-slider">
        {products.map((product) => (
          <div key={product.id} className="keen-slider__slide">
            <div style={{
              padding: '15px',
              textAlign: 'center',
              backgroundColor: '#f8f9fa',
              borderRadius: '8px',
              height: '100%'
            }}>
              <img
                src={product.image}
                alt={product.name}
                style={{
                  width: '100%',
                  height: '250px',
                  objectFit: 'cover',
                  borderRadius: '4px',
                  marginBottom: '10px'
                }}
              />
              <h3 style={{ margin: '0 0 5px 0' }}>{product.name}</h3>
              <p style={{ margin: 0, fontWeight: 'bold', color: '#007bff' }}>{product.price}</p>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

export default ProductCarouselKeenSlider;
Enter fullscreen mode Exit fullscreen mode

Update your App.jsx:

// src/App.jsx
import React from 'react';
import ImageGalleryKeenSlider from './ImageGalleryKeenSlider';
import ProductCarouselKeenSlider from './ProductCarouselKeenSlider';
import './App.css';

function App() {
  return (
    <div className="App">
      <ImageGalleryKeenSlider />
      <ProductCarouselKeenSlider />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This example demonstrates:

  • Image gallery with thumbnail navigation
  • Product carousel with responsive breakpoints
  • Programmatic control
  • Multiple slider instances
  • Touch/swipe gestures
  • Custom navigation

Common Issues / Troubleshooting

  1. Slider not displaying: Make sure you've imported the CSS file (import 'keen-slider/keen-slider.min.css'). Also ensure the container has the keen-slider class and slides have keen-slider__slide class.

  2. Hook not working: Import useKeenSlider from 'keen-slider/react'. The hook returns an array with [sliderRef, instanceRef].

  3. Navigation not working: Use instanceRef.current to access slider methods like next(), prev(), and moveToIdx(). Check that the slider is loaded before calling these methods.

  4. Responsive not working: Use the breakpoints option with media query strings. Configure slides.perView and slides.spacing for each breakpoint.

  5. Thumbnails not syncing: For thumbnail galleries, use separate slider instances and sync them using slideChanged callbacks and moveToIdx() method.

  6. Performance issues: Keen Slider is optimized for performance. If you experience issues, check for CSS conflicts or ensure slides have proper dimensions.

Next Steps

Now that you have an advanced understanding of Keen Slider:

  • Explore all available options and plugins
  • Learn about custom animations
  • Implement lazy loading for images
  • Add custom navigation controls
  • Create vertical sliders
  • Learn about other slider libraries (swiper, react-slick)
  • Check the official repository: https://github.com/rcbyr/keen-slider

Summary

You've successfully integrated Keen Slider into your React application with advanced features including thumbnail navigation, responsive breakpoints, programmatic control, and multiple slider instances. Keen Slider provides a lightweight, performant solution for creating professional sliders with excellent touch support.

SEO Keywords

keen-slider
React Keen Slider
keen-slider tutorial
React touch slider
keen-slider installation
React carousel slider
keen-slider example
React slider library
keen-slider setup
React performant slider
keen-slider customization
React slider hooks
keen-slider React integration
React slider component
keen-slider getting started

Top comments (0)