How can I make an image carousel with only CSS?


Tags: javascript,jquery,html,css

Problem :

I'm looking to make an image carousel, where a user can toggle between images, by clicking on arrows. For example:

image of an image carousel

However, I can only use HTML and CSS—no JavaScript (and, therefore, jQuery). I just need the basic setup; smooth transitions and the like are not necessary.

How can I go about accomplishing this?



Solution :

That's easy! Just use radio buttons and targeted labels.

Radio buttons have the (necessary) behavior of only allowing one to be selected at any one time—just like an image in our carousel.

Demo

div.wrap2 {
  float: left;
  height: 500px;
  width: 422px;
}
div.group input {
  display: none;
  left: -100%;
  position: absolute;
  top: -100%;
}
div.group input ~ div.content {
  border: solid 1px black;
  display: none;
  height: 350px;
  margin: 0px 60px;
  position: relative;
  width: 300px;
}
div.group input:checked ~ div.content {
  display: block;
}
div.group input:checked ~ label.previous,
div.group input:checked ~ label.next {
  display: block;
}
div.group label {
  background-color: #69c;
  border: solid 1px black;
  display: none;
  height: 50px;
  width: 50px;
}
img {
  left: 0;
  margin: 0 auto;
  position: absolute;
  right: 0;
}
p {
  text-align: center;
}
label {
  font-size: 4em;
  margin: 125px 0 0 0;
}
label.previous {
  float: left;
  padding: 0 0 30px 5px;
}
label.next {
  float: right;
  padding: 0 5px 25px 0;
  text-align: right;
}
<div class="wrap">
  <div class="wrap2">
    <div class="group">
      <input type="radio" name="test" id="0" value="0">
      <label for="4" class="previous">&lt;</label>
      <label for="1" class="next">&gt;</label>
      <div class="content">
        <p>panel #0</p>
        <img src="http://i.stack.imgur.com/R5yzx.jpg" width="200" height="286">
      </div>
    </div>
    <div class="group">
      <input type="radio" name="test" id="1" value="1">
      <label for="0" class="previous">&lt;</label>
      <label for="2" class="next">&gt;</label>
      <div class="content">
        <p>panel #1</p>
        <img src="http://i.stack.imgur.com/k0Hsd.jpg" width="200" height="139">
      </div>
    </div>
    <div class="group">
      <input type="radio" name="test" id="2" value="2">
      <label for="1" class="previous">&lt;</label>
      <label for="3" class="next">&gt;</label>
      <div class="content">
        <p>panel #2</p>
        <img src="http://i.stack.imgur.com/Hhl9H.jpg" width="140" height="200">
      </div>
    </div>
    <div class="group">
      <input type="radio" name="test" id="3" value="3" checked="">
      <label for="2" class="previous">&lt;</label>
      <label for="4" class="next">&gt;</label>
      <div class="content">
        <p>panel #3</p>
        <img src="http://i.stack.imgur.com/r1AyN.jpg" width="200" height="287">
      </div>
    </div>
    <div class="group">
      <input type="radio" name="test" id="4" value="4">
      <label for="3" class="previous">&lt;</label>
      <label for="0" class="next">&gt;</label>
      <div class="content">
        <p>panel #4</p>
        <img src="http://i.stack.imgur.com/EHHsa.jpg" width="96" height="139">
      </div>
    </div>
  </div>
</div>

TLDR: Important notes

  • Make sure at least one input(type="radio") is checked by default, or the whole carousel will be hidden.
  • Hide the input radios and use labels as the previous/next buttons
  • Make sure the labels correctly target the previous/next radio input (see labels section at the end on how to do the targeting)
  • Show an image when its corresponding input radio is :checked
  • Use cute kitten pictures

Explanation

Here's what the basic HTML structure should look like:

div#holder
    div.group
        input(type="radio")
        label.previous
        label.next
        div.content
            img
    div.group
        // ... repeat as necessary

