NeuroAgent

Horizontal Scrolling with Arrows: Complete Guide

Learn how to create horizontal scrolling with arrow buttons. Complete guide with code examples, optimization, and responsive design.

How can I implement horizontal scrolling using arrow buttons instead of the standard scrollbar? I need a solution where arrow buttons will handle scrolling left and right.

NeuroAgent

Implementing Horizontal Scrolling with Arrow Buttons

To implement horizontal scrolling with arrow buttons, you can use JavaScript in combination with CSS. The main approach involves creating a container with overflow-x: hidden and adding buttons that trigger scroll functions when clicked. The simplest method is to use the scrollBy() method for smoothly moving content left or right.

Table of Contents

Basic Implementation Methods

There are several basic approaches to creating horizontal scrolling with arrow buttons:

Using scrollBy()

The simplest and most effective method is to use the built-in scrollBy() method, which allows scrolling content by a specified number of pixels.

javascript
// Scroll right
document.getElementById('scrollContainer').scrollBy({
  left: 200,
  behavior: 'smooth'
});

// Scroll left
document.getElementById('scrollContainer').scrollBy({
  left: -200,
  behavior: 'smooth'
});

Using CSS transform

Another popular approach is to use CSS transforms for scroll animation:

javascript
// Save current scroll position
let currentPosition = 0;

// Function to scroll right
function scrollRight() {
  currentPosition += 200;
  document.getElementById('scrollContainer').style.transform = `translateX(-${currentPosition}px)`;
}

// Function to scroll left
function scrollLeft() {
  currentPosition -= 200;
  document.getElementById('scrollContainer').style.transform = `translateX(-${currentPosition}px)`;
}

Using jQuery

For those who prefer jQuery, there are many ready-made plugins and solutions:

javascript
// Example with jQuery
$('#rightArrow').click(function() {
  $('#scrollContainer').stop().animate({
    scrollLeft: '+=200px'
  }, 400);
});

$('#leftArrow').click(function() {
  $('#scrollContainer').stop().animate({
    scrollLeft: '-=200px'
  }, 400);
});

Complete Example with HTML, CSS and JavaScript

Here’s a complete example of implementing horizontal scrolling with arrow buttons:

HTML Structure

html
<div class="scroll-container">
  <div class="scroll-wrapper">
    <div class="scroll-item">Item 1</div>
    <div class="scroll-item">Item 2</div>
    <div class="scroll-item">Item 3</div>
    <div class="scroll-item">Item 4</div>
    <div class="scroll-item">Item 5</div>
    <div class="scroll-item">Item 6</div>
  </div>
  <button class="scroll-button left" id="leftArrow">
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <path d="M15 18l-6-6 6-6"/>
    </svg>
  </button>
  <button class="scroll-button right" id="rightArrow">
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <path d="M9 18l6-6-6-6"/>
    </svg>
  </button>
</div>

CSS Styles

css
.scroll-container {
  position: relative;
  width: 100%;
  overflow: hidden;
  padding: 20px 0;
}

.scroll-wrapper {
  display: flex;
  transition: transform 0.3s ease;
  gap: 20px;
}

.scroll-item {
  flex: 0 0 300px;
  height: 200px;
  background: #f0f0f0;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: bold;
}

.scroll-button {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  transition: background 0.3s ease;
}

.scroll-button:hover {
  background: #0056b3;
}

.scroll-button.left {
  left: 10px;
}

.scroll-button.right {
  right: 10px;
}

/* Styles for hiding buttons when reaching boundaries */
.scroll-button.hidden {
  opacity: 0.3;
  pointer-events: none;
}

JavaScript Functionality

javascript
document.addEventListener('DOMContentLoaded', function() {
  const scrollWrapper = document.querySelector('.scroll-wrapper');
  const leftArrow = document.getElementById('leftArrow');
  const rightArrow = document.getElementById('rightArrow');
  
  let scrollPosition = 0;
  const scrollAmount = 320; // Item width + gap
  
  // Function to check arrow visibility
  function checkArrowsVisibility() {
    const maxScroll = scrollWrapper.scrollWidth - scrollWrapper.parentElement.clientWidth;
    
    if (scrollPosition <= 0) {
      leftArrow.classList.add('hidden');
    } else {
      leftArrow.classList.remove('hidden');
    }
    
    if (scrollPosition >= maxScroll) {
      rightArrow.classList.add('hidden');
    } else {
      rightArrow.classList.remove('hidden');
    }
  }
  
  // Handler for right arrow
  rightArrow.addEventListener('click', function() {
    scrollPosition += scrollAmount;
    scrollWrapper.style.transform = `translateX(-${scrollPosition}px)`;
    checkArrowsVisibility();
  });
  
  // Handler for left arrow
  leftArrow.addEventListener('click', function() {
    scrollPosition -= scrollAmount;
    scrollWrapper.style.transform = `translateX(-${scrollPosition}px)`;
    checkArrowsVisibility();
  });
  
  // Initialize
  checkArrowsVisibility();
  
  // Recheck arrow visibility on window resize
  window.addEventListener('resize', checkArrowsVisibility);
});

Advanced Techniques and Optimizations

Smooth Scrolling Animation

For smoother scrolling, you can use requestAnimationFrame:

javascript
let isScrolling = false;
let targetPosition = 0;
let currentPosition = 0;

function smoothScroll(targetX) {
  if (isScrolling) return;
  
  isScrolling = true;
  targetPosition = targetX;
  
  function animate() {
    const diff = targetPosition - currentPosition;
    
    if (Math.abs(diff) < 1) {
      currentPosition = targetPosition;
      isScrolling = false;
      return;
    }
    
    currentPosition += diff * 0.1;
    scrollWrapper.style.transform = `translateX(-${currentPosition}px)`;
    
    requestAnimationFrame(animate);
  }
  
  animate();
}

