Javascript image carousel

Hi there I am having difficulty in figuring out the logic in an image carousel using vanilla js, can anyone help?

You will need to provide the full code you are using and explain what the problem is that you are encountering before someone can offer any relevant help.

Or have you not coded anything yet and want some pointers in where to start?

There are about a million sliders out there (and tutorials) so there’s plenty you can copy and learn from.:slight_smile:

basically i have been learning js for a year part time now and thought i need to start actually creating things myself now to consolidate my knowledge , so i thought image slider as its common on websites i tried different codes but nothing worked

this is my js :slight_smile:


const imgs = document.getElementById('imgs')
const btnPrev = document.getElementById('button-prev')
const btnNext = document.getElementById('button-next')

const slides = document.querySelectorAll('.image-container img')
let index = 0

const slider = ()=>{

     if(index> slides.length-1){
        index = 0
     } else if (index < slides[0]){
        slides++
     }

     slides.forEach(slide=>{ 
        console.log(slide)
        slide.style.transform = `translateX(${-index * 500}px)`
     })
}
const interval  = setInterval(slider, 3000)

slider()

html =


 <div class="carousel">
            <div class="image-container" id="imgs">
       
                <img src="/images/image-1.jpg" width="500px" height="500px" alt="">  
                <img src="/images/image-2.jpg"  width="500px" height="500px" alt="">      
                <img src="/images/image-3.jpg"  width="500px" height="500px" alt="">          
                <img src="/images/image-4.jpg"  width="500px" height="500px" alt="">      
                <img src="/images/image-5.jpg"  width="500px" height="500px" alt="">            
            </div>
        <div class="button-container">
            <button id=" button-prev" class="btn">Previous</button>
            <button id="button-next" class="btn">Next</button>
        </div>
    </div>

Simplifying Code (The Modulo Operator)

This may need a bit of looking at. It’s not doing what you expect it to do.

So this can be reduced somewhat, if I am understanding what you are trying to do, by use of the Modulo operator.

Modulo: For a % b (read: “a mod b”), the value returned is the remainder after dividing a by b. So:
5 % 3 = 2
2 % 3 = 2
1000 % 25 = 0

So if you want to add 1 to the value, but wrap around if it hits the limit of the array, we can shorten all of that code down to one line:

index = ++index % slides.length;

A bit complex but what it says is:

index = ++index % slides.length;

Assign to index the value:
Add 1 to index, and return the new value;
Modulo that value by the length of the slides array.

Let’s say you’ve got 3 slides.
If index is 0, and you execute this line, the blue part gives the value 1, the modulo does 1 % 3, and gives 1. So index is now 1.
Repeat that with index 1, and 2%3 gives you 2. So index is 2.
When index is 2 and you run that line, the blue part gives a value 3. 3%3 however, will yield 0 (because 3/3 = 1 with no remainder). So index gets a 0, and you’ve reset the index.

NOTE: There is a choice that every language has to make when it comes to the modulo of negative numbers. In Javascript, the modulo of a negative number will yield a negative value, because javascript does not use Euclidean Division to figure out the remainder.


forEach Functionality

Now, what you appear to be trying to do with the index is actually doable with a feature of the forEach. forEach will actually yield up to 3 arguments to the function; the second parameter yielded is the index of the element currently being processed.

