MerryGo Background

MerryGo

carousel

Features

Everything you need for a modern, performant carousel

Infinite Loop

Seamless continuous scrolling with automatic cloning

Touch & Drag

Mobile-friendly swipe gestures and mouse drag support

Responsive

Breakpoint-based configuration for all screen sizes

Lightweight

Less than 10KB gzipped with zero dependencies

Autoplay

Optional automatic sliding with configurable intervals

Customizable

Flexible API with extensive configuration options

Basic Carousel

Simple full-width carousel with infinite loop and autoplay

              
<div class="carousel">
  <div class="carousel__inner">
    <div class="carousel__slide">
      <img src="banner1.jpg" alt="Banner 1">
    </div>
    <div class="carousel__slide">
      <img src="banner2.jpg" alt="Banner 2">
    </div>
    <div class="carousel__slide">
      <img src="banner3.jpg" alt="Banner 3">
    </div>
  </div>
</div>

<button class="carousel__arrow carousel__arrow--prev">←</button>
<button class="carousel__arrow carousel__arrow--next">→</button>
<div class="carousel__pagination"></div>
              
            
              
.carousel {
  width: 100%;
  overflow: hidden;
}

.carousel__inner {
  display: flex;
  gap: 5px;
  transition: transform 0.4s ease;
}

.carousel__slide {
  flex-shrink: 0;
  width: 100%;
}

.carousel__slide img {
  width: 100%;
  height: auto;
  display: block;
}

.carousel__arrow {
  position: absolute;
  top: 50%;
  z-index: 10;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  background: #FFFFFF;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  transition: all 0.3s ease;
  font-weight: 700;
  font-size: 22px;
}

.carousel__arrow:hover {
  background: #f5f5f5;
  transform: translateY(-50%) scale(1.05);
}

.carousel__arrow--prev {
  left: 16px;
}

.carousel__arrow--next {
  right: 16px;
}

