Creating a Sweet Content Slider

Learn how to create a content slider from scratch using a dash of the usual suspects (HTML, CSS, JavaScript) and a sweet CSS Transition.
This is a companion discussion topic for the original entry at http://www.kirupa.com/html5/creating_a_sweet_content_slider.htm

hi kirupa, i’m early for javascript. so this article very awesome.

this work to me, but i got some case.
i create jquery animate, when i change width image 960px be 1130px. when the slider with 1130px in cutting process, slide image so messy.

i got the problem, because < li class=“itemLinks” data-pos=“0” > </ li> < li class=“itemLinks” data-pos="-960px" >< /li > , data-post still “960px”. can you help me? how data-pos change be 1130px in the proses jquery animate?
thx in advance, regards :slight_smile:

Unfortunately, I don’t know much about how jquery animate works to help you out :frowning:

When you say “messy”, what do you mean? Is the animation really choppy? If so, I am guessing the CSS transition on the page is interfering with jQuery Animate’s approach for moving things.

thank’s for reply,

so, i have web html just two column ( column left for menu, column right for slide). when column menu be smaller ( width ), so automatically column slider be enlarged…

not messy = dirty, i mean when column slider be enlarged and the shift of slide2, slide3 shown partially. because data-pos="-960px" can’t be changed to -1130px for slide2. so slide3 shown partially

yeah, animation really really choppy…

This was the code that I typed, but it doesn’t seem to be right.

    <!DOCTYPE html>
    <html>

    <head>

    <style>
    #wrapper {
    width: 2200px;
    transform: translate3d(0, 0, 0);
     transition: transform .5s ease-in-out;
}

    .content {
    float: left;
    width: 550px;
    height: 350px;
    white-space: normal;
    background-repeat: no-repeat;
}
    #contentContainer {
    width: 550px;
    height: 350px;
    border: 5px black solid;
    overflow: hidden;
}
    #itemOne {
    background-color: #ADFF2F;
    background-image: url("http://www.kirupa.com/images/blueSquare.png");
}
    #itemTwo {
    background-color: #FF7F50;
    background-image: url("http://www.kirupa.com/images/yellowSquare.png");
}
    #itemThree {
    background-color: #1E90FF;
    background-image: url("http://www.kirupa.com/images/pinkSquare.png");
}
    #itemFour {
    background-color: #DC143C;
    background-image: url("http://www.kirupa.com/images/graySquare.png");
}
    #navLinks {
    text-align: center;
    width: 550px;
}
    #navLinks ul {
        margin: 0px;
        padding: 0px;
        display: inline-block;
        margin-top: 6px;
    }
        #navLinks ul li {
            float: left;
            text-align: center;
            margin: 10px;
            list-style: none;
            cursor: pointer;
            background-color: #CCCCCC;
            padding: 5px;
            border-radius: 50%;
            border: black 5px solid;
        }
            #navLinks ul li:hover {
                background-color: #FFFF00;
            }
            #navLinks ul li.active {
                background-color: #333333;
                color: #FFFFFF;
                outline-width: 7px;
            }
                #navLinks ul li.active:hover {
                    background-color: #484848;
                    color: #FFFFFF;
                }

    </style>
    </head>

    <body>
    <div id="contentContainer">
	    <div id="wrapper">
	    <div id="itemOne" class="content">
 
	    </div>
	    <div id="itemTwo" class="content">
 
	    </div>
	    <div id="itemThree" class="content">
 
	    </div>
	    <div id="itemFour" class="content">
 
	    </div>
	</div>
    </div>
    <div id="navLinks">
        <ul>
            <li class="itemLinks" data-pos="0px"></li>
            < li class="itemLinks" data-pos="-550px"></li>
            <li class="itemLinks" data-pos="-1100px"></li>
            <li class="itemLinks" data-pos="-1650px"></li>
        </ul>
    </div>

    <script>
	// just querying the DOM...like a boss!
    var links = document.querySelectorAll(".itemLinks");
var wrapper = document.querySelector("#wrapper");
 
// the activeLink provides a pointer to the currently displayed item
var activeLink = 0;
 
// setup the event listeners
for (var i = 0; i < links.length; i++) {
    var link = links[i];
    link.addEventListener('click', setClickedItem, false);
 
    // identify the item for the activeLink
    link.itemID = i;
}
 
// set first item as active
links[activeLink].classList.add("active");
 
function setClickedItem(e) {
    removeActiveLinks();
    resetTimer();
    var clickedLink = e.target;
    activeLink = clickedLink.itemID;
 
    changePosition(clickedLink);
}
 
