Making a Pure CSS Featured Image Slider

Making a Pure CSS Featured Image Slider

Demo

CSS3 has given us some pretty power­ful tools. Not so long ago we had to use JavaScript if we wanted an image slider, but now it isn’t too hard to do it with only CSS. This art­icle will explain how.

I have tried to keep this as to the point as pos­sible, so if you want me to cla­rify any­thing, feel free to ask. Also, keep in mind that you will need to use browser pre­fixes where required.

The plan

  1. The markup
  2. Basic styl­ing
  3. Navigating
  4. Finishing touches

Want to see the fin­ished code? Click here.

Step 1: The markup

Let’s get the found­a­tion worked out. This slider will con­tain four pan­els, so let’s write up an unordered list con­tain­ing four images. We will give it a class of slider so that we can tar­get it in our style sheet. I am using images that are roughly 400 × 240, but feel free to use whatever size you would like.

<ul class="slider">
    <li>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 1">
    </li>
    <li>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 2">
    </li>
    <li>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 3">
    </li>
    <li>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 4">
    </li>
</ul>

Step 2: Basic styling

I am using em instead of px to size up this slider. If you aren’t that com­fort­able with using em then this art­icle may help, oth­er­wise, feel free to simply mul­tiple any value by 16, and use that as a pixel value instead.

.slider {
    height: 15em;
    width: 25em;
}
.slider li {
    list-style: none;
    position: absolute;
}
.slider img {
    height: 15em;
    width: 25em;
    vertical-align: top;
}

The height and width on the image aren’t strictly required, but they do guar­an­tee that any lar­ger images are res­ized to fit within the slider.

Step 3: Navigating

Now that we have the basics sor­ted, let’s intro­duce a tech­nique that will allow us to nav­ig­ate between the slides. To do this, I am going to use what is known as the check­box hack (see here for more information).

Let’s add some form ele­ments to our markup.

<ul class="slider">
    <li>
        <input type="radio" id="slide1" name="slide" checked>
        <label for="slide1"></label>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 1">
    </li>
    <li>
        <input type="radio" id="slide2" name="slide">
        <label for="slide2"></label>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 2">
    </li>
    <li>
        <input type="radio" id="slide3" name="slide">
        <label for="slide3"></label>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 3">
    </li>
    <li>
        <input type="radio" id="slide4" name="slide">
        <label for="slide4"></label>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 4">
    </li>
</ul>

You may have noticed that I marked the first radio but­ton as checked. The checked image will be the one show­ing on page load. The oth­ers will be hid­den so that we can fade them in when they are selec­ted. We will do that via the fol­low­ing CSS:

.slider input {
    display: none;
}
.slider label {
    background-color: #111;
    bottom: .5em;
    cursor: pointer;
    display: block;
    height: .5em;
    position: absolute;
    width: .5em;
    z-index: 10;
}
.slider li:nth-child(1) label {
    left: .5em;
}
.slider li:nth-child(2) label {
    left: 2em;
}
.slider li:nth-child(3) label {
    left: 3.5em;
}
.slider li:nth-child(4) label {
    left: 5em;
}
.slider img {
    opacity: 0;
    visibility: hidden;
}
.slider li input:checked ~ img {
    opacity: 1;
    visibility: visible;
    z-index: 10;
}

Awesome, we now have an inter­act­ive slider using only CSS!

Step 4: Finishing touches

Alright, now it’s time to have some fun! Feel free to style the slider how­ever you like. If you would like to see what I did, keep reading.

With the use of pseudo-elements and box-shadow, I’m going to trans­form our bor­ing look­ing slider into a pic­ture frame. I’ll use a few trans­itions to make it smooth, and hide the nav­ig­a­tion ele­ments until the slider is hovered. Check out my final code below.

Final product