.carousel__pagination {
  width: max-content;
  position: absolute;
  bottom: 15px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  padding: 8px 16px;
  background: #FFFFFF;
  border-radius: 40px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.merrygo-bullet {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #CED1D3;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
}

.merrygo-bullet-active {
  background: #000000;
}
              
            
              
const carousel = new MerryGo({
  gallery: document.querySelector('.carousel'),
  galleryInner: document.querySelector('.carousel__inner'),
  prevBtn: document.querySelector('.carousel__arrow--prev'),
  nextBtn: document.querySelector('.carousel__arrow--next'),
  pagination: document.querySelector('.carousel__pagination'),
  gap: 5,
  autoplay: 5000,
  infinityLoop: true
});
              
            
View Full Example

Products Carousel

Multiple slides visible with responsive breakpoints

Merry Go Round Image
              
<div class="products-carousel">
  <div class="products-carousel__inner">
    <div class="products-carousel__slide">Product 1</div>
    <div class="products-carousel__slide">Product 2</div>
    <div class="products-carousel__slide">Product 3</div>
    <!-- more slides -->
  </div>
</div>

<button class="products-carousel__arrow products-carousel__arrow--prev">←</button>
<button class="products-carousel__arrow products-carousel__arrow--next">→</button>
<div class="products-carousel__pagination"></div>
              
            
              
.products-carousel {
  overflow: hidden;
  user-select: none;
}

.products-carousel__inner {
  display: flex;
  gap: 20px;
  transition: transform 0.4s ease;
}

.products-carousel__slide {
  box-sizing: border-box;
  flex-shrink: 0;
  width: calc((100% - 60px) / 4); /* 4 visible */
}

.products-carousel__arrow {
  background-color: #fff;
  width: 44px;
  height: 44px;
  border-radius: 800px;
  border: 1px solid #E6E6E6;
  box-shadow: 0px 1px 8px 0px #0000001F;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  font-weight: 700;
  font-size: 22px;
}

.products-carousel__arrow:hover {
  background: #f5f5f5;
  transform: translateY(-50%) scale(1.05);
}

.products-carousel__arrow--prev {
  left: 16px;
}

.products-carousel__arrow--next {
  right: 16px;
}

.products-carousel__pagination {
  width: max-content;
  position: absolute;
  bottom: 15px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  padding: 8px 16px;
  background: #FFFFFF;
  border-radius: 40px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.merrygo-bullet {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #CED1D3;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
}

.merrygo-bullet-active {
  background: #000000;
}

@media (max-width: 1024px) {
  .products-carousel__inner { 
    gap: 15px; 
  }

  .products-carousel__slide { 
    width: calc((100% - 30px) / 3);  /* 3 visible */
  }
}

@media (max-width: 768px) {
  .products-carousel__slide { 
    width: calc((100% - 15px) / 2); /* 2 visible */
  } 
}

@media (max-width: 560px) {
  .products-carousel__inner { 
    gap: 0; 
  }

  .products-carousel__slide { 
    width: 100%; /* 1 visible */
  }
}
              
            
              
const carousel = new MerryGo({
  gallery: document.querySelector('.products-carousel'),
  galleryInner: document.querySelector('.products-carousel__inner'),
  prevBtn: document.querySelector('.products-carousel__arrow--prev'),
  nextBtn: document.querySelector('.products-carousel__arrow--next'),
  pagination: document.querySelector('.products-carousel__arrow--next'),
  infinityLoop: false,
  breakpoints: {
    0: { slidesVisible: 1, gap: 0 },
    561: { slidesVisible: 2, gap: 15 },
    769: { slidesVisible: 3, gap: 15 },
    1025: { slidesVisible: 4, gap: 20 }
  }
});
              
            
View Full Example

Gallery with Thumbnails

Synchronized carousel with clickable thumbnail navigation

Gallery 1
Gallery 2
Gallery 3
              
<!-- Thumbnails -->
<div class="gallery__thumbnails">
  <input type="radio" name="thumb" id="thumb-0" checked>
  <label class="gallery__thumbnail" for="thumb-0">
    <img src="image1.jpg">
  </label>

  <input type="radio" name="thumb" id="thumb-1" checked>
  <label class="gallery__thumbnail" for="thumb-1">
    <img src="image2.jpg">
  </label>

  <input type="radio" name="thumb" id="thumb-2" checked>
  <label class="gallery__thumbnail" for="thumb-2">
    <img src="image3.jpg">
  </label>
</div>

<!-- Main Gallery -->
<div class="gallery">
  <div class="gallery__inner">
    <div class="gallery__slide">
      <img src="image1.jpg">
    </div>

    <div class="gallery__slide">
      <img src="image2.jpg">
    </div>

    <div class="gallery__slide">
      <img src="image3.jpg">
    </div>
  </div>
</div>

<button class="gallery__arrow gallery__arrow--prev">←</button>
<button class="gallery__arrow gallery__arrow--next">→</button>
              
            
              
.gallery {
  overflow: hidden;
  display: flex;
  gap: 20px;
}

.gallery__inner {
  display: flex;
  gap: 5px;
  transition: transform 0.4s ease;
}

.gallery__slide {
  box-sizing: border-box;
  flex-shrink: 0;
}

.gallery__arrow {
  background-color: #fff;
  width: 44px;
  height: 44px;
  border-radius: 800px;
  border: 1px solid #E6E6E6;
  box-shadow: 0px 1px 8px 0px #0000001F;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  font-weight: 700;
  font-size: 22px;
}

.gallery__arrow:hover {
  background: #f5f5f5;
  transform: translateY(-50%) scale(1.05);
}

.gallery__arrow--prev {
  left: 16px;
}

.gallery__arrow--next {
  right: 16px;
}

.gallery__thumbnails {
  width: 80px;
  min-width: 80px;
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.gallery__thumbnails input[type="radio"] {
  display: none;
}

.gallery__thumbnail {
  width: 100%;
  height: 80px;
  border: 3px solid transparent;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
}

.gallery__thumbnails input:checked + .gallery__thumbnail {
  border-color: #000000;
}

.gallery__thumbnail:hover {
  border-color: #82898E;
}

.gallery__thumbnail img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
              
            
              
const thumbInputs = Array.from(
  document.querySelectorAll('.gallery__thumbnails input[type="radio"]')
);

const carousel = new MerryGo({
  gallery: document.querySelector('.gallery'),
  galleryInner: document.querySelector('.gallery__inner'),
  thumbs: thumbInputs, // Array of radio inputs
  gap: 5,
  prevBtn: document.querySelector(.gallery__arrow--prev'),
  nextBtn: document.querySelector('.gallery__arrow--next'),
});
              
            
View Full Example

Get Started

Install MerryGo and start to create!

Installation

<script src="https://cdn.jsdelivr.net/npm/merrygo-carousel@1.0.7/dist/merrygo.js"></script>
npm install merrygo-carousel