So instead of:
slides.forEach(slide=>{
We can do:

slides.forEach((slide,index)=>{
and index will be 0 for the first loop, 1 for the second, etc… without you needing to code the math in at all!


Combining the Lessons: What I Think You are Trying to Do

(This is me guessing a bit, so feel free to tell me i’m wrong.)

What it looks like you’re trying to do to me is that you want to use “index” to refer to the image currently ‘shown’ the slider, and that you want that slide’s translate to be 0.

We can work with that.

We have a couple of things using the name “index” here, so let me use a few of my own terms, to try and keep it clear.

I will call the current slide value current. We will assume that this starts as a 0.
Each time we run the slider function, we want to do two things:

  1. Add 1 to current, wrapping it around if it goes beyond the length of the array.
  2. Change all of the slides’ translate values, to move them around.

Step 1 is the modulo outlined above, except instead of index it’s current.
Step 2 will use the index value of the forEach also outlined above to do the math.

Let’s assume you’re pulling (slide,index) from the forEach.
What value do you want to give to the translate function for a given index, if you’re looking at the current slide?

Well, the current slide you want to return 0; the next slide you want to return 1.

If current is 0, this is simple:

index target
0 0
1 1
2 2
3 3
4 4

Simple enough: current + index.
But that doesn’t work if current is, lets say, 2.

index target current+index
0 3 2
1 4 3
2 0 4
3 1 5
4 2 6

Well that didnt work. We can see that at some point, we’re going to need the idea of “looping back”, so a modulo is going to sneak into our math here somewhere…

So let’s try slapping a modulo on the end.

index target (current+index)%slide.length
0 3 2
1 4 3
2 0 4
3 1 0
4 2 1

Close… the value is off slightly. And if current is, say, 4, this gets more off-kilter:

index target (current+index)%slide.length
0 1 4
1 2 0
2 3 1
3 4 2
4 0 3

The key idea here is that we want the value of the slide at current to be 0. So some subtraction needs to go in there… I could spend more time explaining how I work through the math, but the eventual outcome is that the math you want at the end is ((slide.length+index-current)%slide.length

(current = 2)

index target ((slide.length+index-current)%slide.length
0 3 4
1 4 0
2 0 1
3 1 2
4 2 3

(current = 4)

index target ((slide.length+index-current)%slide.length
0 1 1
1 2 2
2 3 3
3 4 4
4 0 0

(Why do we need to add the slide length? See the note at the end of the modulo section.)

1 Like

Shouldn’t that be index++ ?

and you want slidelength -2 as you don’t want the last one to slide away and leave a blank space

if (index > slides.length - 2) 

I’ve rolled it into a codepen.

Hope that helps.

[edit]
I see @m_hutley beat me to it so I should read his post first as my JS is pretty basic.:slight_smile:

[edit]

1 Like

Pfft. Your Javascript is fine, Paul. I apparently decided to go college professor this morning and give a dissertation on the maths behind the code :stuck_out_tongue:

1 Like

thanks for your response my code has started to work but still not behaving like i expected it, only 2 images are sliding. my code looks same as yours?

I dont understand why its slides.length - 2, if slides.length-1 means the last image node then i want it to go back to the start does slides.length -1 then return index = 0 not correlate to that?

thank you for taking your time to respond to me, the answer you gave is too advance for me as i could follow and process most of it, but i will re-read it tomorrow morning on a fresher mind

Put your code it into a codepen so we can see where you are going wrong (codepen is free and a good tool for sharing code). You don’t show your CSS either so it could be a mixture of both.

Slides.length is the number of images. However the variable called index is starting from zero. Therefore you need -2. (If the index variable was starting at 1 then slides.length-2 would be correct.)

HMM by i initialised my index at 0, let me see how i can use codepen and will post shortly

my codepen hope it works https://codepen.io/fahim22/pen/QWYJKXK
so basically out of 5 images it displays 3 and then blank then starts over

Yeah, i’m pretty sure it’s something CSS’y at this point…
Yours:

Paul’s:

omg i think i just got it my flex justify content was centred so it was starting and image node 1 insted of 0, i changed it to start and now its working

1 Like

just figured it out thank you , i had set justify content to centre insted of start so it wasnt starting the roll and the begining

strange!! my code actually works but on the codepen it didnt?

It’s possible the final page is loading extra CSS you didnt put into the codepen?

my bad its working, so anyway i spent probably 12 hours in total over seven days trying to figure out how to make this and its not even complete, now i can work on the next and previous buttons, is this how it is when starting off or am i bad at this

2 Likes

I mean, are you asking me if problems only occur when you’re starting out? No.
I run into problems every time I code something. That’s the nature of coding.

What happens is as you do it more and more, you build up a history of “Oh yeah, I saw this before, the solution was…”, and can solve your own problems quicker.

2 Likes

Would it not be better to think about how you can make this responsive before you start adding loads of JS that relies on a fixed dimension of 500px width and height?

If instead you use percentages then you can make the image responsive using aspect-ratio and object-fit and then you don’t need to change the js for different screens sizes.

Here’s your code slightly adapted as proof of concept.

The js only needed the 500 changed to a 100% instead. Now the slider will display on a phone or a large desktop. The css has a number of pertinent changes though.

When you code that you will need to work out how to slide the images in the other direction when selecting the previous button as usually the slider would continue in that reverse direction once a previous slide has been selected (and vice versa for next).

Assuming you are keeping the transition effect you will need to think about whether you want the current transition to finish before the next/previous buttons are clicked to avoid a jump half way through a slide (You will need to look at transition-end for this).

You may want to consider whether the slide should loop back to the first seamlessly or whether it flashes back to the start as in the current example.

There’s a lot to think about before you start coding as one thing may depend on the other :slight_smile:

thanks for this, right now i just want to create a working carousel with next and prev functionality to develop my js coding skills, i was working on this earlier on but to no avail but gna keep thinking about it till i get it if not i will request for some assistance.