Introduction
We have a lot of readymade solutions for carousels from many UI/UX frameworks like Bootstrap, Glide, Flickity, etc. What if we want to build a carousel using HTML5 and CSS3 without depending on any 3rd party libraries. This article is about building a simple carousel without any JS code.
Background
In this article, we would take 4 DIV
s of different colors and create an infinite scrolling carousel.
Step 1: Create DIVs and Style Them
First, we'll create 4 div
s and keep them inside a parent container.
<div class="gallery">
<div class="red"></div>
<div class="blue"></div>
<div class="yellow"></div>
<div class="green"></div>
</div>
The CSS classes would be like this:
.gallery {
position: relative;
width:100%;
}
.gallery >div{
position: absolute;
top:0;
height: 200px;
width: 100%;
}
Note: The parent div
's position is relative and all the child div
s are absolute. All the div
s would be placed one behind the other inside the parent div
'gallery
'.
Step 2: Create Controls to Slide Through the Carousel
This is where it gets interesting, we need some buttons/control to navigate through our carousel. But if we have an HTML button, that would require an onclick
event listener which in turn should be handled by the JavaScript.
Let's do it the CSS way. Instead of buttons, we'll use radio buttons and the radio button.
Create 1 radio button for each div
. The idea here is, if radio button 1
is clicked, the div 1
is shown and so on.
<div class="carousel-container">
<input type="radio" name='control' id="slide1" class="carousel-control-radio">
<input type="radio" name='control' id="slide2" class="carousel-control-radio">
<input type="radio" name='control' id="slide3" class="carousel-control-radio">
<input type="radio" name='control' id="slide4" class="carousel-control-radio">
<div class="gallery">
<div class="red"></div>
<div class="blue"></div>
<div class="yellow"></div>
<div class="green"></div>
</div>
</div>
In HTML5, we have an attribute in <label
> tag 'for' which is useful to map the input element with its label. The other interesting property of this attribute is: The corresponding radio button gets checked when we click on the label assigned to it. We are going to use this feature to leverage our controls.
Note: I have enclosed the entire HTML block into a div
with class carousel-container with position relative and any arbitrary width.
Let's implement the control. The logic is setting the opacity of all the div
s to 0
and make the opacity of selected div
as 1
.
.gallery >div{
position: absolute;
top:0;
height: 200px; /* can be anything */
width: 100%;
opacity:0 /* all divs are hidden */
}
We'll overwrite the opacity of the selected radio button's div
. How do we do that??
The general sibling combinator (~): It is used to select all the siblings after the selector.
#slide1:checked ~ .gallery > div:nth-child(1),
#slide2:checked ~ .gallery > div:nth-child(2),
#slide3:checked ~ .gallery > div:nth-child(3),
#slide4:checked ~ .gallery > div:nth-child(4)
{
opacity: 1;
}
#slide1:checked ~ .gallery > div:nth-child(1)
denotes when #slide1
is checked, select from the siblings that follows it -> .gallery div
and the first child of it. We set the opacity
to 1
.
Now our output should look like this:
The radio buttons will be hidden and only the labels of the radio button will act as our controls.
Step 3: Create Labels for Each Radio Button
<div class="slider-controls">
<label for="slide1"></label>
<label for="slide2"></label>
<label for="slide3"></label>
<label for="slide4"></label>
</div>
Now we need to keep the slider-controls to center of our carousel-container.
.slider-controls{
position: absolute;
width: 100%;
top:100px;
}
Note: There is no text inside label. Exaclty! we are going to use CSS pseudo element to dynamically change the content of the text as '<
' or '>
' which will denote the direction of previous or next div
.
As per our design, we would show the div
when its corresponding radio button is selected.
Say radiobutton slide2
is checked: then '<
' should be a control when clicked should go to slide 1
and '>
' should be a control when clicked should go to slide 3
.
So:
#slide2:checked ~ .slider-controls > label:nth-child(3)::after{
content: '>';
float:right;
}
#slide2:checked ~ .slider-controls > label:nth-child(1)::after{
content: '<';
float:left;
}
We don't need to show any other controls. We just need to show these two. SImilarly, for 3
and 4
:
#slide3:checked ~ .slider-controls > label:nth-child(4)::after{
content: '>';
float:right;
}
#slide3:checked ~ .slider-controls > label:nth-child(2)::after{
content: '<';
float:left;
}
#slide4:checked ~ .slider-controls > label:nth-child(1)::after{
content: '>';
float:right;
}
#slide4:checked ~ .slider-controls > label:nth-child(3)::after{
content: '<';
float:left;
}
Note: Slide 4
's next will be slide 1
.
Now the first slide is a bit tricky.
This will have '>
' pointing to slide 2
which is direct. and '<
' should be the last slide. We will use the nth-last-child(1
) pseudo element to select the last div
.
#slide1:checked ~ .slider-controls > label:nth-child(2)::after{
content: '>'
float:right;
}
#slide1:checked ~ .slider-controls > label:nth-last-child(1)::after{
content: '<'
float:left;
}
This concludes our solution.
Improvements