New CSS carousel features let a scroll container generate previous/next buttons and markers. The browser keeps them in sync with scroll snap, which removes a surprising amount of JavaScript.

.carousel {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-marker-group: after;
}

.carousel::scroll-button(left) {
  content: '<' / 'Previous';
}

.carousel::scroll-button(right) {
  content: '>' / 'Next';
}

.carousel > * {
  flex: 0 0 80%;
  scroll-snap-align: center;
}

.carousel > *::scroll-marker {
  content: attr(data-label);
}  

The newer pseudo-elements are still settling, so keep the HTML useful without them. More info on MDN.