admin管理员组

文章数量:1122846

I'm trying to make carousel with 3 items displayed that the width scales of 100%/3 of its parent.

The next prev button works fine and the show-hide function works well if only they reach the edge of the element [0] and [1].

If I start from [0] the prev button still hidden and when I press the next button, the item will be scrolled perfectly and the prev button will be shown, but when I reach the last item the next button doesn't hide immediately unless I press once again, then it will be hidden, same as the prev button, if I go back to the first element it won't immediately hidden, unless I press once again.

I want the next prev button to be hidden as soon as I have displayed the first/last 3 items

const carousel = document.querySelector(".container5-carousel");
const firstDiv = carousel.querySelectorAll(".carousel-item")[0];
const carouselBtn = document.querySelectorAll(".carousel-button i");

let firstDivWidth = firstDiv.clientWidth + 14;
let scrollWidth = carousel.scrollWidth - carousel.clientWidth;

const showHideButton = () => {
  carouselBtn[0].style.display = carousel.scrollLeft == 0 ? "none" : "block";
  carouselBtn[1].style.display = carousel.scrollLeft == scrollWidth ? "none" : "block";
}

carouselBtn.forEach(btn => {
  btn.addEventListener("click", () => {
    if (btn.id == "prev") {
      carousel.scrollLeft -= firstDivWidth;
    } else {
      carousel.scrollLeft += firstDivWidth;
    }

    setTimeout(() => showHideButton(), 60);
  })
});
.container5 {
  width: 100%;
  margin: auto;
  align-items: center;
  background-color: #fdd8d8;
  padding: 2rem 0;
}

.container5-subcontainer {
  width: 100%;
  position: relative;
}

.carousel-wrapper {
  width: 80%;
  max-width: 1200px;
  height: fit-content;
  margin: 0 auto;
  position: relative;
  padding: 1rem 0;
}

.container5-carousel {
  margin: 0 auto;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100%/3) - 2rem);
  overflow: hidden;
  padding: 2rem 0;
  gap: 3rem;
  white-space: nowrap;
  scroll-behavior: smooth;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding: 0;
}

.carousel-item {
  border-radius: 15px;
  background-color: #ffffff;
  box-shadow: 0 -0.4rem 1rem 0.2rem rgba(0, 0, 0, 0.12);
  scroll-snap-align: center;
}

.carousel-button i {
  font-size: 1.5rem;
  color: #222222;
  width: 50px;
  height: 50px;
  line-height: 50px;
  text-align: center;
  border-radius: 50%;
  background-color: #ffffffc4;
  margin: 0;
  box-shadow: 3px 3px 9px 5px rgba(0, 0, 0, 0.12);
  position: absolute;
  min-width: 50px;
  min-height: 50px;
  cursor: pointer;
}

.carousel-button i:first-child {
  left: 0;
  display: none;
}

.carousel-button i:last-child {
  right: 0;
}
<div class="container5">
  <h1>Portfolio!</h1>
  <div class="container5-subcontainer">
    <div class="carousel-wrapper">
      <div class="carousel-button">
        <i id="prev" class="fa-solid fa-angle-left"></i>
        <i id="next" class="fa-solid fa-angle-right"></i>
      </div>

      <div class="container5-carousel">
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample3.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample4.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample5.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample6.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample3.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample4.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample5.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample6.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
      </div>
      <div class="container5-vm flex-grow">
        <a class="content5-button" href="#">View More &rarr; </a>
      </div>
    </div>
  </div>
</div>

I'm trying to make carousel with 3 items displayed that the width scales of 100%/3 of its parent.

The next prev button works fine and the show-hide function works well if only they reach the edge of the element [0] and [1].

If I start from [0] the prev button still hidden and when I press the next button, the item will be scrolled perfectly and the prev button will be shown, but when I reach the last item the next button doesn't hide immediately unless I press once again, then it will be hidden, same as the prev button, if I go back to the first element it won't immediately hidden, unless I press once again.

I want the next prev button to be hidden as soon as I have displayed the first/last 3 items

const carousel = document.querySelector(".container5-carousel");
const firstDiv = carousel.querySelectorAll(".carousel-item")[0];
const carouselBtn = document.querySelectorAll(".carousel-button i");

let firstDivWidth = firstDiv.clientWidth + 14;
let scrollWidth = carousel.scrollWidth - carousel.clientWidth;