div#holder will hold all of our content in place. Then, we'll group our radio buttons, labels, and images all under a div.group. This makes sure our radio inputs don't suffer from destructive interference (pun).

The key is in the selectors (and the labels—make sure to read that section)

First, we'll hide our radio buttons—they're ugly anyway:

div.group input {
    display: none;
    position: absolute;
    top: -100%;
    left: -100%;
}

We won't ever have to click the radio buttons. Instead, we'll style our labels and add targets (for properties), so that they redirect the click to the appropriate radio input block.

Most of our labels should be hidden:

div.group label {
    display: none;
}

(I will omit all aesthetic styling, so as to make the styling easier to understand. You can see the better-looking version in the stack snippet.)

Except for those next to a radio input that is toggled on, or :checked

div.group input:checked ~ label.previous,
div.group input:checked ~ label.next {
    display: block;
}

In addition, the div.content following a checked input should also be displayed:

div.group input:checked ~ div.content {
    display: block;
}

However, when the radio button is not checked, div.content should be hidden:

div.group input ~ div.content {
    display: none;
    position: relative;
}

Bazinga! Now our carousel should be fully mostly functional, albeit a little ugly. Let's move our labels to the correct position:

label.previous { float: left; }
label.next { float: right; }

And center our images within their respective divs:

img {
    left: 0;
    margin: 0 auto;
    position: absolute;
    right: 0;
}

The last step is how you set up your labels:

<input type="radio" id="1">
<label class="previous" for="0">&lt;</label>
<label class="next" for="2">&gt;</label>

Note how, given a radio input with an id of n, the label.previous will have a for attribute of (n - 1) % M and the label.next will have a for attribute of (n + 1) % M, where M is the number of images in the carousel.

Extra

If you're using Jade (or some other template engine), you can set it up with a simple for-loop like this:

div.wrap2
    - var imgs = [[200, 286], [200, 139], [140, 200], [200, 287], [96, 139]];
    - for (var i = 0; i < imgs.length; i++)
        div.group
            input(type="radio" name="test" id="#{i}" value="#{i}" checked="#{input == 3}")
            label(for="#{(i - 1 + imgs.length) % imgs.length}").previous &lt;
            label(for="#{(i + 1) % imgs.length}").next &gt;
            div.content
                p panel ##{i}
                img(src="http://placekitten.com/g/#{imgs[i].join('/')}"
                    height="#{imgs[i][1]}"
                    width="#{imgs[i][0]}"
                )

    CSS Howto..

    How do I set a block of text to drop to a new line all at once?

    how to manage layers in position:absolute css block

    How to create a caption for a pure CSS/HTML Slider with thumbnails, no java/jquery

    how to add a different css to last mysql query result using php

    CSS-how to text-indent a nested unordered list

    Menu hover effect - how to reproduce this effect?

    How to prevent the jump during css transition?

    How to make a progress bar like this in CSS

    How to resize grid-view column width?

    How to select via regex all class notations in css file

    How put an element more close to a html label

    How to make CSS fade out but the HTML to collapse

    How to provide a stylesheet for rendering PDFs?

    How to check if the current page is a plugin admin panel in wordpress

    How do I get Jquery to toggle display

    How to show a background color over the full width when zooming in?

    How to create multiple spoiler buttons

    How can I override an external css?

    How to override CSS Background that already has !important?

    CSS how to not use style

    How to prevent the backdrop of bootstrap modal dialog from covering the whole screen?

    How to use toggle css classes on an element onclick?

    How to chain multiple -webkit-transition animations in my css without keyframes

    Cannot get Font Awesome Images to Show

    How I can change the position of 3 div's to be side by side?

    How can I center my

    when there is an next to it?

    How to fade CSS sprite images using CSS background-position with jQuery?

    How to Display this CSS List using Class

    How to handle an id tag with '.' in CSS

    How to define absolute positioned element's anchor point?