How to Build a Simple Slideshow With the CSS Checkbox Hack

Read MoreWhat You’ll Be CreatingIn this new tutorial, we’ll learn how to create a fully functional, responsive image slideshow with thumbnails, from scratch. To accomplish it, we won’t need to write a single line of JavaScript. In actual fact, once more, we’ll only use HTML and CSS as we take advantage of the “CSS checkbox hack technique”. Note: This tutorial assumes that you’re familiar with that CSS technique along with advanced CSS selectors (e.g. general sibling combinator). If you haven’t heard of these before, or need a refresher, check out the following tutorials:CSS Selectors
How to Build an Accordion Component With the CSS Checkbox Hack
George Martsoukos
CSS
Quick Tip: How to Create an Off-Canvas Feedback Form With Pure CSS
George Martsoukos
CSS Selectors
How to Build a Filtering Component in Pure CSS
George Martsoukos
Our Responsive CSS SlideshowHere’s the slideshow that we’re going to create during this tutorial:

1. Begin With the HTML MarkupFor the purposes of this exercise, we’ll grab three images from Unsplash.Then, we’ll create the corresponding radio buttons which we’ll group under the image keyword:<input type=”radio” id=”image1″ name=”image” checked>
<input type=”radio” id=”image2″ name=”image”>
<input type=”radio” id=”image3″ name=”image”>Next, we’ll put inside a container the .featured-wrapper and .thumb-list elements. The .featured-wrapper element will contain three lists:The first list will hold the slideshow images. Only one single image will appear at a time. 
The other two lists which are identical will be used for navigating between images/slides. Both lists will contain labels whose for values match the id values of the aforementioned radio buttons.
Tip: In our example, we’ll associate a radio button with more than one label. It’s perfectly valid.The .thumb-list element will also include the slideshow images along with their descriptions. However, unlike the images of the .featured-list element, these images will always be visible and used for the thumbnail navigation.In short, our slideshow will provide users the ability to switch between slides via dots, arrows, and thumbnails. Niiice!Final HTML StructureBy default, the first image should be visible/active. With that in mind, we’ll add the checked attribute to the first radio button.Putting it all together, here’s the structure of our container:<div class=”container”>
<div class=”featured-wrapper”>
<ul class=”featured-list”>
<li>
<figure>
<img src=”IMG_SRC” alt=””>
</figure>
</li>
<!– other two list items here –>
</ul>
<ul class=”arrows”>
<li>
<label for=”image1″></label>
</li>
<li>
<label for=”image2″></label>
</li>
<li>
<label for=”image3″></label>
</li>
</ul>
<ul class=”dots”>
<li>
<label for=”image1″></label>
</li>
<li>
<label for=”image2″></label>
</li>
<li>
<label for=”image3″></label>
</li>
</ul>
</div>
<ul class=”thumb-list”>
<li>
<label for=”image1″>
<img src=”IMG_SRC” alt=””>
<span class=”outer”>
<span class=”inner”>…</span>
</span>
</label>
</li>
<!– other two list items here –>
</ul>
</div>Note: Within each label inside the .thumb-list, I don’t use the block-level figure and figcaption elements because the W3C Validator will throw an error. We’ll just stick to inline elements.
2. Define the StylesIn terms of styles we’ll first visually hide the radio buttons by moving them off-screen:input[type=”radio”] {
position: absolute;
bottom: 0;
left: -9999px;
}Note: I added the bottom: 0 property value to prevent the browser from jumping to the top of the page, each time a label is clicked. Not the ideal approach, yet it seems to do the job. Alternatively, as a more stable solution, I could have set display: none, yet this isn’t recommended due to keyboard accessibility restrictions. Specifically, that style will prevent arrow keys from changing the selected radio button.As usual, our container will have a maximum width with horizontally centered content.container {
max-width: 700px;
padding: 0 20px;
margin: 0 auto;
}Large ImagesBy default, all featured images will be stacked on top of another. They will all be hidden, apart from the image associated with the checked radio button.To stack the images, surprisingly enough we won’t use the common position property. Normally, what you might expect is that we turn the images into absolutely positioned elements. But that method comes with one big disadvantage: absolute elements are removed from the normal document flow, so we would have to find a way to preserve images’ aspect ratio. For example, a rough, non-elegant solution might be to add a fixed height to the images’ container.This is where new CSS additions like CSS Grid comes to the rescue, especially if you’re only interested in modern browsers. So first, we’ll make the list behave as a grid container, then we’ll position its items in the same cell by giving them grid-row: 1 and grid-column: 1. Here’s the corresponding CSS:.featured-wrapper .featured-list {
display: grid;
}

.featured-wrapper .featured-list li {
grid-column: 1;
grid-row: 1;
opacity: 0;
transition: opacity 0.25s;
}DotsThe dots navigation will be absolutely positioned and located at the bottom of the .featured-wrapper element. Each of its labels will have the appearance of a circle, like this:Here are the related styles:/*CUSTOM VARIABLES HERE*/

.featured-wrapper {
position: relative;
}

.featured-wrapper .dots {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
display: flex;
}

.featured-wrapper .dots li:not(:last-child) {
margin-right: 8px;
}