const showHideButton = () => {
  carouselBtn[0].style.display = carousel.scrollLeft == 0 ? "none" : "block";
  carouselBtn[1].style.display = carousel.scrollLeft == scrollWidth ? "none" : "block";
}

carouselBtn.forEach(btn => {
  btn.addEventListener("click", () => {
    if (btn.id == "prev") {
      carousel.scrollLeft -= firstDivWidth;
    } else {
      carousel.scrollLeft += firstDivWidth;
    }

    setTimeout(() => showHideButton(), 60);
  })
});
.container5 {
  width: 100%;
  margin: auto;
  align-items: center;
  background-color: #fdd8d8;
  padding: 2rem 0;
}

.container5-subcontainer {
  width: 100%;
  position: relative;
}

.carousel-wrapper {
  width: 80%;
  max-width: 1200px;
  height: fit-content;
  margin: 0 auto;
  position: relative;
  padding: 1rem 0;
}

.container5-carousel {
  margin: 0 auto;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100%/3) - 2rem);
  overflow: hidden;
  padding: 2rem 0;
  gap: 3rem;
  white-space: nowrap;
  scroll-behavior: smooth;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding: 0;
}

.carousel-item {
  border-radius: 15px;
  background-color: #ffffff;
  box-shadow: 0 -0.4rem 1rem 0.2rem rgba(0, 0, 0, 0.12);
  scroll-snap-align: center;
}

.carousel-button i {
  font-size: 1.5rem;
  color: #222222;
  width: 50px;
  height: 50px;
  line-height: 50px;
  text-align: center;
  border-radius: 50%;
  background-color: #ffffffc4;
  margin: 0;
  box-shadow: 3px 3px 9px 5px rgba(0, 0, 0, 0.12);
  position: absolute;
  min-width: 50px;
  min-height: 50px;
  cursor: pointer;
}

.carousel-button i:first-child {
  left: 0;
  display: none;
}

.carousel-button i:last-child {
  right: 0;
}
<div class="container5">
  <h1>Portfolio!</h1>
  <div class="container5-subcontainer">
    <div class="carousel-wrapper">
      <div class="carousel-button">
        <i id="prev" class="fa-solid fa-angle-left"></i>
        <i id="next" class="fa-solid fa-angle-right"></i>
      </div>

      <div class="container5-carousel">
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample3.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample4.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample5.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample6.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample3.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample4.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample5.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample6.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
      </div>
      <div class="container5-vm flex-grow">
        <a class="content5-button" href="#">View More &rarr; </a>
      </div>
    </div>
  </div>
</div>

Share Improve this question edited Nov 21, 2024 at 17:35 mplungjan 177k28 gold badges180 silver badges240 bronze badges asked Nov 21, 2024 at 17:29 marsel herdianmarsel herdian 31 bronze badge 1
  • I made you a snippet. Please click edit, then scroll down and click "edit above snippet" and add relevant frameworks or functions from CDN – mplungjan Commented Nov 21, 2024 at 17:36
Add a comment  | 

1 Answer 1

Reset to default 0

You could use the first and last elements getBoundingClientRect().left and add that with the scrollX of the window and compare that with the parents getBoundingClientRect().left positions respectively.

To check the first elements position see if the elements getBoundingClientRect().left position + the window.scrollX position is greater than or equal to the parents getBoundingClientRect().left position.

To check the last elements position relative to its parent, just add the getBoundingClientRect().left + getBoundingClientRect().width + window.scrollX for the last elements position and then compare it to the getBoundingClientRect().left + getBoundingClientRect().width on the parentNode, wrap the last elements calculation in Math.floor() to remove any unwanted decimals. Set the style appropriately within the conditionals.

I added the showHideButton method to a scroll eventListener on the parent element.

Note: Moved firstDiv, firstDivWidth, and scrollWidth into the btn eventListener methods scope, in case you expand the size of the page after the page loads and caches the clientWidth of firstDiv. This way when you press the button it will query that element then and get its current clientWidth.

See further explanation in the code.

Let me know if anything is unclear or if this is not what you were looking for.

const carouselBtn = document.querySelectorAll(".carousel-button i");
const carousel = document.querySelector(".container5-carousel");