function removeActiveLinks() {
    for (var i = 0; i < links.length; i++) {
        links[i].classList.remove("active");
    }
}
 
// Handle changing the slider position as well as ensure
// the correct link is highlighted as being active
function changePosition(link) {
    link.classList.add("active");
 
    var position = link.getAttribute("data-pos");
    var translateValue = "translate3d(" + position + ", 0px, 0)";
    wrapper.style[transformProperty] = translateValue;
}
var transforms = ["transform",
            "msTransform",
            "webkitTransform",
            "mozTransform",
            "oTransform"];
 
var transformProperty = getSupportedPropertyName(transforms);
 
// vendor prefix management
function getSupportedPropertyName(properties) {
    for (var i = 0; i < properties.length; i++) {
        if (typeof document.body.style[properties[i]] != "undefined") {
            return properties[i];
        }
    }
    return null;
}

//
// The code for sliding the content automatically
//
var timeoutID;
 
function startTimer() {
    // wait 2 seconds before calling goInactive
    timeoutID = window.setInterval(goToNextItem, 2000);
}
startTimer();
 
function resetTimer() {
    window.clearInterval(timeoutID);
    startTimer();
}
 
function goToNextItem() {
    removeActiveLinks();
 
    if (activeLink < links.length - 1) {
        activeLink++;
    } else {
        activeLink = 0;
    }
 
    var newLink = links[activeLink];
    changePosition(newLink);
}
    </script>
    </body>
    </html>

Sorry for the irregularity in the code typing. I am new to embedding the code in a comment :grin:

Do you have a link to your non-working implementation that you can point us to instead? :slight_smile:

I copied and pasted your code, and it worked fine for me. What exactly isn’t working for you? What browser are you testing against?

Hi Kirupa …Many many thanks for the very nice tutorial…

I want to add multiple slide on the same page. I tried but didn’t work.

Can you please help me with this.

Thanks in advance.

Hello ,

im just wondering , how to change slide to fade effect ? Can you help with that ? :slight_smile:
Best regards

Can you elaborate a bit more? Do you want the content to fade in and fade out as you are sliding through each piece?

:smiley:

Roman, I made this fiddle here not sure if this is what you are looking for. If it’s not hopefully ti will get you on the right path.

“content to fade in and fade out as you are sliding through each piece?”

exactly what i want ! :slight_smile:

can’t we use availeble slider like flex slider or carousal slider etc

Thanks for the article. Here is another tutorial about making a slider: http://rafbm.github.io/howtomakeaslider/

Hi there, thanks heaps for the great tutorial.

I just have one question. When you’re viewing the last image of the sequence, and then you click to the first one, instead of ‘wrapping around’ and smoothly transitioning to it, instead you skim back past all the other images.

It’s a little difficult to describe, but you can see what I mean in the example immediately under the ‘Bonus: Automatic Content Slider’ heading. Link: https://www.kirupa.com/html5/creating_a_sweet_content_slider.htm#sliderStart
See the transition from last image to first.

How can I make it so that the transition from last image to first doesn’t pass by the other images? I’d really appreciate any tips. Thank you so much.

That is an interesting question :slight_smile:

Would you like the reset to just go to the second image naturally without revisiting old images? If so, one way you can do that is by having the first image duplicated after the last one. When you reset, you go to the “next” copy of the first image. Behind the scenes, once that happens, you secretly jump from the copy of the first image to the actual first image itself. That can give you the effect you are looking for.

I am just thinking out loud here, so I am hoping others have some better suggestions. I will fiddle with trying to create this sometime this week if I have some time!

Thanks very much for your reply, Kirupa!

What I mean is that when moving from Image4 → Image1, I would like it to be a direct transition, rather than going Image4 [ → Image3 → Image2] → Image1.
Hopefully this makes sense - I think we’re on the same page.

That’s a good idea, of a doubled first image that ‘redirects’ to the actual first image. I don’t totally understand how it would work, but I could probably play around and figure it out.

Yet, it seems that there must be a cleaner way to achieve this. Hmmm. Let me know if you come up with anything! Thanks again :slight_smile:

This is really well put together. Thank you.

Is there anyway of passing different durations into the Javascript so that you can keep some slides onscreen for longer than others?

Ray! There is, but it will require modifying the code a bit to do that. At a high-level, one way to do that would be to store the duration a custom property (or even data- attribute in the HTML) for each element. Once you have that, you can read that duration value and use it on a setTimeout/setInterval call.

I don’t have the time right now to do that, but I’ll look into it by end of the week (unless somebody beats me to it) :slight_smile:

Thank you Kirupa, I wondered about a data- tag but they are new to me and I wasn’t sure how to code them. Will investigate…