<section class="carousel" aria-label="carousel">
  <p class="sr-only">Carousel with three slides shown at a time. Use the Previous and Next buttons to navigate, or the slide dot buttons at the end to jump to slides.</p>
  
  <button class="previous">
    <span class="fas fa-chevron-left" aria-hidden="true"></span>
    <span class="sr-only">Previous slides</span>
  </button>
  
  <div class="slides">
    <div class="slide" role="group" aria-label="slide 1 of 9">
      <p>And I know you're saying, 'Oh Bob, you've done it this time.' And you may be right. Little short strokes. In life you need colors. <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a>.</p>
    </div>
    
    <div class="slide" role="group" aria-label="slide 2 of 9">
      <p>This painting comes right out of your heart. It's beautiful - and we haven't even done anything to it yet. In this world, everything can be happy. <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a></p>
    </div>
    
    <div class="slide" role="group" aria-label="slide 3 of 9">
      <p>We don't make mistakes we just have happy little accidents. Mountains are so simple, they're hard. You got your heavy coat out yet? <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a></p>
    </div>
    
    <div class="slide" role="group" aria-label="slide 4 of 9">
      <p>It's getting colder. You can't have light without dark. You can't know happiness unless you've known sorrow. <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a></p>
    </div>
    
    <div class="slide" role="group" aria-label="slide 5 of 9">
      <p>Exercising the imagination, experimenting with talents, being creative; these things, to me, are truly the windows to your soul. <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a></p>
    </div>
    
    <div class="slide" role="group" aria-label="slide 6 of 9">
      <p>I spend a lot of time walking around in the woods and talking to trees, and squirrels, and little rabbits and stuff. <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a></p>
    </div>
    
    <div class="slide" role="group" aria-label="slide 7 of 9">
      <p>And that's when it becomes fun - you don't have to spend your time thinking about what's happening - you just let it happen. <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a></p>
    </div>
    
    <div class="slide" role="group" aria-label="slide 8 of 9">
      <p>Let your imagination just wonder around when you're doing these things. It looks so good, I might as well not stop. Just use the old one inch brush. <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a></p>
    </div>
    
    <div class="slide" role="group" aria-label="slide 9 of 9">
      <p>This is probably the greatest thing that's ever happened in my life. You don't want to kill all your dark areas they are very important. <a href="https://en.wikipedia.org/wiki/Bob_Ross">Read more</a></p>
    </div>
  </div>
  
  <button class="next">
    <span class="fas fa-chevron-right" aria-hidden="true"></span>
    <span class="sr-only">Next slides</span>
  </button>
  
  <ul class="navigation">
    <li>
      <button aria-current="true">
        <span class="sr-only">Go to slide 1</span>
      </button>
    </li>
    <li>
      <button>
        <span class="sr-only">Go to slide 2</span>
      </button>
    </li>
    <li>
      <button>
        <span class="sr-only">Go to slide 3</span>
      </button>
    </li>
    <li>
      <button>
        <span class="sr-only">Go to slide 4</span>
      </button>
    </li>
    <li>
      <button>
        <span class="sr-only">Go to slide 5</span>
      </button>
    </li>
    <li>
      <button>
        <span class="sr-only">Go to slide 6</span>
      </button>
    </li>
    <li>
      <button>
        <span class="sr-only">Go to slide 7</span>
      </button>
    </li>
    <li>
      <button>
        <span class="sr-only">Go to slide 8</span>
      </button>
    </li>
    <li>
      <button>
        <span class="sr-only">Go to slide 9</span>
      </button>
    </li>
  </ul>
</section>
@import url('https://fonts.googleapis.com/css2?family=Merriweather:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400;1,700;1,900&display=swap');

:root {
  --carousel-height: 300px;
  --slide-width: calc(100% / 3);
}

* {
  box-sizing: border-box;
}

body {
  background-color: #f5f5f5;
  padding: 20px;
  font-family: 'Merriweather', serif;
}

/** Wrapper **********************/
.carousel {
  position: relative;
  width: calc(100% - 40px);
  max-width: 900px;
  height: var(--carousel-height);
  margin: 0 auto;
  padding: 0 20px;
}

/** Previous/next buttons ********/
.previous,
.next {
  display: flex;
  justify-content: center;
  align-items: center;
  
  padding: 5px 10px;
  position: absolute;
  top: calc(50% - 16px);
  cursor: pointer;
  font-size: 32px;
  
  border: 0;
  background: none;
}

  .previous { left: -30px; }
  .next { right: -30px; }

/** Slides track ***************/
.slides {
  list-style: none;
  padding: 0;
  margin: 0;
  
  display: flex;
  width: 100%;
  overflow: hidden;
}