.featured-wrapper .dots label {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
border: 1px solid var(–white);
transition: background 0.25s;
}

.featured-wrapper .dots label:hover {
background: currentColor;
}ArrowsThe navigation arrows will be absolutely positioned inside the .featured-wrapper element:Keep in mind that only the arrows for the label associated with the checked radio button will appear. To create them, we’ll use the ::before and ::after pseudo-elements of the target label.Here are the required styles:/*CUSTOM VARIABLES HERE*/

.featured-wrapper .arrows label::before,
.featured-wrapper .arrows label::after {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 50%;
color: var(–black);
background-position: center;
background-repeat: no-repeat;
background-size: 24px 24px;
background-color: var(–white);
opacity: 0.5;
transition: opacity 0.25s;
}

.featured-wrapper .arrows label::before {
left: 10px;
}

.featured-wrapper .arrows label::after {
right: 10px;
}ThumbnailsEach thumbnail will cover one-third of the parent width, like so:To position the caption on top of its image, instead of using the traditional CSS positioning, we’ll take advantage of the CSS Grid trick which we learned previously. We’ll turn the label into a grid element and force the children to cover its full dimensions. By default, only the caption associated with the checked radio button will appear. Also, its content will be horizontally and vertically centered thanks to CSS Grid again.Here are the target styles:/*CUSTOM VARIABLES HERE*/

.thumb-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 20px;
margin-top: 20px;
}

.thumb-list label {
display: grid;
}

.thumb-list img,
.thumb-list .outer {
grid-column: 1;
grid-row: 1;
}

.thumb-list .outer {
display: grid;
place-items: center;
transition: background 0.25s;
}

.thumb-list .inner {
font-size: 18px;
opacity: 0;
transform: translateY(20px);
transition: all 0.25s;
}
3. Checkbox Hack: Switch Between SlidesLet’s now have some fun! We’ll push the boundaries of CSS thanks to the checkbox hack and mimic JavaScript’s click event. So, each time a thumbnail image, a dot, or an arrow is clicked (i.e. becomes active), the following things will happen:The active slide will become visible.
The active dot will receive a white background color.
The caption of the active thumbnail image will appear.
The previous and next arrows of the active slide will appear. These will link to its previous slide and its next slide, respectively.
Here are the styles that handle this functionality:/*CUSTOM VARIABLES HERE*/

[id=”image1″]:checked ~ .container .featured-list li:nth-child(1),
[id=”image2″]:checked ~ .container .featured-list li:nth-child(2),
[id=”image3″]:checked ~ .container .featured-list li:nth-child(3),
[id^=”image”]:checked ~ .container .arrows [for^=”image”]:hover::before,
[id^=”image”]:checked ~ .container .arrows [for^=”image”]:hover::after {
opacity: 1;
}

[id=”image1″]:checked ~ .container .arrows [for=”image3″]::before,
[id=”image2″]:checked ~ .container .arrows [for=”image1″]::before,
[id=”image3″]:checked ~ .container .arrows [for=”image2″]::before {
content: ’’;
background-image: url(arrow-prev-slideshow.svg);
}

[id=”image1″]:checked ~ .container .arrows [for=”image2″]::after,
[id=”image2″]:checked ~ .container .arrows [for=”image3″]::after,
[id=”image3″]:checked ~ .container .arrows [for=”image1″]::after {
content: ’’;
background-image: url(arrow-next-slideshow.svg);
}

[id=”image1″]:checked ~ .container .dots [for=”image1″],
[id=”image2″]:checked ~ .container .dots [for=”image2″],
[id=”image3″]:checked ~ .container .dots [for=”image3″] {
background: currentColor;
}

[id=”image1″]:checked ~ .container [for=”image1″] .outer,
[id=”image2″]:checked ~ .container [for=”image2″] .outer,
[id=”image3″]:checked ~ .container [for=”image3″] .outer {
background: var(–overlay);
}

[id=”image1″]:checked ~ .container [for=”image1″] .inner,
[id=”image2″]:checked ~ .container [for=”image2″] .inner,
[id=”image3″]:checked ~ .container [for=”image3″] .inner {
opacity: 1;
transform: none;
}It might take you some time to understand how the aforementioned styles work. If this is the case, the browser inspector is your best friend!ConclusionThat’s it, folks! In this tutorial, we managed to build a responsive CSS-only slideshow with thumbnails by taking advantage of the “CSS checkbox hack technique”. Hopefully, you enjoyed this exercise and you’ll incorporate it in an upcoming project.Here’s a reminder of what we built:

As a last thought, I’d say that without a doubt, the CSS checkbox hack technique is a great way to enhance your CSS knowledge. On the other hand, in a real project, we should be aware of its limitations (accessibility, markup) and when it’s worth using ιt instead of JavaScript alternatives.Have you ever built something interesting with the checkbox hack? Let us know!Further ReadingCheck out these tutorials to get some inspiration about powerful slideshows you can create by customizing popular jQuery plugins:jQuery
How to Build an Attractive Responsive Image Gallery With slick.js
George Martsoukos
jQuery
How to Build a Full-Screen Responsive Carousel Slider With Owl.js
George Martsoukos

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top