Search code examples
javascripthtmlcss

How do I make my Next and Previous buttons move this carousel? I already got it to slide transition automatically, but can't get manual navigation


I am trying to make a carousel for our company LMS homepage. I want it to automatically transition through each carousel item (the banner images) as well as have it so people can click buttons to navigate back or forward through the carousel items without breaking the automatic timer. I have the automatic slide transitioning working and I have the buttons built for manually navigating. I just can't figure out how to make the buttons work. I am not too experienced with Javascript and I am guessing that is what I need to get this all working. So, if anyone could help me figure this out, I'd be eternally grateful!

My entire code is below for reference:

<!DOCTYPE html>
<html>
<head>
    <link tabindex="11" rel="preconnect" href="https://fonts.googleapis.com">
    <link tabindex="11" rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link tabindex="11" href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@300&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <style>
    * {box-sizing: border-box}
    body {
    font-family: "Open Sans"; 
    margin:0; 
    white-space: nowrap;

    }


    * {
    margin: 0;
    padding: 0;
    }

    .carousel_items {
    display: flex;
    overflow: hidden;
    }


    .carousel_item {
    position: relative;
    min-width: 100%;
    max-width: 100%;
    height: 200px;
    transition: all 0.5s linear;
    background-repeat: no-repeat;
    background-size: cover;


    }
    .carousel_text {
    color: #f2f2f2;
    font-size: 4vh;
    padding: 8px 12px;
    position: absolute;
    bottom: 70px;
    width: 26%;
    text-align: center;
    background-color: none;
    font-family: "Open Sans";
    font-size: calc(1.5rem + 0.3vw);


    }

    .item1 {
    background-image: url("https://images.unsplash.com/photo-1707218526479-91d005196060?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");

    }
    .item2 {
    background-image: url("https://images.unsplash.com/photo-1435527173128-983b87201f4d?q=80&w=2067&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");
    }
    .item3 {
    background-image: url("https://images.unsplash.com/photo-1523655223303-4e9ef5234587?q=80&w=2074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");
    }



    .prev, .next {
    cursor: pointer;
    position: absolute;
    top: 10%;
    width: auto;
    padding-top: 30px;
    padding-bottom: 30px;
    padding-right: 15px;
    padding-left: 15px;
    margin-top: -40px;
    color: white;
    font-weight: bold;
    font-size: calc(1.5rem + 0.3vw);
    transition: 0.6s ease;
    border-radius: 0 3px 3px 0;
    user-select: none;
    }


    .next {
    right: 0;
    border-radius: 3px 0 0 3px;
    }

    .prev:hover, .next:hover {
    background-color: rgba(0,0,0,0.8);
    }


    @media only screen and (max-width: 300px) {
    .prev, .next,.text {font-size: 11px}
    }


        
</style>
</head>
<body>

    
    <div class="carousel-container">
  <div class="carousel_items">
    <div class="carousel_item item1">
      <p class="carousel_text">Featured Training</p>
    </div>
    <div class="carousel_item item2">
      <p class="carousel_text">Activity Calendar</p>
    </div>
    <div class="carousel_item item3">
      <p class="carousel_text">Technical Learning</p>
    </div>
    
  </div>
    <a class="prev"><i class="material-icons">chevron_left</i></a>
        <a class="next"><i class="material-icons">chevron_right</i></a> 
        
</div>

    
    </body>
    
    
    
<script>
    const carouselItems = document.querySelectorAll(".carousel_item"); 
let i = 1;

setInterval(() => {
 Array.from(carouselItems).forEach((item,index) => {
   if(i < carouselItems.length){
    item.style.transform = `translateX(-${i*100}%)`
   }
  })

    
  if(i < carouselItems.length){
    i++;
  }
  else{
    i=0;
  }
},4000)
    
    

    </script>



</html> 

I've tried adding triggers to the buttons but I just am far too inexperienced with Javascript. Trying to implement other people's javascript codes for navigation buttons was too hard to get to work as well. So, I never really got anywhere.

Edit: Actually, I made some progress. I didnt know Chatgpt could do this. Managed to get somewhat there using chatgpt like iorgu mentioned. This gets VERY close. Only issue is that it has a random blank banner it transitions too and doesn't transition to my third item, Technical Learning.

Any advice to clean it up? Here is the new script:

