@glidejs/glide, slick-carousel, and swiper are JavaScript libraries used to create sliding content interfaces like image carousels, product sliders, and touch-enabled galleries. slick-carousel is a legacy option built on jQuery, known for its simplicity but limited by its dependency on an older library. @glidejs/glide is a lightweight, dependency-free vanilla JavaScript solution focused on performance and basic slider needs. swiper is a comprehensive, modular framework that supports complex interactions, virtual slides, and offers official integrations for modern frameworks like React and Vue.
All three libraries solve the same core problem — moving content horizontally or vertically in a touch-friendly way. However, their underlying architecture, dependency requirements, and maintenance status differ significantly. Choosing the wrong one can lock your project into legacy tech or force you to rewrite components later. Let's break down the technical realities.
The most immediate architectural decision is whether you want to bring jQuery into your modern stack.
slick-carousel requires jQuery.
This means your bundle must include jQuery even if you don't use it elsewhere. Initialization happens via jQuery chaining.
// slick-carousel: Requires jQuery
import $ from 'jquery';
import 'slick-carousel';
$('.slider').slick({
infinite: true,
slidesToShow: 3
});
@glidejs/glide is dependency-free.
It uses vanilla JavaScript and requires an explicit mount() call to start the engine.
// @glidejs/glide: Vanilla JS
import Glide from '@glidejs/glide';
const slider = new Glide('.slider', {
perView: 3
});
slider.mount();
swiper is also dependency-free but modular.
Since version 7, you must import specific features (modules) and pass them to the config.
// swiper: Modular Vanilla JS
import Swiper from 'swiper';
import { Navigation, Pagination } from 'swiper/modules';
const slider = new Swiper('.slider', {
modules: [Navigation, Pagination],
slidesPerView: 3
});
How you listen for changes affects how you sync state with the rest of your application.
slick-carousel uses jQuery events.
You listen to DOM events triggered by the plugin. This can feel disconnected from modern component lifecycles.
// slick-carousel: jQuery events
$('.slider').on('init', function(event, slick){
console.log('Initialized');
});
$('.slider').on('afterChange', function(event, slick, currentSlide){
console.log('Current slide:', currentSlide);
});
@glidejs/glide uses a custom event emitter.
Events are bound to the instance, keeping logic encapsulated within your JavaScript scope.
// @glidejs/glide: Instance events
slider.on('mount.after', function(){
console.log('Mounted');
});
slider.on('run', function(){
console.log('Slide changed');
});
swiper has a rich API of callbacks and events.
You can use config callbacks or listen to events on the instance. It offers more granular control over transition states.
// swiper: Config callbacks
const slider = new Swiper('.slider', {
on: {
init: function(){
console.log('Initialized');
},
slideChange: function(){
console.log('Slide changed');
}
}
});
Not all sliders need the same features. Loading unused code hurts performance.
slick-carousel is monolithic.
You import the whole library regardless of whether you need arrows, dots, or lazy loading. There is no tree-shaking.
// slick-carousel: All or nothing
import 'slick-carousel'; // Includes all features
@glidejs/glide is lightweight but fixed.
It includes core features by default. It is small enough that tree-shaking is less critical, but you cannot remove core parts.
// @glidejs/glide: Fixed core
import Glide from '@glidejs/glide'; // Core + basic extensions
swiper is fully modular.
You only import what you use. This keeps bundles small even when using advanced features like virtual slides or zoom.
// swiper: Tree-shakable modules
import { Virtual, Zoom } from 'swiper/modules';
new Swiper('.slider', {
modules: [Virtual, Zoom],
virtual: true
});
Modern apps often use React, Vue, or Svelte. Native DOM manipulation can conflict with these frameworks.
slick-carousel has no official framework wrappers.
You must manage the jQuery instance inside useEffect or mounted hooks manually. This often leads to memory leaks if not cleaned up properly.
// React + slick-carousel: Manual cleanup
useEffect(() => {
$('.slider').slick();
return () => $('.slider').slick('unslick');
}, []);
@glidejs/glide has community wrappers.
There is no official React component, but the vanilla API is simple enough to wrap manually. You still manage the instance lifecycle.
// React + @glidejs/glide: Manual instance
useEffect(() => {
const slider = new Glide('.slider').mount();
return () => slider.destroy();
}, []);
swiper offers official wrappers.
Packages like swiper/react provide components that handle initialization and updates automatically. This reduces boilerplate and bugs.
// React + swiper: Official components
import { Swiper, SwiperSlide } from 'swiper/react';
<Swiper slidesPerView={3}>
<SwiperSlide>Slide 1</SwiperSlide>
<SwiperSlide>Slide 2</SwiperSlide>
</Swiper>
This is the most critical architectural factor.
slick-carousel is effectively legacy.
The repository sees minimal activity. It relies on jQuery, which is no longer standard in modern frontend stacks. Using it introduces technical debt.
@glidejs/glide is maintained but niche.
It receives updates but focuses on staying lightweight. It is stable for simple use cases but lacks the ecosystem of larger libraries.
swiper is actively developed.
It receives frequent updates, security patches, and new features. It is the industry standard for complex slider requirements.
| Feature | slick-carousel | @glidejs/glide | swiper |
|---|---|---|---|
| Dependency | ❌ jQuery required | ✅ Vanilla JS | ✅ Vanilla JS |
| Modularity | ❌ Monolithic | ⚠️ Fixed Core | ✅ Fully Modular |
| Framework Support | ❌ Manual Only | ⚠️ Community Wrappers | ✅ Official Wrappers |
| Maintenance | ❌ Legacy/Inactive | ✅ Stable | ✅ Active |
| Complexity | Low | Low | High |
slick-carousel should not be used in new projects.
The jQuery dependency and lack of maintenance make it a risk for long-term stability. Only use it if you are fixing bugs in an old system that already depends on it.
@glidejs/glide is perfect for simple needs.
If you just need a basic slider without bells and whistles, this is a great choice. It is fast, small, and easy to understand.
swiper is the professional standard.
For production apps, especially those using React or Vue, swiper offers the best balance of features, support, and integration. The modular system ensures you do not pay a performance penalty for features you do not use.
Final Thought: While all three slide content, swiper provides the engineering foundation needed for modern applications — @glidejs/glide serves lightweight cases well — and slick-carousel belongs to the past.
Choose swiper if you require advanced features like virtual slides, complex breakpoints, or framework-specific components. It is the best fit for production-grade applications needing long-term support, accessibility features, and deep customization options.
Avoid slick-carousel for new projects due to its jQuery dependency and lack of active maintenance. Only consider it if you are maintaining a legacy codebase that already relies on jQuery and requires minimal changes to existing slider implementations.
Choose @glidejs/glide if you need a simple, lightweight slider without external dependencies. It is ideal for projects where bundle size matters and you only need basic sliding functionality without complex gestures or lazy loading.
Swiper - is the free and most modern mobile touch slider with hardware accelerated transitions and amazing native behavior. It is intended to be used in mobile websites, mobile web apps, and mobile native/hybrid apps.
Swiper is not compatible with all platforms, it is a modern touch slider which is focused only on modern apps/platforms to bring the best experience and simplicity.