/** Individual slides ***********/
.slide {
  flex: 0 0 calc(100% / 3 - 10px);
  
  margin: 0 5px;
  padding: 20px;
  height: var(--carousel-height);
  
  display: flex;
  align-items: center;
  
  font-size: 18px;
  line-height: 26px;
  background-color: white;
}

  @media screen and (max-width: 768px) {
    .slide {
      font-size: 14px;
      line-height: 18px;
      align-items: flex-start;
    }
  }

  .slide a {
    color: black;
    font-weight: bold;
  }

/** Slide dots ******************/
.navigation {
  position: absolute;
  left: 0;
  bottom: -40px;
  
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
}

  .navigation li {
    display: inline-block;
  }

    .navigation li button {
      display: block;
      width: 10px;
      height: 10px;
      margin: 0 5px;
      border: 0;
      border-radius: 100px;
      background-color: rgba(0,0,0,.2);
      cursor: pointer;
    }

      .navigation li button:focus {
        outline-offset: 4px;
      }

      /** Active slide dot */
      .navigation li button[aria-current="true"] {
        background-color: black;
        width: 15px;
        height: 15px;
      }
var previousButton, nextButton;
var slidesContainer, slides, slideDots;
var leftMostSlideIndex = 0;
var slideGap = 5;

window.addEventListener('DOMContentLoaded', function(e) {
  previousButton = document.querySelector('.previous');
  nextButton = document.querySelector('.next');
  slidesContainer = document.querySelector('.slides');
  slides = slidesContainer.querySelectorAll('.slide');
  slideDots = document.querySelectorAll('.navigation li button');

  // Set up previous/next button behaviors
  previousButton.addEventListener('click', previousSlide);
  nextButton.addEventListener('click', nextSlide);
  
  // Ensure that all non-visible slides are impossible to reach.
  hideNonVisibleSlides();
  
  // Set up the slide dot behaviors
  slideDots.forEach(function(dot) {
    dot.addEventListener('click', function(e) {
      goToSlide(Array.prototype.slice.call(slideDots).indexOf(e.target));
    });
  });
});

/** Go to previous slide */
function previousSlide() {
  if(leftMostSlideIndex > 0) {
    goToSlide(leftMostSlideIndex - 1);
  } else {
    goToSlide(slides.length - 1);
  }
}

/** Go to next slide */
function nextSlide() {
  if(leftMostSlideIndex < slides.length - 1) {
    goToSlide(leftMostSlideIndex + 1);
  } else {
    goToSlide(0);
  }
}

/** Go to a specific slide */
function goToSlide(nextLeftMostSlideIndex) {
  // Smoothly scroll to the requested slide
  $(slidesContainer).animate({
    scrollLeft: (slidesContainer.offsetWidth / 3) * nextLeftMostSlideIndex
  }, {
    duration: 200
  });
  
  // Unset aria-current attribute from any slide dots that have it
  slideDots.forEach(function(dot) {
    dot.removeAttribute('aria-current');
  });
  
  // Set aria-current attribute on the correct slide dot
  slideDots[nextLeftMostSlideIndex].setAttribute('aria-current', true);
  
  // Update the record of the left-most slide
  leftMostSlideIndex = nextLeftMostSlideIndex;
  
  // Update each slide so that the ones that are now off-screen are fully hidden.
  hideNonVisibleSlides();
}


/**
  Fully hide non-visible slides by adding aria-hidden="true" and tabindex="-1" when they go out of view
*/
function hideNonVisibleSlides() {
  // Start by hiding all the slides and their content
  slides.forEach(function(slide) {
    slide.setAttribute('aria-hidden', true);
    
    slide.querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(function(focusableElement) {
      focusableElement.setAttribute('tabindex', -1);      
    });
  });
  
  // Since we know 3 slides are visible at a time, make sure that the 3 slides starting with the left-most one are not hidden to anybody.
  if(leftMostSlideIndex < 6) {
    for(var i = leftMostSlideIndex; i < leftMostSlideIndex + 3; i++) {
      slides[i].removeAttribute('aria-hidden');
      
      slides[i].querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(function(focusableElement) {
        focusableElement.removeAttribute('tabindex');      
      });
    }
    
  // Since scrolling stops when the carousel reaches the last three slides, we should make sure that these last three slides stay visible until the user wraps or goes backwards.
  } else {
    for(var i = 6; i < 9; i++) {
      slides[i].removeAttribute('aria-hidden');
      
      slides[i].querySelectorAll('a, button, select, input, textarea, [tabindex="0"]').forEach(function(focusableElement) {
        focusableElement.removeAttribute('tabindex');      
      });
    }
  }
}

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js