const carouselItems = document.querySelectorAll(".carousel_item");
const prevButton = document.querySelector(".prev");
const nextButton = document.querySelector(".next");
let currentIndex = 0;

function goToSlide(index) {
  if (index < 0) {
    index = carouselItems.length - 1;
  } else if (index >= carouselItems.length) {
    index = 0;
  }

  // Slide to the given index
  carouselItems.forEach((item, i) => {
    item.style.transform = `translateX(${(i - index) * 100}%)`;
  });

  currentIndex = index;
}

function slideNext() {
  goToSlide(currentIndex + 1);
}

function slidePrev() {
  goToSlide(currentIndex - 1);
}

// Automatic sliding
setInterval(slideNext, 4000);

// Manual navigation event listeners
prevButton.addEventListener("click", slidePrev);
nextButton.addEventListener("click", slideNext);

Solution

  • Here's the updated version:

    <!DOCTYPE html>
    <html>
    <head>
        <link tabindex="11" rel="preconnect" href="https://fonts.googleapis.com">
        <link tabindex="11" rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link tabindex="11" href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@300&display=swap" rel="stylesheet">
        <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
        <style>
        * {box-sizing: border-box}
        body {
        font-family: "Open Sans"; 
        margin:0; 
        white-space: nowrap;
        }
    
        * {
        margin: 0;
        padding: 0;
        }
    
        .carousel_items {
        display: flex;
        overflow: hidden;
        }
    
        .carousel_item {
        position: relative;
        min-width: 100%;
        max-width: 100%;
        height: 200px;
        transition: all 0.5s linear;
        background-repeat: no-repeat;
        background-size: cover;
        }
        .carousel_text {
        color: #f2f2f2;
        font-size: 4vh;
        padding: 8px 12px;
        position: absolute;
        bottom: 70px;
        width: 26%;
        text-align: center;
        background-color: none;
        font-family: "Open Sans";
        font-size: calc(1.5rem + 0.3vw);
        }
    
        .item1 {
        background-image: url("https://images.unsplash.com/photo-1707218526479-91d005196060?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");
        }
        .item2 {
        background-image: url("https://images.unsplash.com/photo-1435527173128-983b87201f4d?q=80&w=2067&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");
        }
        .item3 {
        background-image: url("https://images.unsplash.com/photo-1523655223303-4e9ef5234587?q=80&w=2074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");
        }
    
        .prev, .next {
        cursor: pointer;
        position: absolute;
        top: 10%;
        width: auto;
        padding-top: 30px;
        padding-bottom: 30px;
        padding-right: 15px;
        padding-left: 15px;
        margin-top: -40px;
        color: white;
        font-weight: bold;
        font-size: calc(1.5rem + 0.3vw);
        transition: 0.6s ease;
        border-radius: 0 3px 3px 0;
        user-select: none;
        }
    
        .next {
        right: 0;
        border-radius: 3px 0 0 3px;
        }
    
        .prev:hover, .next:hover {
        background-color: rgba(0,0,0,0.8);
        }
    
        @media only screen and (max-width: 300px) {
        .prev, .next,.text {font-size: 11px}
        }
    </style>
    </head>
    <body>
        <div class="carousel-container">
            <div class="carousel_items">
                <div class="carousel_item item1">
                    <p class="carousel_text">Featured Training</p>
                </div>
                <div class="carousel_item item2">
                    <p class="carousel_text">Activity Calendar</p>
                </div>
                <div class="carousel_item item3">
                    <p class="carousel_text">Technical Learning</p>
                </div>
            </div>
            <a class="prev" onclick="plusSlides(-1)"><i class="material-icons">chevron_left</i></a>
            <a class="next" onclick="plusSlides(1)"><i class="material-icons">chevron_right</i></a> 
        </div>
        
        <script>
            let currentSlide = 0;
            const carouselItems = document.querySelectorAll(".carousel_item");
    
            function showSlide(index) {
                const totalSlides = carouselItems.length;
                if (index >= totalSlides) {
                    currentSlide = 0;
                } else if (index < 0) {
                    currentSlide = totalSlides - 1;
                } else {
                    currentSlide = index;
                }
                Array.from(carouselItems).forEach((item, i) => {
                    item.style.transform = `translateX(-${currentSlide * 100}%)`;
                });
            }
    
            function plusSlides(n) {
                showSlide(currentSlide + n);
            }
    
            setInterval(() => {
                plusSlides(1);
            }, 4000);
    
            showSlide(currentSlide);
        </script>
    </body>
    </html>

    To address the issue of the auto-sliding being annoying when manually sliding, we can reset the interval each time a manual slide occurs. This way, the auto-sliding will pause and then resume after a fixed period of time. Here's the updated code with this behavior implemented:

    <!DOCTYPE html>
    <html>
    <head>
        <link tabindex="11" rel="preconnect" href="https://fonts.googleapis.com">
        <link tabindex="11" rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link tabindex="11" href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@300&display=swap" rel="stylesheet">
        <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
        <style>
        * {box-sizing: border-box}
        body {
        font-family: "Open Sans"; 
        margin:0; 
        white-space: nowrap;
        }
    
        * {
        margin: 0;
        padding: 0;
        }
    
        .carousel_items {
        display: flex;
        overflow: hidden;
        }
    
        .carousel_item {
        position: relative;
        min-width: 100%;
        max-width: 100%;
        height: 200px;
        transition: all 0.5s linear;
        background-repeat: no-repeat;
        background-size: cover;
        }
        .carousel_text {
        color: #f2f2f2;
        font-size: 4vh;
        padding: 8px 12px;
        position: absolute;
        bottom: 70px;
        width: 26%;
        text-align: center;
        background-color: none;
        font-family: "Open Sans";
        font-size: calc(1.5rem + 0.3vw);
        }
    
        .item1 {
        background-image: url("https://images.unsplash.com/photo-1707218526479-91d005196060?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");
        }
        .item2 {
        background-image: url("https://images.unsplash.com/photo-1435527173128-983b87201f4d?q=80&w=2067&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");
        }
        .item3 {
        background-image: url("https://images.unsplash.com/photo-1523655223303-4e9ef5234587?q=80&w=2074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");
        }
    
        .prev, .next {
        cursor: pointer;
        position: absolute;
        top: 10%;
        width: auto;
        padding-top: 30px;
        padding-bottom: 30px;
        padding-right: 15px;
        padding-left: 15px;
        margin-top: -40px;
        color: white;
        font-weight: bold;
        font-size: calc(1.5rem + 0.3vw);
        transition: 0.6s ease;
        border-radius: 0 3px 3px 0;
        user-select: none;
        }
    
        .next {
        right: 0;
        border-radius: 3px 0 0 3px;
        }
    
        .prev:hover, .next:hover {
        background-color: rgba(0,0,0,0.8);
        }
    
        @media only screen and (max-width: 300px) {
        .prev, .next,.text {font-size: 11px}
        }
    </style>
    </head>
    <body>
        <div class="carousel-container">
            <div class="carousel_items">
                <div class="carousel_item item1">
                    <p class="carousel_text">Featured Training</p>
                </div>
                <div class="carousel_item item2">
                    <p class="carousel_text">Activity Calendar</p>
                </div>
                <div class="carousel_item item3">
                    <p class="carousel_text">Technical Learning</p>
                </div>
            </div>
            <a class="prev" onclick="plusSlides(-1)"><i class="material-icons">chevron_left</i></a>
            <a class="next" onclick="plusSlides(1)"><i class="material-icons">chevron_right</i></a> 
        </div>
        
        <script>
            let currentSlide = 0;
            const carouselItems = document.querySelectorAll(".carousel_item");
            let autoSlideInterval;
    
            function showSlide(index) {
                const totalSlides = carouselItems.length;
                if (index >= totalSlides) {
                    currentSlide = 0;
                } else if (index < 0) {
                    currentSlide = totalSlides - 1;
                } else {
                    currentSlide = index;
                }
                Array.from(carouselItems).forEach((item, i) => {
                    item.style.transform = `translateX(-${currentSlide * 100}%)`;
                });
            }
    
            function plusSlides(n) {
                showSlide(currentSlide + n);
                resetAutoSlide();
            }
    
            function startAutoSlide() {
                autoSlideInterval = setInterval(() => {
                    plusSlides(1);
                }, 4000);
            }
    
            function resetAutoSlide() {
                clearInterval(autoSlideInterval);
                startAutoSlide();
            }
    
            // Start the auto-sliding
            startAutoSlide();
    
            // Initialize the first slide
            showSlide(currentSlide);
        </script>
    </body>
    </html>