Inertial Scrolling

Adding inertial scrolling for mobile devices:

javascript
let touchStartX = 0;
let touchEndX = 0;
let isDragging = false;

scrollWrapper.addEventListener('touchstart', function(e) {
  touchStartX = e.changedTouches[0].screenX;
  isDragging = true;
});

scrollWrapper.addEventListener('touchmove', function(e) {
  if (!isDragging) return;
  
  touchEndX = e.changedTouches[0].screenX;
  const diff = touchStartX - touchEndX;
  
  currentPosition += diff;
  scrollWrapper.style.transform = `translateX(-${currentPosition}px)`;
  
  touchStartX = touchEndX;
});

scrollWrapper.addEventListener('touchend', function() {
  isDragging = false;
  
  // Add inertia
  const velocity = touchStartX - touchEndX;
  if (Math.abs(velocity) > 10) {
    targetPosition = currentPosition + velocity * 2;
    smoothScroll(targetPosition);
  }
});

Performance Optimization

To improve performance, you can use will-change:

css
.scroll-wrapper {
  will-change: transform;
  transform: translateZ(0);
}

Responsiveness and Mobile Devices

Responsive Scroll Sizes

For different screens, you can adjust the scroll amount:

javascript
function getScrollAmount() {
  const width = window.innerWidth;
  if (width < 768) {
    return 280; // For mobile devices
  } else if (width < 1024) {
    return 300; // For tablets
  } else {
    return 320; // For desktop
  }
}

// Use in handlers
const scrollAmount = getScrollAmount();

Touch Controls

For mobile devices, it’s important to add touch event support:

javascript
let touchStartX = 0;
let touchEndX = 0;

scrollWrapper.addEventListener('touchstart', function(e) {
  touchStartX = e.changedTouches[0].screenX;
});

scrollWrapper.addEventListener('touchend', function(e) {
  touchEndX = e.changedTouches[0].screenX;
  
  const swipeDistance = touchStartX - touchEndX;
  
  if (swipeDistance > 50) {
    // Swipe left - scroll right
    rightArrow.click();
  } else if (swipeDistance < -50) {
    // Swipe right - scroll left
    leftArrow.click();
  }
});

Mobile Optimization

css
@media (max-width: 768px) {
  .scroll-button {
    width: 35px;
    height: 35px;
  }
  
  .scroll-item {
    flex: 0 0 250px;
  }
}

Alternative Solutions

Using Existing Libraries

You can use ready-made solutions such as:

Swiper.js:

html
<div class="swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">Slide 1</div>
    <div class="swiper-slide">Slide 2</div>
    <div class="swiper-slide">Slide 3</div>
  </div>
  <div class="swiper-button-next"></div>
  <div class="swiper-button-prev"></div>
</div>

<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
<script>
  const swiper = new Swiper('.swiper', {
    slidesPerView: 'auto',
    spaceBetween: 20,
    navigation: {
      nextEl: '.swiper-button-next',
      prevEl: '.swiper-button-prev',
    },
  });
</script>

Slick Carousel:

javascript
$('.scroll-container').slick({
  infinite: false,
  slidesToShow: 3,
  slidesToScroll: 1,
  prevArrow: $('.left-arrow'),
  nextArrow: $('.right-arrow'),
  responsive: [
    {
      breakpoint: 768,
      settings: {
        slidesToShow: 1
      }
    }
  ]
});

CSS-Only Solution

For simple cases, you can use a CSS-only approach with radio buttons:

html
<input type="radio" name="carousel" id="slide1" checked>
<input type="radio" name="carousel" id="slide2">
<input type="radio" name="carousel" id="slide3">

<label for="slide2" class="carousel-control next"></label>
<label for="slide1" class="carousel-control prev"></label>

<div class="carousel-viewport">
  <div class="carousel-track">
    <div class="carousel-slide">Slide 1</div>
    <div class="carousel-slide">Slide 2</div>
    <div class="carousel-slide">Slide 3</div>
  </div>
</div>

<style>
.carousel-viewport {
  overflow: hidden;
  position: relative;
}

.carousel-track {
  display: flex;
  transition: transform 0.5s ease;
}

input[type="radio"]:nth-of-type(1):checked ~ .carousel-track {
  transform: translateX(0);
}

input[type="radio"]:nth-of-type(2):checked ~ .carousel-track {
  transform: translateX(-100%);
}

input[type="radio"]:nth-of-type(3):checked ~ .carousel-track {
  transform: translateX(-200%);
}

.carousel-control {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  z-index: 10;
}
</style>

Sources

  1. Arrow buttons for responsive horizontal scroll menu
  2. Horizontal Scrolling Menu with Arrow Keys
  3. How to Create a Responsive Horizontal Scrolling Card Slider
  4. Horizontal scrolling div with arrows using HTML and CSS
  5. Scroll div content horizontally using left and right arrow in jquery

Conclusion

  • For implementing horizontal scrolling with arrow buttons, the methods using scrollBy() or CSS transforms are most suitable
  • It’s important to add visibility checks for buttons when reaching content boundaries
  • For mobile devices, you need to add touch event support and inertial scrolling
  • Responsive design requires adjusting scroll parameters for different screen sizes
  • For complex projects, you can use ready-made libraries like Swiper.js or Slick Carousel
  • Performance optimization with will-change and transform: translateZ(0) improves animation smoothness

The simple and effective solution lies in the balance between performance and functionality - choose the approach that best meets your project requirements.