<ul class="slider">
    <li>
        <input type="radio" id="slide1" name="slide" checked>
        <label for="slide1"></label>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 1">
    </li>
    <li>
        <input type="radio" id="slide2" name="slide">
        <label for="slide2"></label>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 2">
    </li>
    <li>
        <input type="radio" id="slide3" name="slide">
        <label for="slide3"></label>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 3">
    </li>
    <li>
        <input type="radio" id="slide4" name="slide">
        <label for="slide4"></label>
        <img src="http://joshnh.com/2012/08/14/making-a-pure-css-featured-image-slider/"Panel 4">
    </li>
</ul>​

.slider {
    background-color: #fff;
    box-shadow: inset 0 0 2px hsla(0,0%,0%,.2),
                0 3px 1px hsla(0,0%,100%,.75),
                0 -1px 1px 2px hsla(0,0%,0%,.1);
    height: 15em;
    left: 50%;
    margin: -8em -13em;
    padding: .5em;
    position: absolute;
    top: 50%;
    width: 25em;
}
.slider:before {
    background-color: #22130c;
    bottom: -2.5em;
    box-shadow: inset 0 1px 1px 1px hsla(0,0%,100%,.2),
                inset 0 -2px 1px hsla(0,0%,0%,.4),
                0 5px 50px hsla(0,0%,0%,.25),
                0 20px 20px -15px hsla(0,0%,0%,.2),
                0 30px 20px -15px hsla(0,0%,0%,.15),
                0 40px 20px -15px hsla(0,0%,0%,.1);
    content: '';
    left: -2.5em;
    position: absolute;
    right: -2.5em;
    top: -2.5em;
    z-index: -1;
}
.slider:after {
    background-color: #fff5e5;
    bottom: -1.5em;
    box-shadow: 0 2px 1px hsla(0,0%,100%,.2),
                0 -1px 1px 1px hsla(0,0%,0%,.4),
                inset 0 2px 3px 1px hsla(0,0%,0%,.2),
                inset 0 4px 3px 1px hsla(0,0%,0%,.2),
                inset 0 6px 3px 1px hsla(0,0%,0%,.1);
    content: '';
    left: -1.5em;
    position: absolute;
    right: -1.5em;
    top: -1.5em;
    z-index: -1;
}
.slider li {
    box-shadow: 0 -1px 0 2px hsla(0,0%,0%,.03);
    list-style: none;
    position: absolute;
}
.slider input {
    display: none;
}
.slider label {
    background-color: #111;
    background-image: linear-gradient(transparent, hsla(0,0%,0%,.25));
    border: .2em solid transparent;
    bottom: .5em;
    border-radius: 100%;
    cursor: pointer;
    display: block;
    height: .5em;
    left: 24em;
    opacity: 0;
    position: absolute;
    transition: .25s;
    width: .5em;
    visibility: hidden;
    z-index: 10;
}
.slider label:after {
    border-radius: 100%;
    bottom: -.2em;
    box-shadow: inset 0 0 0 .2em #111,
                inset 0 2px 2px #000,
                0 1px 1px hsla(0,0%,100%,.25);
    content: '';
    left: -.2em;
    position: absolute;
    right: -.2em;
    top: -.2em;
}
.slider:hover label {
    opacity: 1;
    visibility: visible;
}
.slider input:checked + label {
    background-color: #fff;
}
.slider:hover li:nth-child(1) label {
    left: .5em;
}
.slider:hover li:nth-child(2) label {
    left: 2em;
}
.slider:hover li:nth-child(3) label {
    left: 3.5em;
}
.slider:hover li:nth-child(4) label {
    left: 5em;
}
.slider img {
    height: 15em;
    opacity: 0;
    transition: .25s;
    width: 25em;
    vertical-align: top;
    visibility: hidden;
}
.slider li input:checked ~ img {
    opacity: 1;
    visibility: visible;
    z-index: 10;
}

Tweet this

