
2025-08-28 — By Siddharth Jain · 7 min read
Creating a stylish, interactive image slider doesn’t need complex JavaScript!
With just HTML and CSS, you can build a fully functional slider that’s smooth, responsive, and lets users click arrows or dots to change images.
Let’s break down the process and understand how this clever technique works.
The backbone of this slider uses:
Each slide has a corresponding radio input, so only one slide can be “checked” at a time.
.slides container uses display: flex for a row layout.#slide2 is checked, CSS :checked selectors with ~ shift the .slides container using transform: translateX(...) to bring the right slide into view.<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Image Slider with Font Awesome Arrows</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.slider-container {
width: 100%;
max-width: 800px;
margin: 50px auto;
position: relative;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.slides {
display: flex;
width: 300%;
transition: transform 0.5s ease-in-out;
}
.slide {
width: 33.333%;
flex-shrink: 0;
}
.slide img {
width: 100%;
height: 400px;
object-fit: cover;
}
.dots {
position: absolute;
bottom: 15px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
}
.dot {
width: 12px;
height: 12px;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 50%;
cursor: pointer;
transition: background-color 0.3s;
}
.dot:hover {
background-color: rgba(255, 255, 255, 0.8);
}
.arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 30px;
color: #fff;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
cursor: pointer;
user-select: none;
border-radius: 5px;
transition: background-color 0.3s;
text-decoration: none;
}
.arrow:hover {
background-color: rgba(0, 0, 0, 0.8);
}
.left-arrow {
left: 10px;
}
.right-arrow {
right: 10px;
}
input[type="radio"] {
display: none;
}
#slide1:checked ~ .slides {
transform: translateX(0);
}
#slide2:checked ~ .slides {
transform: translateX(-33.333%);
}
#slide3:checked ~ .slides {
transform: translateX(-66.666%);
}
#slide1:checked ~ .dots label[for="slide1"],
#slide2:checked ~ .dots label[for="slide2"],
#slide3:checked ~ .dots label[for="slide3"] {
background-color: #fff;
}
#slide1:checked ~ .arrow.left-arrow[for="slide3"],
#slide1:checked ~ .arrow.right-arrow[for="slide2"],
#slide2:checked ~ .arrow.left-arrow[for="slide1"],
#slide2:checked ~ .arrow.right-arrow[for="slide3"],
#slide3:checked ~ .arrow.left-arrow[for="slide2"],
#slide3:checked ~ .arrow.right-arrow[for="slide1"] {
display: block;
}
.arrow {
display: none;
}
</style>
</head>
<body>
<div class="slider-container">
<input type="radio" name="slider" id="slide1" checked />
<input type="radio" name="slider" id="slide2" />
<input type="radio" name="slider" id="slide3" />
<div class="slides">
<div class="slide">
<img src="https://picsum.photos/800/400?random=1" alt="Slide 1" />
</div>
<div class="slide">
<img src="https://picsum.photos/800/400?random=2" alt="Slide 2" />
</div>
<div class="slide">
<img src="https://picsum.photos/800/400?random=3" alt="Slide 3" />
</div>
</div>
<label for="slide3" class="arrow left-arrow"
><i class="fas fa-chevron-left"></i
></label>
<label for="slide1" class="arrow left-arrow"
><i class="fas fa-chevron-left"></i
></label>
<label for="slide2" class="arrow left-arrow"
><i class="fas fa-chevron-left"></i
></label>
<label for="slide2" class="arrow right-arrow"
><i class="fas fa-chevron-right"></i
></label>
<label for="slide3" class="arrow right-arrow"
><i class="fas fa-chevron-right"></i
></label>
<label for="slide1" class="arrow right-arrow"
><i class="fas fa-chevron-right"></i
></label>
<div class="dots">
<label for="slide1" class="dot"></label>
<label for="slide2" class="dot"></label>
<label for="slide3" class="dot"></label>
</div>
</div>
</body>
</html>
:checked state.~ to animate the .slides container (translateX) so the right slide is visible.This pure CSS slider is perfect for landing pages, portfolios, and wherever you want a simple, dependency-free image carousel.