Infinte Scrolling Carousel using CSS






1.60/5 (3 votes)
Carousel using only CSS3 (without JavaScript and JS frameworks)
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%; /* takes the parent div's width*/
}
.gallery >div{
position: absolute;
top:0;
height: 200px; /* can be anything */
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:
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; /*push the control on the right side*/
}
#slide2:checked ~ .slider-controls > label:nth-child(1)::after{
content: '<';
float:left; /*push the control on the left side*/
}
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; /*push the control on the right side*/
}
#slide3:checked ~ .slider-controls > label:nth-child(2)::after{
content: '<';
float:left; /*push the control on the left side*/
}
#slide4:checked ~ .slider-controls > label:nth-child(1)::after{
content: '>';
float:right; /*push the control on the right side*/
}
#slide4:checked ~ .slider-controls > label:nth-child(3)::after{
content: '<';
float:left; /*push the control on the left side*/
}
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; /*push the control on the right side*/
}
#slide1:checked ~ .slider-controls > label:nth-last-child(1)::after{
content: '<'
float:left; /*push the control on the left side*/
}
This concludes our solution.
Improvements
- We can also add CSS transitions to smoothen our opacity transitions.
.gallery >div{ position: absolute; top:0; height: 200px; /* can be anything */ width: 100%; opacity:0 /* all divs are hidden */ transtion: opacity 800ms ease-in-out; }
- The radio buttons in the top can be hidden with
display:none
and the solution will still work. - The content of pseudo selector can be designed using border over the pseudo element instead of '
>
' or '<
' - The
div
s background can be set as an image which created a beautiful gallery of images.