Making a Pure CSS Featured Image Slider

Making a Pure CSS Featured Image Slider

Demo

This post will take 3 minutes to read.

CSS3 has given us some pretty powerful 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 article will explain how.

I have tried to keep this as to the point as possible, so if you want me to clarify anything, feel free to ask. Also, keep in mind that you will need to use browser prefixes 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 foundation worked out. This slider will contain four panels, so let’s write up an unordered list containing four images. We will give it a class of slider so that we can target 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 styl­ing

I am using em instead of px to size up this slider. If you aren’t that comfortable with using em then this article may help, otherwise, feel free to simply multiple 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 guarantee that any larger images are resized to fit within the slider.

Step 3: Navigating

Now that we have the basics sorted, let’s introduce a technique that will allow us to navigate between the slides. To do this, I am going to use what is known as the checkbox hack (see here for more information).

Let’s add some form elements 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 button as checked. The checked image will be the one showing on page load. The others will be hidden so that we can fade them in when they are selected. We will do that via the following 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 interactive slider using only CSS!

Step 4: Finishing touches

Alright, now it’s time to have some fun! Feel free to style the slider however 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 transform our boring looking slider into a picture frame. I’ll use a few transitions to make it smooth, and hide the navigation elements 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

66 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 navigation, then I would recommend using one based on JavaScript, as it will have much better functionality 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 background for image slider..?

  4. Josh

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

  5. Josh

    Okay. Tim uses a parent element that has the monitor as a background image with the slider contained within. That is also how I would handle it.

  6. Alexis

    Hi Josh

    I’m trying to implement your coding to create my first CSS image slide ever. I have read that to use transition I need to add a browser prefix to the start of the property. Could you let me know what this prefix would be and where exactly in the HTML I should insert it?

    Many thanks,

    Alexis

  7. Joshua

    So, from the previous question about it not being able to auto-transition, are you saying that there is NO way other than javascript or Jquery? purely CSS3?

  8. Josh

    Joshua, you can make the slides auto transition using CSS animations, but you then lose the ability to navigate between slides.

  9. Josh

    Nice find, Tom! It would be great if CSS allowed us to have a timed transition between panels, as well as navigation to quickly select which panel we wanted to view.

  10. filip

    hello,
    I really like your blog, it’s helpful and very comprehensibly written. I’m just a begginer but I could understand most of it.
    I’d like to use a pure css slider but instead of radio buttons I want simple nav buttons – you know: “prev” and “next”. So: is there an easy way to change your example to do this or I should better look for another example of a css slider?
    (I hope you can understand my question – my english is rather poor)
    cheers!

  11. filip

    Thanks! Now I just need to put ‘next’ and ‘prev’ buttons outside the image but I think I can do this alone. I will experiment a bit. I’ve started to learn css and html one month ago but it’s amusing to change a code and see what will happen…
    Once again: thank you very much!

  12. Marcello Africano

    Wow Josh, great tutorial, I love it! You seem to be a really enthusiastic web developer, eager to help people out, and I had a question. So here’s the deal…

    I’m 14 and I’m a freshman in high school and I make music, graphics, and websites, but I don’t have anybody to talk to or contact whenever I run into any problems besides people on forums. But people on forums are not always reliable (or exceptionally talented web developers like yourself), so I was wondering this… could I email you, and you give me helpful tips and advice maybe, but if not, I understand your busy (being great), but if so, that would be so great!

    – Thanks so much,
    – Marcello Africano –

  13. Sara

    Hi- I was using the CSS you recommended for a slider with arrows (http://codepen.io/joshnh/pen/zbaLI) but I’m having the problem that every time I click the next or previous arrow, my page jumps so the div .slider is at the top of the page, regardless of where you were in the page to begin with. Is there a way to get around this?

    Thanks- your tutorial was great!

  14. Josh

    Hi, Sara. Unfortunately you can’t stop the page jump with CSS, it is standard behaviour. You could do it with JavaScript, but if you take that approach, then you would be better off doing the whole slider using JavaScript.

  15. ashok kumar patel

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

  16. Narender Yadav

    Just learn the Html css at starting point

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

  17. Nathaniel Flick

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

  18. Stephen Meszaros

    Fantastic article and lovely, lovely site! Very glad to have stumbled upon it. I love the design coupled with your personal and relatable style of writing. I’m going to need to mess around with this one specifically as I am trying to add some slider’s to my portfolio site.

    Keep it up!

  19. rakesh

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

  20. Josh

    To add further images, just add extra list items, you will need to adjust the CSS a little to accomodate the extra images though (the position of the slide labels).

  21. Erno

    Hi! Thanks for the great tutorial! I was wondering if there is a simple solution to make this fluid (ie. resize with the containing element).

  22. Four.Twenty

    I love this very much i used it on my site but i would rather recommend you convert everything into pixels for me.. the em thingy wheeee.. lol i really dont undastand it.. thanks

  23. Josh

    Erno, it’s definitely possible, but unfortunately, not simple.

    Four.Twenty, if you multiply all of the em values by 16, then you will have the px equivalent.

  24. Maurice

    Hi Josh, great tutorial! I’ve run in to a problem though, been trying for two days to figure it out.

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

  25. Maurice

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

    When I hover over the quicknav at the bottom I’d like the slide banners to show (the same way they do when I hover over the slide). I can’t seem to figure out how to target that. Any suggestions?

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

    Thanks again for this tutorial, been really helpfull

  26. Josh

    Hi Maurice, unfortunately, with the way the quicknav is set up, you won’t be able to do what you want with pure CSS.

    Perhaps moving the quicknav below the slider might be an option?

  27. Maurice

    Thanks Josh, haha I’m going form one problem to the next. Ok so it was working quite well, UNTIL I tried setting 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 disable the css for “checked” then the slider works.

  28. Josh

    Once again, Maurice, with the way that CSS works (i.e. you can’t select parent elements), what you’re trying to do won’t work. Perhaps simply having the slide you want to appear first as the first list item would be a reasonable compromise?

  29. Doc T

    I really like this slider. It is beautiful and easily customizable. I am having 2 issues though. First off why is the placement setting off by so much. The 0,0 margin setting throws it to the middle right of the browser window. I can manually move it to where I want, but I want to know why this is and if it’s possible to fix it so that 0,0 is the top left corner as with most elements? My second issue is that the slider seems to ignore all other elements. For example when I put it into a box it completely ignores it and stays where it is set in it’s own CSS code. This is a real issues when aligning it around other elements and inside of other elements. Any help would be appreciated.

  30. Josh

    DocT, that’s to do with the absolute positioning that I’ve used (along with the top and left attributes) to centre the slider for the demo. Removing those properties should resolve your issues.

  31. Doc T

    Josh, I got it working. Had to change absolute to relative in just the top .slider {} and remove the top and left settings in that {} as well. Also had to change the margin to = .slider:before width. Works great now. Thanks for the help.

  32. David Ngugi

    Hey pretty cool….I have implemented this in my new upcoming site.Post even better ones…thanks!!

  33. nate

    how do i move the radio buttons beneath the slider?

  34. Josh

    Nate, you will need to change the bottom value for the labels. Try using a negative value, something like this:

    .slider label {
        bottom: -5em;
    }
  35. Qas

    Hi Josh, thank you for sharing this. Following your helpful steps, I’ve managed to create a slider that functions perfectly… well, in all browsers but Internet Explorer. ha!

    In IE10 the first image of the slider is permanently displayed with no visible radio buttons. While in IE8, no images are displayed at all, although one radio button can be seen.

    Is there a quick way of fixing this and ensuring that the slider operates fully in all versions of IE 7/8 and above?

    If not, is there a way of forcing the first image of the slider to be displayed permanently (much like IE10) in browsers that do not support the slider?

    Thanks

    Qas

  36. Josh

    Hi, Qas. Unfortunately a cross browser, pure CSS image slider is not currently a realistic option. Using this slider is going to cause issues in earlier versions of Internet Explorer no matter what you do. If you need reasonable browser support then you will have to look at a slider that uses Javascript.

  37. Ashley

    Josh,

    Great tutorial. Easy to follow and well explained. How would you go about adding captions underneath the images and displaying them when the images display?

  38. Josh

    Hi, Ashley. You could do something like this. I’ve added the relevant CSS to the bottom. If you have any questions, let me know!

  39. PJ

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

  40. Josh

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

  41. PJ

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

  42. PJ

    Another question (of cource): Is it possible to put two different sliders on the same page?

  43. Josh

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

  44. PJ

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

    http://hujo.be/winkel

    However, the first slider gallery doens’t show a standard 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;
    }
  45. PJ

    Okay, I forgot to check the first radio box. Tkans you so much for the awesome tut and all the help!