Comments

  1. Habibur Rahman

    Hi

    I hv used it and make this. Awesome tnx a lot.

    But where is auto scrolling. Images not auto going. Is there any way for auto going in css/css3.

    Habib

  2. Josh

    Hi, Habib. If you want a scrolling slider with nav­ig­a­tion, then I would recom­mend using one based on JavaScript, as it will have much bet­ter func­tion­al­ity and browser support.

  3. kanth

    Hi,

    It is a great tutorial.…. Could you please tell me how to put a imac desktop image at the back­ground for image slider..?

  4. Josh

    I’m not sure I under­stand exactly what you mean, Kanth. Would you mind elaborating?

  5. Josh

    Okay. Tim uses a par­ent ele­ment that has the mon­itor as a back­ground image with the slider con­tained within. That is also how I would handle it.

  6. Alexis

    Hi Josh

    I’m try­ing to imple­ment your cod­ing to cre­ate my first CSS image slide ever. I have read that to use trans­ition I need to add a browser pre­fix to the start of the prop­erty. Could you let me know what this pre­fix would be and where exactly in the HTML I should insert it?

    Many thanks,

    Alexis

  7. Joshua

    So, from the pre­vi­ous ques­tion about it not being able to auto-transition, are you say­ing that there is NO way other than javas­cript or Jquery? purely CSS3?

  8. Josh

    Joshua, you can make the slides auto trans­ition using CSS anim­a­tions, but you then lose the abil­ity to nav­ig­ate between slides.

  9. Josh

    Nice find, Tom! It would be great if CSS allowed us to have a timed trans­ition between pan­els, as well as nav­ig­a­tion to quickly select which panel we wanted to view.

  10. Lith

    is it pos­sible to add a link in the slide images ?

  11. filip

    hello,
    I really like your blog, it’s help­ful and very com­pre­hens­ibly writ­ten. I’m just a beg­giner but I could under­stand most of it.
    I’d like to use a pure css slider but instead of radio but­tons I want simple nav but­tons — you know: “prev” and “next”. So: is there an easy way to change your example to do this or I should bet­ter look for another example of a css slider?
    (I hope you can under­stand my ques­tion — my eng­lish is rather poor)
    cheers!

  12. filip

    Thanks! Now I just need to put ‘next’ and ‘prev’ but­tons out­side the image but I think I can do this alone. I will exper­i­ment a bit. I’ve star­ted to learn css and html one month ago but it’s amus­ing to change a code and see what will hap­pen…
    Once again: thank you very much!

  13. Marcello Africano

    Wow Josh, great tutorial, I love it! You seem to be a really enthu­si­astic web developer, eager to help people out, and I had a ques­tion. So here’s the deal…

    I’m 14 and I’m a fresh­man in high school and I make music, graph­ics, and web­sites, but I don’t have any­body to talk to or con­tact whenever I run into any prob­lems besides people on for­ums. But people on for­ums are not always reli­able (or excep­tion­ally tal­en­ted web developers like your­self), so I was won­der­ing this… could I email you, and you give me help­ful tips and advice maybe, but if not, I under­stand your busy (being great), but if so, that would be so great!

    - Thanks so much,
    – Marcello Africano -

  14. Josh

    Sure, Marcello. Feel free to email me and I will help out as much as I can.

  15. Sara

    Hi– I was using the CSS you recom­men­ded for a slider with arrows (http://codepen.io/joshnh/pen/zbaLI) but I’m hav­ing the prob­lem that every time I click the next or pre­vi­ous arrow, my page jumps so the div .slider is at the top of the page, regard­less of where you were in the page to begin with. Is there a way to get around this?

    Thanks– your tutorial was great!

  16. Josh

    Hi, Sara. Unfortunately you can’t stop the page jump with CSS, it is stand­ard beha­viour. You could do it with JavaScript, but if you take that approach, then you would be bet­ter off doing the whole slider using JavaScript.

  17. ashok kumar patel

    Its a good help for us.for this a lot of thanks.

  18. Narender Yadav

    Just learn the Html css at start­ing point

    ;;;;;
    That’s very good, Nice & I’an give the 10 point out 10.

  19. Nathaniel Flick

    Great tut! One thing, FF requires height/width in order to cor­rectly apply z index, which comes in handy if you want to cycle through images but not hide them.

  20. Stephen Meszaros

    Fantastic art­icle and lovely, lovely site! Very glad to have stumbled upon it. I love the design coupled with your per­sonal and relat­able style of writ­ing. I’m going to need to mess around with this one spe­cific­ally as I am try­ing to add some slider’s to my port­fo­lio site.

    Keep it up!

  21. rakesh

    hi,
    i want to add more than 4 images how to add

  22. Josh

    To add fur­ther images, just add extra list items, you will need to adjust the CSS a little to acco­mod­ate the extra images though (the pos­i­tion of the slide labels).

  23. Erno

    Hi! Thanks for the great tutorial! I was won­der­ing if there is a simple solu­tion to make this fluid (ie. res­ize with the con­tain­ing element).

  24. Four.Twenty

    I love this very much i used it on my site but i would rather recom­mend you con­vert everything into pixels for me.. the em thingy wheeee.. lol i really dont undast­and it.. thanks

  25. Josh

    Erno, it’s def­in­itely pos­sible, but unfor­tu­nately, not simple.

    Four.Twenty, if you mul­tiply all of the em val­ues by 16, then you will have the px equivalent.

  26. Maurice

    Hi Josh, great tutorial! I’ve run in to a prob­lem though, been try­ing for two days to fig­ure it out.

    I’ve included next/previous but­tons but can’t get them to work. Let me know your thoughts: http://codepen.io/acekicker77/pen/kdpEf

  27. Maurice

    Hi Josh, think I’ve made a lot of pro­gress. Though now I have another problem.

    When I hover over the quick­nav at the bot­tom I’d like the slide ban­ners to show (the same way they do when I hover over the slide). I can’t seem to fig­ure out how to tar­get that. Any suggestions?

    Have a look: http://codepen.io/acekicker77/pen/BxkpD

    Thanks again for this tutorial, been really helpfull

  28. Josh

    Hi Maurice, unfor­tu­nately, with the way the quick­nav is set up, you won’t be able to do what you want with pure CSS.

    Perhaps mov­ing the quick­nav below the slider might be an option?

  29. Maurice

    Thanks Josh, haha I’m going form one prob­lem to the next. Ok so it was work­ing quite well, UNTIL I tried set­ting to get the “checked” image to show on load.

    Now it just shows the checked image only: http://codepen.io/acekicker77/pen/aAgie

    When I dis­able the css for “checked” then the slider works.

  30. Josh

    Once again, Maurice, with the way that CSS works (i.e. you can’t select par­ent ele­ments), what you’re try­ing to do won’t work. Perhaps simply hav­ing the slide you want to appear first as the first list item would be a reas­on­able compromise?

  31. Doc T

    I really like this slider. It is beau­ti­ful and eas­ily cus­tom­iz­able. I am hav­ing 2 issues though. First off why is the place­ment set­ting off by so much. The 0,0 mar­gin set­ting throws it to the middle right of the browser win­dow. I can manu­ally move it to where I want, but I want to know why this is and if it’s pos­sible to fix it so that 0,0 is the top left corner as with most ele­ments? My second issue is that the slider seems to ignore all other ele­ments. For example when I put it into a box it com­pletely ignores it and stays where it is set in it’s own CSS code. This is a real issues when align­ing it around other ele­ments and inside of other ele­ments. Any help would be appreciated.

  32. Josh

    DocT, that’s to do with the abso­lute pos­i­tion­ing that I’ve used (along with the top and left attrib­utes) to centre the slider for the demo. Removing those prop­er­ties should resolve your issues.

  33. Doc T

    Josh, I got it work­ing. Had to change abso­lute to rel­at­ive in just the top .slider {} and remove the top and left set­tings in that {} as well. Also had to change the mar­gin to = .slider:before width. Works great now. Thanks for the help.

  34. David Ngugi

    Hey pretty cool.…I have imple­men­ted this in my new upcom­ing site.Post even bet­ter ones…thanks!!

  35. nate

    how do i move the radio but­tons beneath the slider?

  36. Josh

    Nate, you will need to change the bot­tom value for the labels. Try using a neg­at­ive value, some­thing like this:

    .slider label {
        bottom: -5em;
    }

  37. Qas

    Hi Josh, thank you for shar­ing this. Following your help­ful steps, I’ve man­aged to cre­ate a slider that func­tions per­fectly… well, in all browsers but Internet Explorer. ha!

    In IE10 the first image of the slider is per­man­ently dis­played with no vis­ible radio but­tons. While in IE8, no images are dis­played at all, although one radio but­ton can be seen.

    Is there a quick way of fix­ing this and ensur­ing that the slider oper­ates fully in all ver­sions of IE 7/8 and above?

    If not, is there a way of for­cing the first image of the slider to be dis­played per­man­ently (much like IE10) in browsers that do not sup­port the slider?

    Thanks

    Qas

  38. Josh

    Hi, Qas. Unfortunately a cross browser, pure CSS image slider is not cur­rently a real­istic option. Using this slider is going to cause issues in earlier ver­sions of Internet Explorer no mat­ter what you do. If you need reas­on­able browser sup­port then you will have to look at a slider that uses Javascript.

  39. Ashley

    Josh,

    Great tutorial. Easy to fol­low and well explained. How would you go about adding cap­tions under­neath the images and dis­play­ing them when the images display?

  40. Josh

    Hi, Ashley. You could do some­thing like this. I’ve added the rel­ev­ant CSS to the bot­tom. If you have any ques­tions, let me know!

  41. PJ

    Great tutorial, Josh! I’m new to css. Is it pos­sible to make this slider act as an image and have text wrap left around it and align the whole thing to the right?

  42. Josh

    Yeah, it sure is, PJ. Simply remove the margin, left and top prop­er­ties from the .slider selector and change position: absolute; to position: relative;.

  43. PJ

    And what prop­er­ties do I need to add to make the text wrap? Or do I add those prop­er­ties in de code of my images?

  44. PJ

    Another ques­tion (of cource): Is it pos­sible to put two dif­fer­ent sliders on the same page?

  45. Josh

    Yes, that would work fine, you’d just need to make sure all the IDs are unique.

  46. PJ

    So thanks to your tips I worked out how to get two on one page:

    http://hujo.be/winkel

    However, the first slider gal­lery doens’t show a stand­ard image. It only does that when you click one of the radio-buttons.

    The code:

    .slider {
        float: right; 
        height:  300px;
        padding: .5em;
        width: 300px;
        position: relative;
    }
    .slider:after {
        bottom: -1.5em;
        content: '';
        left: -1.5em;
        position: absolute;
        right: -1.5em;
        top: -1.5em;
        z-index: -1;
    }
    .slider li {
        list-style: none;
        position: absolute;
    }
    .slider input {
        display: none;
    }
    .slider label {
        bottom: .5em;
        cursor: pointer;
        display: block;
        height: .5em;
        left: 24em;
        opacity: 0;
        position: absolute;
        transition: .25s;
        width: .5em;
        visibility: hidden;
        z-index: 10;
    }
    .slider label:after {
        border-radius: 100%;
        bottom: -.2em;
        box-shadow: inset 0 0 0 .2em #111,
                    inset 0 2px 2px #000,
                    0 1px 1px hsla(0,0%,100%,.25);
        content: '';
        left: -.2em;
        position: absolute;
        right: -.2em;
        top: -.2em;
    }
    .slider:hover label {
        opacity: 1;
        visibility: visible;
    }
    .slider input:checked + label {
        background-color: #fff;
    }
    .slider:hover li:nth-child(1) label {
        left: .5em;
    }
    .slider:hover li:nth-child(2) label {
        left: 2em;
    }
    .slider:hover li:nth-child(3) label {
        left: 3.5em;
    }
    .slider:hover li:nth-child(4) label {
        left: 5em;
    }
    .slider img {
        height: 300px;
        opacity: 0;
        transition: .25s;
        width: 300px;
        vertical-align: top;
        visibility: hidden;
    }
    .slider li input:checked ~ img {
        opacity: 1;
        visibility: visible;
        z-index: 10;
    }

  47. PJ

    Okay, I for­got to check the first radio box. Tkans you so much for the awe­some tut and all the help!