Welcome to a tutorial on how to create a simple responsive slideshow with pure CSS and vanilla Javascript. Yes, there are a lot of crazy slideshow plugins on the Internet. But some of them require the use of third-party libraries, which adds to the undesired loading bloat – So here it is, a simple and lightweight slideshow that you can use. Read on!
ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.
TABLE OF CONTENTS
DOWNLOAD & DEMO
Firstly, here is the download link to the example code as promised.
QUICK NOTES
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.
SOURCE CODE DOWNLOAD
Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
HOW TO USE & DEMO
<!-- (A) LOAD LIBRARY -->
<link rel="stylesheet" href="slides.css"/>
<script defer src="slides.js"></script>
<!-- (B) CREATE HTML DIV -->
<div id="slidedemo"></div>
<!-- (C) ATTACH SLIDESHOW -->
<script>
window.addEventListener("DOMContentLoaded", () => {
sslide.init({
target: "slidedemo",
images: [
{src: "cat.jpg", cap: "An evil cate."},
{src: "dove.jpg", cap: "A birb."},
{src: "fox.jpg", cap: "Not a doge."}
],
// (OPTIONAL) 3 SEC PER SLIDE, REMOVE TO MANUAL SCROLL
auto: 3000
});
});
</script>
- Captain Obvious, load both
slides.css
andslides.js
. - Define a
<div>
to attach the slideshow to. - Lastly, use
sslide.init()
to attach the slideshow. There are only 3 options here:target
ID of the<div>
element that you want to attach the slideshow to.images
Array of images you want to show. Remember to provide both the source URL and caption.auto
In milliseconds, optional. Automatically rotate between the slides.
HOW IT WORKS
Now for those who are interested to “deep customize” the slideshow – Here is the Javascript and a quick walkthrough.
PART 1) PRELOAD IMAGES
/* (A) INITIALIZE - PRELOAD IMAGES */
instances : [],
init : (opt) => {
// (A1) REGISTER SLIDESHOW INSTANCE
const id = sslide.instances.length;
sslide.instances.push(opt);
// (A2) PRELOAD IMAGES
let loaded = 0, ready = () => {
loaded++;
if (loaded == opt.images.length) { sslide.attach(id); }
};
for (let i of opt.images) {
let img = new Image();
img.src = i.src;
img.onload = ready;
}
}
The sslide.init()
function is what we call to initialize the slideshow.
- (A1) Very simply, we push a new instance into the
sslide.instances
array. Yes, we need to support multiple slideshows on a single page, and this is used to track which is which. - (A2) Proceed with the next step only when all the images are preloaded.
PART 2) ATTACH HTML INTERFACE
/* (B) INITIALIZE - ATTACH HTML CONTROLS */
attach : (id) => {
// (B1) GET HTML CONTAINER
let inst = sslide.instances[id],
sSlide = document.getElementById(inst.target);
// (B2) SLIDESHOW HTML INTERFACE
let sImg = document.createElement("img"),
sCaption = document.createElement("div"),
sLeft = document.createElement("div"),
sRight = document.createElement("div");
sSlide.className = "sSlide";
sImg.className = "sImg";
sCaption.className = "sCaption";
sLeft.className = "sLeft";
sRight.className = "sRight";
sLeft.innerHTML = "<";
sRight.innerHTML = ">";
sLeft.addEventListener("click", () => { sslide.nav(id, 0); });
sRight.addEventListener("click", () => { sslide.nav(id, 1); });
sSlide.appendChild(sImg);
sSlide.appendChild(sCaption);
sSlide.appendChild(sLeft);
sSlide.appendChild(sRight);
// (B3) READY!
inst.current = -1;
inst.sImg = sImg;
inst.sCaption = sCaption;
sslide.nav(id, 1);
}
Ok, this looks crazy. But all it does is essentially generate the following HTML:
<div id="slidedemo" class="sSlide">
<div class="sImg"></div>
<div class="sCaption"></div>
<div class="sLeft" onclick="sslide.nav(ID, 0)"><</div>
<div class="sRight" onclick="sslide.nav(ID, 1)">></div>
</div>
PART 3) DRAW CURRENT SLIDE
/* (C) NAVIGATION */
nav : (id, direction) => {
// (C1) CALCULATE NEXT SLIDE
let inst = sslide.instances[id],
slides = inst.images;
if (direction) { inst.current++; }
else { inst.current--; }
if (inst.current < 0) { inst.current = slides.length - 1; }
if (inst.current >= slides.length) { inst.current = 0; }
// (C2) DRAW SLIDE
inst.sImg.src = slides[inst.current].src;
inst.sCaption.innerHTML = slides[inst.current].cap;
// (C3) AUTO SCROLL MODE
if (inst.auto) {
if (inst.timer) { clearInterval(inst.timer); }
inst.timer = setInterval(() => { sslide.nav(id, 1); }, inst.auto);
}
}
sslide.nav()
is fired whenever the user clicks on left/right. Should be pretty self-explanatory –
- We update the current slide –
inst.current
. - Get the image source and caption –
inst.images[CURRENT]
. - Update the HTML.
- Reset the timer if necessary for auto-scroll.
That’s all!
PART 4) THE CSS
/* (A) SHARED */
.sImg, .sCaption { width: 100%; }
.sSlide, .sLeft, .sRight { display: flex; }
/* (B) CONTAINER */
.sSlide {
flex-wrap: wrap;
position: relative;
max-width: 640px;
}
/* (C) IMAGE */
.sImg {
height: 350px;
object-fit: cover; /* fill, contain, scale-down */
}
/* (D) CAPTION */
.sCaption {
padding: 10px;
color: #fff;
background: #000;
}
/* (E) CONTROLS */
/* (E1) LEFT/RIGHT BUTTONS */
.sLeft, .sRight {
align-items: center;
position: absolute;
top: 0;
z-index: 9;
height: 100%;
padding: 0 20px;
font-size: 2em;
color: #fff;
background: rgba(0, 0, 0, 0.5);
cursor: pointer;
}
.sTop .sLeft { left: 0; }
.sTop .sRight { right: 0; }
/* (E2) SHOW ONLY ON HOVER */
.sLeft, .sRight {
visibility: hidden;
opacity: 0;
transition: opacity 0.3s;
}
.sSlide:hover .sLeft, .sSlide:hover .sRight {
visibility: visible;
opacity: 1;
}
Yep… Don’t think I want to dive too deep into the CSS – These are practically the cosmetics of the slideshow. Feel free to change the colors and layout to fit your own theme.
AUTOLOAD SLIDES
That’s it for the simple slideshow, and here is a small extra that you may find useful.
USING PHP TO AUTOLOAD ALL SLIDES
Lazy to change the HTML every time? Use a server-side script to help you extract all the image files automatically. Here’s a quick example in PHP.
<script>
window.addEventListener("DOMContentLoaded", () => {
sslide.init({
target: "slidedemo",
images: [<?php
$dir = "gallery/";
$images = glob($dir . "*.{jpg,jpeg,gif,png,bmp,webp}", GLOB_BRACE);
$all = count($images);
$last = $all - 1;
for ($i=0; $i<$all; $i++) {
printf('{src:"%s%s", cap:"%s"}%s',
$dir, basename($images[$i]), basename($images[$i]),
$i==$last ? "" : ","
);
}
?>]
});
</script>
COMPATIBILITY CHECKS
- Arrow Functions – CanIUse
- CSS Flexbox – CanIUse
Should work across all major browsers… Less the “ancient ones”.
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you to create a simple slideshow for your project, and if you have anything to share with this guide, please feel free to comment below. Good luck and happy coding!
Excellent! Thanks for this, it was just what I needed.
One small issue with the extra bit (the lazy code as you call it). I couldn’t get this to work initially and think you have a }); missing towards the end.
Other than that – perfect!
It works… But that’s a server-side script, the server needs to support PHP.
I have just installed this, it is great and just what I needed. However when I loaded my own images they did not display, as my Canon camera saves as .JPG files (not .jpg) so I added JPG to the file types in gallery.php (line 14). Now it works, but I wonder if I should just rename all my JPG files to jpg instead.
JPG and jpg are the same, just case-sensitive. Don’t understand why Canon insists on using upper-case…
That was nice. Simple add useful. I also have added a few lines to code and I would like to share… You can contact me via my e-mail if you would like to.