Search code examples
javascripthtmlcss

creating card slider sliding individual card by clicking specific button previous or next using javascript


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>my slider</title>
    <link rel="icon" type="image/x-icon" href="../pages/images/favicon.ico">

    <!-- stylesheet  -->
    <style type="text/css">
        body {
            margin: 0px;
            padding: 0px;
        }
        .card-container {
            width: 100%;
            overflow: hidden;
            border: 2.5px solid #000000;
            margin: 20px auto;
        }

        .card-slider {
            display: flex;
            border: 1.5px solid #ff0000;
        }
        
        .card {
            flex: 0 0 auto;
            width: 100%;
            max-width: 300px;
            height: 200px;
            margin-right: 20px;
            transition: transform 0.5s ease;
            text-align: center;
        }

        .prev, .next {
            cursor: pointer;
            position: absolute;
            top: 50%;
            margin-top: -285px;
        }

        .next {
            right: 0px;
        }

    </style>

</head>
<body>
    <div class="card-container">
        <div class="card-slider">
            <div class="card" style="background-color: #0ffff0;">Card One</div>
            <div class="card" style="background-color: #cab;">Card Two</div>
            <div class="card" style="background-color: #12abc2;">Card Three</div>
            <div class="card" style="background-color: #9000bc;">Card Four</div>
            <div class="card" style="background-color: #500bc1;">Card Five</div>
            <div class="card" style="background-color: #acb111;">Card Six</div>
        </div>
    </div>
    <button class="prev" onclick="previousSlide()">&#10094;</button>
    <button class="next" onclick="nextSlide()">&#10095;</button>

    <script type="text/javascript">
        let currentCard = 0;
        let cards = document.querySelectorAll(".card");
        let totalCards = cards.length;

        
        function showCard() {
            cards[currentCard].style.transform = `translateX(${-100}%)`; // trying to move this card left
            /* only first click above statement execute correctly and move card left 
            but also other click above statement execute but not as I expect
            on second, third etc click above statement move card right direction instead of left direction
            I got the correct logic for above statement to excecute correct way to move card in left direction
            I modify the above statement from this  cards[currentCard].style.transform = `translateX(${-100}%)`;
            to this cards[currentCard].style.transform = `translateX(${-100 * (currentCard + 1)}%)`;
            but I want explanation why cards[currentCard].style.transform = `translateX(${-100}%)`; statement
            move cards to right direction not for first click but second, third etc clicks. */


                // after moving above card space created between currentCard and currentCard +1

                // this for loop for  remove space between the cards
                for(let i = currentCard + 1; i < totalCards; i++ ) {
                // cards[i].style.transform = `translateX(${-100}%)`;
                // cards[i].style.transform = `translateX(${-100 * (currentCard + 1) }%)`;
                cards[i].style.transform = `translateX(calc(${-100 * (currentCard + 1)}% + ${(currentCard + 1) * -20}px ))`;
                console.log("Value of i: ", i, " currentCard: ", currentCard);
            }
            // after come out from for loop slide currentCard end of the all other cards
            cards[currentCard].style.transform = `translateX(${100 * totalCards}%)`;

            // increment currentCard
            currentCard++;
        }
        
        function nextSlide () {
            showCard();
        }
    </script>

</body>
</html>

I'm trying to creat a card slider to slide individual cards my logic:

function show card() {...} first statement of this function is slide current card by left -100% after sliding current card space crated between currentCard and currentCard +1 to remove space creating one for loop to slide cards left -100% one by one

after coming out from for loop move current card end of the last card

increment currentCard; function nextSlide() {...} show current card

but first statement of showCard(){...} function and for loop run only once. why?? what's wrong in my code please answer my question or help me to provide a better solution or explain my code step by step please...


Solution

  • Your code has logical problem. The transform must increase after sliding, you can use your currentCard variable for that.

    Solution

    for ( let i = currentCard +1; i < totalCards; i++ ) {
       cards[i].style.transform = `translateX(${-100 * (currentCard + 1) }%)`; // Check this line
       console.log("Value of i: ",i, " currentCard: ",currentCard);
    } 
    

    And now you should include the gap (the margin size) between cards, I will use calc css method to sum percentage (%) with px, here is the code:

    for ( let i = currentCard +1; i < totalCards; i++ ) {
       cards[i].style.transform = `translateX(calc(${-100 * (currentCard + 1)}% + ${(currentCard+1) * -20}px ))`; // Add -20px for the cards margin
       console.log("Value of i: ",i, " currentCard: ",currentCard);
    } 
    

    It is working perfectly now.


    Edit:

    More Explanation

    When you press the next button, the for loop will shift every card by -100%, when you click it again, the cards will not be shifted anymore, because the translateX is still the same as the first click -100%.

    So the logic here is to increase the translateX by -100% every click, like: -100% > -200% > -300% > ...

    In your showCard function, the currentCard is incremented by 1 for each execution (of course the function is executed when button is clicked).

    Now, we can use this variable to apply our logic:

    cards[i].style.transform = `translateX(${-100 * (currentCard + 1) }%)`;
    

    The currentCard initial value is 0, and -100 * 0 is equal to 0, but we need it to be -100 on the first execution, so we need to add 1 to it. -100 * 1 = -100

    And it will work, now to get rid of the white space caused created by margin-right: 20px for each card, we will apply the same logic but with -20 instead of -100, and combine the two operations using css calc method.

    cards[i].style.transform = `translateX(calc(${-100 * (currentCard + 1)}% + ${(currentCard + 1) * -20}px ))`;
    

    The value of translateX (with calc method) will be (in click sequence): -100% - 20px > -200% - 40px > -300% - 60px > ...