const showHideButton = (e) => {
  const carouselItem = e.target.querySelectorAll(".carousel-item");
  // get the first element in the carousel-item node list 
  // and get its BoundingClientRect
  const firstItemRect = carouselItem[0].getBoundingClientRect();
  // get the last element in the carousel-item node list
  // using carouselItem[carouselItem.length-1]
  // and get its BoundingClientRect
  const lastItemRect = carouselItem[carouselItem.length - 1].getBoundingClientRect();
  // parents boundingClientRect()
  const contRect = e.target.getBoundingClientRect();
  // compare the windows scrollX position + the position of the element rect.left position
  // in relation to the parent elements rect.left position
  firstItemRect.left + window.scrollX >= contRect.left ?
    carouselBtn[0].style.display = "none" :
    carouselBtn[0].style.display = "block";
  // use Math.floor to round to lowest whole
  // get the last elements rect left + its width + window scrollX position and compare
  // to the parents rect.left + rect.width
  Math.floor(lastItemRect.left + lastItemRect.width + window.scrollX) <= contRect.left + contRect.width ?
    carouselBtn[1].style.display = "none" :
    carouselBtn[1].style.display = "block";
}

const slideElement = (e) => {
  // moved the following three variables into btn event scope
  const firstDiv = carousel.querySelectorAll(".carousel-item")[0];
  let firstDivWidth = firstDiv.clientWidth + 14;
  let scrollWidth = carousel.scrollWidth - carousel.clientWidth;
  if (e.target.id == "prev") {
    carousel.scrollLeft -= firstDivWidth;
  } else {
    carousel.scrollLeft += firstDivWidth;
  }
}

carouselBtn.forEach(btn => {
  btn.addEventListener("click", slideElement);
});

// eventListener for scroll on the parent element
carousel.addEventListener('scroll', showHideButton);
.container5 {
  width: 100%;
  margin: auto;
  align-items: center;
  background-color: #fdd8d8;
  padding: 2rem 0;
}

.container5-subcontainer {
  width: 100%;
  position: relative;
}

.carousel-wrapper {
  width: 80%;
  max-width: 1200px;
  height: fit-content;
  margin: 0 auto;
  position: relative;
  padding: 1rem 0;
}

.container5-carousel {
  margin: 0 auto;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100%/3) - 2rem);
  overflow: hidden;
  padding: 2rem 0;
  gap: 3rem;
  white-space: nowrap;
  scroll-behavior: smooth;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding: 0;
}

.carousel-item {
  border-radius: 15px;
  background-color: #ffffff;
  box-shadow: 0 -0.4rem 1rem 0.2rem rgba(0, 0, 0, 0.12);
  scroll-snap-align: center;
}

.carousel-button i {
  font-size: 1.5rem;
  color: #222222;
  width: 50px;
  height: 50px;
  line-height: 50px;
  text-align: center;
  border-radius: 50%;
  background-color: #ffffffc4;
  margin: 0;
  box-shadow: 3px 3px 9px 5px rgba(0, 0, 0, 0.12);
  position: absolute;
  min-width: 50px;
  min-height: 50px;
  cursor: pointer;
}

.carousel-button i:first-child {
  left: 0;
  display: none;
}

.carousel-button i:last-child {
  right: 0;
}


/* added css rule to remove any text overflow */

.carousel-item p {
  overflow-x: hidden;
}
<div class="container5">
  <!--<h1>Portfolio!</h1> removed for demo -->
  <div class="container5-subcontainer">
    <div class="carousel-wrapper">
      <div class="carousel-button">
        <i id="prev" class="fa-solid fa-angle-left"></i>
        <i id="next" class="fa-solid fa-angle-right"></i>
      </div>

      <div class="container5-carousel">
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Accusantium recusandae deleniti voluptates pariatur modi illo corporis obcaecati repudiandae perferendis tempore dolor consequatur dolorem, alias magni id sequi libero amet eaque!</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample3.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample4.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample5.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample6.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample3.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample4.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample5.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample6.jpg" alt="">
          <h2>Product Title</h2>
          <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit.</p>
        </div>
        <div class="carousel-item">
          <img class="carousel-img" src="assets/img/sample2.jpg" alt="">
          <h2>Product Title</h2>
          <p>This is the last item.</p>
        </div>
      </div>
      <div class="container5-vm flex-grow">
        <a class="content5-button" href="#">View More &rarr; </a>
      </div>
    </div>
  </div>
</div>

本文标签: javascriptnextprev button not hiding when reaching firstlast element using scrollsnapalignStack Overflow