A better simple slideshow


If you don’t have time to do it right, when will you have time to do it over?
— John Wooden

It’s a do-over! This is another fairly basic slideshow, written in javascript, html, and css. This is a dual-purpose project, it’s meant (1) to be something you can drop right into your page and use if you so choose, but it’s also meant (2) as an example/tutorial showing you how to build a simple DIY slideshow from scratch on your own. You can see a couple of demos of the finished product here: http://leemark.github.io/better-simple-slideshow/.


Last December I posted a tutorial, “A simple DIY responsive image slideshow made with HTML5, CSS3, and JavaScript“, which ended up being unexpectedly popular (~50K views as I write this).

As I said in a comment on that post: “When I originally wrote this I just spent an afternoon playing around with different techniques, and this seemed like a decent approach. I honestly never expected more than a few people, or a few dozen at most to ever see it, and definitely never meant it to be code that other people would put into production. But I’m really glad to have had a lot of people look at it, and use it, and give feedback on how it can be improved. It’s probably overdue for a new and improved version.”

Now, finally, »this« is that new and improved version.


  • fully responsive
  • option for auto-advancing slides, or manually advancing by user
  • multiple slideshows per-page
  • supports arrow-key navigation
  • full-screen toggle using HTML5 fullscreen api
  • swipe events supported on touch devices (requires hammer.js)
  • written in vanilla JS–this means no jQuery dependency (much ♥ for jQuery though!)



“Medium” by Thomas Hawk.
“Colorado” by Trey Ratcliff.
“Early Morning at the Monte Vista Wildlife Refuge, Colorado” by Dave Soldano.
“Sunrise in Eastern Colorado” by Pam Morris.
“colorado colors” by Jasen Miller.

Demo link

How to use it

If you just want a slideshow script that you can drop into your own site and use, see the GitHub repo and read the “Getting Started” section. There are a couple of files you will need to download, then a small bit of configuration and you are good to go. See the demo slideshows here for usage examples.

Here’s a direct link to the javascript file and to the CSS file that you will need to download and include in your page. If you plan to use the fullscreen option you will also want to grab these 2 icon images for the fullscreen toggle (icon1, icon2).

How to build it yourself

If you’re interested in writing your own code from scratch, or taking the source code and modifying it for your own purposes, you may want to first read or skim this earlier walkthough, many of the same principles and techniques underlying the slideshow apply–although this new version has more features and the javascript has been rewritten from the ground up.

Please Note: The example code snippets below are excerpts meant to illustrate the techniques used in building the slideshow. For the full source code to use in your own pages, please see the “How to use it” section above or get the full finished code on GitHub.

The slideshow HTML

Rather than using an unordered list or a bunch of <div>s or whatever, let’s use the more semantic HTML5 elements figure and figcaption. The HTML markup for the slideshow should look basically like this, with a container element wrapping the whole thing (doesn’t have to be a <div>, any block element will do) and each slide is a <figure>.

Inside each <figure> is an image and a figcaption. Each <img> has a width of 100% which helps make our slideshow responsive, in that it automatically resizes to fit the available width. The image caption goes inside the <figcaption> element, and it’s fine to use inline HTML elements inside of it, so feel free to add hyperlinks in image captions if you want.

The CSS styles

There are 2 major purposes of the CSS for this slideshow, the first is to fine-tune all the little aesthetic details like what font we’re using, what the text and background color is for the caption, etc. I’ve omitted all that from the code below, but you can see the full CSS here if you’d like.

The second purpose is to handle the actual workings of the slideshow, to position all the elements inside of the slideshow, and to show the current slide, hide all of the other slides, and transition between them when needed. This is what I’ve included in the commented example code below.

With this CSS we are setting up nearly everything needed for display of the slideshow, the individual slides, the captions, the ‘hidden’ default state of the slides, and the ‘active’ visible state of the current slide (the one with the ‘bss-show’ class). All we need to do with the javascript is to keep track of the current slide and perform some class-swapping on the figure elements, so that the active slide always has the ‘bss-show’ class and the other slides don’t. Well, that and all the extra features like keyboard navigation, fullscreen, etc.

For clarity and brevity, I’ve only included the standard unprefixed W3C-approved properties in the example CSS above. In production you will also want to include prefixed versions of some properties as needed for cross-browser compatibility. See Chris Coyier’s article “How To Deal With Vendor Prefixes” for a good overview, or use a tool like Autoprefixer.

The JavaScript

Here’s the basic structure of our javascript, the bulk of it is a Slideshow object (using the prototype pattern) that we will create instances of using Object.create(). I’ve replaced the contents of each of the Slideshow object’s methods with a description of what it does, but we’ll walk though each of those methods later on. Also, you can see the full unedited source code here.


This method is called right after the slideshow is created, and it initializes some properties (like the counter to keep track of which slide we’re on), accepts the options object we’ve passed in, and calls all the other methods needed to get the slideshow ready to go.

[1] http://stackoverflow.com/questions/3088098/in-javascript-what-does-it-mean-when-there-is-a-logical-operator-in-a-variable
[2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator


This method is triggered whenever we want to change/advance the current slide, either by clicking the next or prev buttons, via arrow key input, by the auto-advance timer, whatever.

[1] http://stackoverflow.com/a/16053538/2006057


This method is only called once, when the slideshow is initialized on page load, and it creates the controls i.e. the previous and next buttons.

[1] https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment


This method registers event listeners to particular elements, like the previous and next buttons, so that user interactions can trigger the slideshow to change.

[1] http://stackoverflow.com/questions/962033/what-underlies-this-javascript-idiom-var-self-this
[2] http://www.quirksmode.org/js/events_access.html#link5


This method is called once when the slideshow is created, and only if the ‘auto’ option is set. It uses setInterval() to create a timer loop to advance the slides automatically. In the event that the ‘pauseOnHover’ option is also set, this adds event listeners to clear and restart the setInterval() loop when the mouse is moved over and off the slideshow.


This method is called only once when the slideshow is initialized. If the ‘fullScreen’ option is set then it creates the fullscreen toggle button, and adds an event listener to call the toggleFullScreen() method when the button is clicked.


This method is called once, when the slideshow is initialized, only if the ‘swipe’ option is set. It depends on the HammerJS library.


This method is called when the user clicks the fullscreen button (assuming the ‘fullScreen’ option is set), and toggles the slideshow in and out of fullscreen mode. The fullscreen API itself is pretty simple, but because the spec is still being standarized, each browser needs its own prefixed code. You can read more here about using full screen mode.

The finished slideshow: CodePen style

Check out this Pen!

References, Resources, and Further Reading

Post featured image: Looking back in time by 900hp, on Flickr

107 Replies to “A better simple slideshow”

  1. Hi Mark,

    Many thanks for this awesome slideshow!

    It’s by far the easiest solution I’ve found after days of research. And it works like a charm.

    I would like to share some tip I have been thinking of:

    When you try to open one of the slide (image) in another tab, or when you drag & drop a slide on your desktop, it will only select the last slide as it is on top of the stack (even if not being displayed).

    In order to get around this, simply add a “position : relative” on each image, and add a “z-index: 3” for the current slide being displayed.

    This will make the current slide on top of the stack and make the click work with the actual slide being displayed.

    Keep up the good work!

  2. Hey Mark…First of thank you for this ‘piece of ART’….I have been searching on the internet for a slideshow just like that…but i cant figure out how to get it done. I followed the steps, all was going well till i reached the javascript part. Here is my code, please pass through it and let me know where i went wrong. Thanks..


    CSS Code
    position: relative;
    display: block;

    outline: 0;

    .slideshow figure{
    position: absolute;
    top: 0;

    .slideshow figure:first-child{
    position: relative;

    .slideshow figure img{
    opacity: 0;
    transition: opacity 1.2s;
    -webkit-transition: opacity 12s;
    transition: opacity 1.2s;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;

    .slideshow .slideshow-show img{
    opacity: 1;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    .slideshow-next, .slideshow-prev{
    color: #fff;
    position: absolute;
    background: #000;
    background: rgba(0,0,0, .6);
    top: 50%;
    z-index: 1;
    font-size: 2em;
    margin-top: -1.2em;
    opacity: .3;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    .slideshow-next:hover, .slideshow-prev:hover{
    cursor: pointer;
    opacity: 1;
    right: -1px;
    padding: 10px 5px 15px 10px;
    border-top-left-radius: 3px;
    border-bottom-left-radius: 3px;
    left: 0;
    padding: 10px 10px 15px 5px;
    border-top-right-radius: 3px;
    border-bottom-right-radius: 3px;

    display: block;
    width: 32px;
    height: 32px;
    background: rgba(0,0,0,.4) url(https://raw.githubusercontent.com/leemark/better-simple-slideshow/gh-pages/img/arrows-alt_ffffff_64.png);
    -webkit-background-size: contain;
    background-size: contain;
    position: absolute;
    top: 5px;
    left: 5px;
    cursor: pointer;
    opacity: .3;
    opacity: .8;

    :-webkit-full-screen .slideshow-fullscreen{
    background: rgba(0,0,0,.4) url(https://raw.githubusercontent.com/leemark/better-simple-slideshow/gh-pages/img/compress_ffffff_64.png);
    -webkit-background-size: contain;
    background-size: contain;
    :-moz-full-screen .slideshow-fullscreen{
    background: rgba(0,0,0,.4) url(https://raw.githubusercontent.com/leemark/better-simple-slideshow/gh-pages/img/compress_ffffff_64.png);
    background-size: contain;
    :-ms-fullscreen .slideshow-fullscreen{
    background: rgba(0,0,0,.4) url(https://raw.githubusercontent.com/leemark/better-simple-slideshow/gh-pages/img/compress_ffffff_64.png);
    background-size: contain;
    :full-screen .slideshow-fullscreen{
    background: rgba(0,0,0,.4) url(https://raw.githubusercontent.com/leemark/better-simple-slideshow/gh-pages/img/compress_ffffff_64.png);
    -webkit-background-size: contain;
    background-size: contain;
    :-webkit-full-screen .slideshow-fullscreen{
    background: rgba(0,0,0,.4) url(https://raw.githubusercontent.com/leemark/better-simple-slideshow/gh-pages/img/compress_ffffff_64.png);
    -webkit-background-size: contain;
    background-size: contain;
    :-moz-full-screen .slideshow-fullscreen{
    background: rgba(0,0,0,.4) url(https://raw.githubusercontent.com/leemark/better-simple-slideshow/gh-pages/img/compress_ffffff_64.png);
    background-size: contain;
    :-ms-fullscreen .slideshow-fullscreen{
    background: rgba(0,0,0,.4) url(../img/compress_ffffff_64.png);
    background-size: contain;
    :fullscreen .slideshow-fullscreen{
    background: rgba(0,0,0,.4) url(../img/compress_ffffff_64.png);
    -webkit-background-size: contain;
    background-size: contain;
    var makeSLIDESHOW = function (el, options) {
    var $slideshows = document.querySelectorAll(el), // a collection of all of the slideshow
    $slideshow = {},
    Slideshow = {
    init: function (el, options) {
    this.counter = 0; // to keep track of current slide
    this.el = el; // current slideshow container
    this.$items = el.querySelectorAll(‘figure’); // a collection of all of the slides, caching for performance
    this.numItems = this.$items.length; // total number of slides
    options = options || {}; // if options object not passed in, then set to empty object
    options.auto = options.auto || false; // if options.auto object not passed in, then set to false
    this.opts = {
    auto: (typeof options.auto === “undefined”) ? false : options.auto,
    speed: (typeof options.auto.speed === “undefined”) ? 1500 : options.auto.speed,
    pauseOnHover: (typeof options.auto.pauseOnHover === “undefined”) ? false : options.auto.pauseOnHover,
    fullScreen: (typeof options.fullScreen === “undefined”) ? false : options.fullScreen,
    swipe: (typeof options.swipe === “undefined”) ? false : options.swipe

    this.$items[0].classList.add(‘slideshow-show’); // add show class to first figure
    if (this.opts.auto) {
    this.autoCycle(this.el, this.opts.speed, this.opts.pauseOnHover);
    if (this.opts.fullScreen) {
    if (this.opts.swipe) {
    showCurrent: function (i) {
    // increment or decrement this.counter depending on whether i === 1 or i === -1
    if (i > 0) {
    this.counter = (this.counter + 1 === this.numItems) ? 0 : this.counter + 1;
    } else {
    this.counter = (this.counter – 1 < 0) ? this.numItems – 1 : this.counter – 1;

    // remove .show from whichever element currently has it
    // http://stackoverflow.com/a/16053538/2006057
    [].forEach.call(this.$items, function (el) {

    // add .show to the one item that's supposed to have it
    injectControls: function (el) {
    // build and inject prev/next controls
    // first create all the new elements
    var spanPrev = document.createElement("span"),
    spanNext = document.createElement("span"),
    docFrag = document.createDocumentFragment();

    // add classes

    // add contents
    spanPrev.innerHTML = '«';
    spanNext.innerHTML = '»';

    // append elements to fragment, then append fragment to DOM
    addEventListeners: function (el) {
    var that = this;
    el.querySelector('.slideshow-next').addEventListener('click', function () {
    that.showCurrent(1); // increment & show
    }, false);

    el.querySelector('.slideshow-prev').addEventListener('click', function () {
    that.showCurrent(-1); // decrement & show
    }, false);

    el.onkeydown = function (e) {
    e = e || window.event;
    if (e.keyCode === 37) {
    that.showCurrent(-1); // decrement & show
    } else if (e.keyCode === 39) {
    that.showCurrent(1); // increment & show
    autoCycle: function (el, speed, pauseOnHover) {
    var that = this,
    interval = window.setInterval(function () {
    that.showCurrent(1); // increment & show
    }, speed);

    if (pauseOnHover) {
    el.addEventListener('mouseover', function () {
    interval = clearInterval(interval);
    }, false);
    el.addEventListener('mouseout', function () {
    interval = window.setInterval(function () {
    that.showCurrent(1); // increment & show
    }, speed);
    }, false);
    } // end pauseonhover

    addFullScreen: function(el){
    var that = this,
    fsControl = document.createElement("span");

    el.querySelector('.slideshow-fullscreen').addEventListener('click', function () {
    }, false);
    addSwipe: function(el){
    var that = this,
    ht = new Hammer(el);
    ht.on('swiperight', function(e) {
    that.showCurrent(-1); // decrement & show
    ht.on('swipeleft', function(e) {
    that.showCurrent(1); // increment & show
    toggleFullScreen: function(el){
    // https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
    if (!document.fullscreenElement && // alternative standard method
    !document.mozFullScreenElement && !document.webkitFullscreenElement &&
    !document.msFullscreenElement ) { // current working methods
    if (document.documentElement.requestFullscreen) {
    } else if (document.documentElement.msRequestFullscreen) {
    } else if (document.documentElement.mozRequestFullScreen) {
    } else if (document.documentElement.webkitRequestFullscreen) {
    } else {
    if (document.exitFullscreen) {
    } else if (document.msExitFullscreen) {
    } else if (document.mozCancelFullScreen) {
    } else if (document.webkitExitFullscreen) {
    } // end toggleFullScreen

    }; // end Slideshow object

    // make instances of Slideshow as needed
    [].forEach.call($slideshows, function (el) {
    $slideshow = Object.create(Slideshow);
    $slideshow.init(el, options);

    Thank You once again

  3. Greetings, Thanks for this set of coding. When I use it on 640×480 pictures the first one comes up full browser window width and the other ones show up as 640×480. It shows up properly if I shrink the browser window to display the picture at its proper size or smaller. When the pictures are smaller than the browser display window the first one is full screen and the others are regular sized.
    I just resized one of the pictures in the folder to a smaller size and it displays at its size of 400×300.
    I was thinking that the width=”100%” in the part of the code would stretch the photo, but is seems to only do that for the first photo in the list.
    Should I resize the photos to be that big or use columns in my web page that have an absolute width to match the photo sizes?
    I even tried pasting one of the small photos into the directory and changing the third picture in your example web page to point to that picture with the same results. The picture becomes small and displays in the upper left corner of the area and the next arrow icon remains on the right side of the browser window.
    I am using OS X Mavericks and Safari Version 7.1 (9537. Perhaps it’ll work differently on a different browser?
    Thanks – Greg

    1. Hi Greg,
      If you add width: 100%; to the CSS styles for .bss-slides figure then that’ll make all your images automatically fit to the size of the slideshow container, which is what I think you want. I will update my code accordingly, thanks for pointing out this issue!

    1. This script is pretty dependent on the order in which the slides appear in the DOM in order to cycle through the slides. That being said, the easiest/simplest way to show the slides in a random order might be to shuffle the order of the slides in the slideshow just before you initialize the slideshow (i.e. before you call makeBSS()). Here’s a method for accomplishing that with jQuery: http://css-tricks.com/snippets/jquery/shuffle-dom-elements/

  4. Hello Mark,

    thank you very much for programming this little slideshow. It´s really great, not little.
    But I spend a lot of time to find out, that it´s makeBSS(‘.demo1’, opts); and not ‘.bss-slides’.

    No it´s tunning, but the preview and next button doesn’t work. Any idea, what I could´ve done wrong?

    The site isn´t online in the moment, still only on my harddrive.
    It would be nice, if you can give me a helpful answer.

    Tank you very much in advance!

    Manuel (from Germany)

  5. Hi there!

    I got the slideshow to work, but I can’t seem to post more than one… Is there a setting that isn’t letting me do that? I copy the exact same html code of the one that works but it doesn’t show up?

    1. I would check whether both the slideshows have either a different class or different id, then initialize each one independently with makeBSS().

  6. Hi Mark,

    Thanks for the fantastic tutorial. I think this is one of the best and easiest slideshow I’ve come across.

    Wondering if you can help me out on a small hiccup. Everything works for me, the slideshow, the next/prev buttons, etc. However, my slideshow has shifted to the right and off screen a bit.

    The next/prev buttons are in perfect position (at edge of screen), but the slideshow shifted to the right. I’m guessing it has something to do with div container element. I can’t seem to fix it from the CSS file. Any clues? Thanks Mark.


    1. Hi Paul,
      I would try to make sure that the containing <div> doesn’t have any padding applied, and that the <figure> elements inside don’t have any margin applied. The developer tools in Chrome or Firefox can be really helpful with seeing what styles are actually being applied.

    2. Paul

      Did you find a solution to this. I have the exact same problem and have no padding or margins in the containing div

      1. Think I’ve found it:


        Most browsers will display the element with the following default values:

        figure {
        display: block;
        margin-top: 1em;
        margin-bottom: 1em;
        margin-left: 40px;
        margin-right: 40px;

        The only way I seem to be able to resolve this (being a css novice) is to override it when defining the images:

        which is a bit of a pain to add it to every image in the slideshow class but if I try to change figure in the stylesheet or the bss-slides figure as a default , it doesn’t work. i.e.

        figure {
        display: block;
        margin-top: 1em;
        margin-bottom: 1em;
        margin-left: 0px;
        margin-right: 40px;
        } either in my html file or the slideshow stylesheet.

        Not sure why.

        1. Must have had an error originally because:

          bss-slides figure{
          position: absolute;
          top: 0;
          width: 100%;


          now works

    3. Aloha Paul,

      provide a margin set up in css element .bss-slides

      position: relative;
      display: block;
      margin: 0;

  7. Hi Mark,
    Great slideshow! One question; any plans to make this work in ie? I thought I’d ask before I start picking the code apart to try and make it work. I’m guessing it’s css thing.

  8. Hi Mark,

    Thanks so much for this slideshow. I’m having problems getting it going. I’m totally new to javascript, and I was hoping to use this as a tutorial, but I think I’ve tried something a little too ambitious.

    After setting everything up, when I load the page containing the slideshow, I can’t see any image. I know it’s there because if I open the image in another tab, it appears. I think the javascript isn’t changing the class to ‘show’, meaning all the images’ opacity are left at 0.

    I noticed on all the examples you’ve created, you have another class such as ‘demo1’ attached to the slideshow div and this is the class you call in the tag. Do you have do anything else with this class, such as define it in the css? I initially thought you just needed the ‘bss-slides’ class in the script tag before inspecting the elements of your demos. Do you need to use a second class name for it to work?

    I created another class called ‘slideshow’ but I’m still having the same problem. I’ve sort of reached my limit of troubleshooting. Is there anything else I should check?

  9. Hi Mark,

    Can’t get it to work and I know why… I suck as a web developer! However, this slideshow looks like it’s exactly what I need. A little help would be very appreciated if you got the time… I think my main problem is getting the html togheter. But lets take it from the start..

    With my limited knowledge I’m guessing this is what I need to do:

    1. Download better-simple-slideshow.min.js, simple-slideshow-styles.css, the two toggle images an put them in folder in my site. I don’t need do edit these in any way (?).

    2. Create a HTML page (For example MySlideshow.html) in the same folder that references and makes use of the the .js and .css files above by:
    – referencing them by doing an include
    – (if desired) create an options object
    – initialize the slideshow by calling makeBSS

    I this correct? If it is then I think I need an small but complete example for the “MySlideshow.html”, because that’s got to be where my problem is…

    Sorry for the presumably stupid question :)

    Kind regards


  10. Mark,

    Great work, thank you for sharing!

    I am curious as to why the auto-cycle doesn’t work if I comment out injectControls

  11. Mark,

    Great work, thank you for sharing!

    I am curious as to why the auto-cycle doesn’t work if I comment out injectControls?

    The idea is to remove the controls and just have it cycle.

    I’m working around it by making the controls the same color as the background.

    Thanks again!


    1. Mark,

      If finally dawned on me. The auto-cycle didn’t work because the script failed when it tried to add event listeners to non-existent spans in the addEventListeners when injectControls wasn’t called.

      By commenting both functions out it works just like I hoped!

      Thanks again!


      1. Thank you Scott. I was looking for this. But I enhanced it as an option to turn the controls on or off. This is what I changed in the javascript-file.
        behind line 17 I added a comma and added a new line of code.
        Old line 17: swipe: (typeof options.swipe === "undefined") ? false : options.swipe
        New line 17: swipe: (typeof options.swipe === "undefined") ? false : options.swipe,
        After line 17 I added: controls: (typeof options.controls === "undefined") ? true : options.controls
        It means that, if you don’t define it in your html you will always have controls.

        Further down the line I replaced lines 21 and 22:
        if (this.opts.controls) {

        Finally in my html-file containing the slideshow(s) I added the option to turn the controls off:
        controls : false

  12. Great Tutorial and fantastic code!

    I eventually got past the timing issue when doing slideshows with different numbers of slides by dividing number of slides into 100 to get a starting point for the timing, adding a blank slide at the end, and then increasing the values slightly until it looked how I wanted.

    Only problem now is that though it works great on iPhone and iPad running IOS 7, even the titles came up if you tapped the images, it does not work on IOS 8 and I can’t figure out what is up with the webkit thing.
    Have you any clues?
    Thank you again. Happy New Year!

  13. Giving this a shot for using with collected weather maps (radar) and other time captured files. Simple to implement with your great tutorial.

    Unlike a photo slide show, these would show radar map stills in quick succession to display the past hours movement or in the case of Satellite maps, last 24 hours.

    It is working great so far… but I am experiencing some weird blinking on Chrome that is not happening on IE11 or FF. On chrome, after the images go through the first round, the images start to blink. IE11 and FF don’t do this.

    Wondering if I am missing a setting that would relate just to Chrome.

    Note that I have turned off the delay of opacity and the speed of the images is set to 200. Doesn’t matter if the background is dark or light. Like there is some dark in between background color being set. Again, this is only happening on Chrome.

    Again, thanks for the great scripts…

  14. Mark,

    The issue that I reported with blinking on chrome was corrected by changing the opacity in the CSS from 0 to 1 in the .bss-slides figure img tag. Note that I am not using transitions for this purpose so *transition: opacity 0s; is set to 0

    .bss-slides figure img{
    opacity: 1;
    -webkit-transition: opacity 0s;
    transition: opacity 0s;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;

  15. I cant see the full screen button. Tried the demo on 3 different browsers IE 11, Chrome and Safari. Sometimes you can see it top left when you click the next or prev buttons but you cant click it in time.

  16. Hi Mark, Great Slideshow!! truly helpful!! I have one query..I am not able to control the speed of slideshow and also unable o activate pauseonhover feature. Help required. Thanks!!

  17. Hi Mark,

    thanks for a great tutorial and an awesome slideshow,

    im looking to add my own buttons (png s), is that possible? and how do i do that?

    step by step instructions would be appreciated since im not a web ninja.

    thanks again and keep up the good work.

  18. Omg, thank you very much!
    I finally found a slideshow that is working!!
    I spent more than 2 whole days finding the perfect one. So many others have failed.

    Many greets from Germany,

  19. Playing with the better simple slideshow, and for some reason I get a black bar where the PREVIOUS button is that shoves the picture over. The next button is still on screen, but I have a scroll bar to see the entire pic. What did I do wrong, or is this by design?

  20. Progress… or maybe not. I figured out the black bar (or at least I made it go away), but still behaving oddly. All three of the images are exactly the same size. When the second and third slides load, the two slides drop about 20 px, then it returns to normal when it cycles to the first slide, then repeats the cycle of dropping down.

    Same issue occurs if I use the same image all three times. Any idea what might cause this to occur?

  21. Mark, great slide show!, well documented for dummies like me, has nice cross fades, lots of controls, works on five browsers, but I can’t figure how to get the index of the current showing slide. I want to add voiceover tags and use the index number as the audio start and audio file name that matches the slide. I’ve been able to play audio but have spent weeks trying to get the slides index number. The snippet below does not work and is probably not even close to what it takes… seems it should be simple tho.

    var x = document.getElementById(“bss-show”);
    document.write (x);

    I’m retired and my web site is just a ‘keep busy’ project. It’s for family, friends or anyone. I’ve given some space to my friend Dave Akers who has been researching the strange phenomena of things that go bump in the dark.

    If you can point me in the right direction, that would be GREAT!

    Is the main entry. I used a flash program for the original slides, but so many folks use Apple devices and so doesn’t work for them. What was Steve Jobs thinking! The most current set of slides is our trip to Ireland and does not use flash. I assume you can see the code with your browser or something better.

    This is your code, with a test shot at how to include audio with an audio message for you!

    This is something I found online that does voiceovers but has no cross fades, no controls and is buggy, however has a great routine for generating the play list. It does not do captions, but that’s ok since I’ve started to burn the captions into the slides. However on the other hand, captions would be a good thing if I re-do all the junk that’s on the site now.

    Not sure how all this Q and A stuff works but desperate enough to give it a try!

    Cheers and take care Mark!

    Lee Hurley

  22. Nice slideshow. And thanks for sharing.

    Not sure if I missed something in the setup, but I spent a couple hours spinning my wheels with photos expanding beyond the screen size (in spite of specifying width:100%). I finally found your demostyles.css file which removes margin and padding from all elements e.g. *{margin:0;padding:0;}. Adding this to the simple-slideshow-styles.css fixed my margin (and image sizing) issues.

    Hopefully this will save others some time!

    1. Jeremy,

      You totally saved me. My slides weren’t lining up with my arrows and the first slide was shifted above all of the other ones. Adding *{margin:0;padding:0;} fixed the issue.

      Thank you!

  23. Man this is a great slideshow! You make it very easy to understand and it seems to be laid out so well. I have just finished going through a textbook on javascript and was looking for something exactly like this to pick apart and see if I can figure out exactly how it works, and this was perfect as it was easy to read and your instructions were great. I had a hard time understanding the [].forEach.call(…) so i did a little bit of research to see if I could figure it out. I found a couple of sites explaining what it was and then came across this one by Todd Motto.


    He went on to talk about how doing that was bad. As I am a beginner I and don’t know/don’ t want to get into any bad habits I tried his solution to the problem and replaced a bit of code in the BSS. It seems to work great! However like stated before I am a beginner and not sure whether this is even good practice, could anyone advise me otherwise? or is this okay to use? Below is what I replaced I commented out the original code and below is the code I added.

    // remove .show from whichever element currently has it

    // [].forEach.call(this.$items, function (el) {
    // el.classList.remove(‘bss-show’);
    // });

    var removeClass = function(array){
    for(var i = 0; i < array.length; i++){

    // make instances of Slideshow as needed

    // [].forEach.call($slideshows, function (el) {
    // $slideshow = Object.create(Slideshow);
    // $slideshow.init(el, options);
    // });

    var createSlideshow = function(el){
    for(var i = 0; i < el.length; i++){
    $slideshow = Object.create(Slideshow);
    $slideshow.init(el[i], options);

  24. Hello Mr. Mark,

    This is very nice. BTW, can you also teach us how to add those little navigational circles under the slider OR above the images just a bit above from the bottom border?

    Thank you

  25. Mark,
    Very nice code. Just what I’ve been looking for. Everything works great except I can’t seem to get the fullscreen toggle to work. I never actually see a fullscreen toggle on the screen. I’ve enabled using the fullScreen : true option in the opts var. Tried IE11 and Firefox 36.0.4. Any ideas?
    Thank you. David.

  26. Absolutely great slideshow and tutorial!

    I have incorporated this into my website and used 3 slideshows in total. My only problem is the second and third seem to have small black boxes in the top left corner. This causes the pictures to sit lower on my page and also looks odd.

    Any ideas?

  27. Hello Mark!

    First of all, thanks a lot for this great tutorial! Learned a lot from it.
    But there is an issue: when swipe is done on mobile device, autoCycle doesn’t pause, which is not very nice. For example, user swipes to picture just to look at it a bit longer. So it won’t be good if after ms the picture slides away, I think. I understand that there is actually no mobile hover, but maybe there is some other way to implement pause (not stop) for mobile devices? Or all that can be done is just stop autoCycle when swipe is done (so in this case cycle won’t continue at all)? I am very interested to know your opinion on this issue.
    Thanks in advance!

  28. Hi Mark,

    Thank you for this slideshow!

    The images in my slideshow don’t show up, though…
    Could it be because of the background setting?

    I was planning on having a simple small slideshow.

    Thank you,


  29. (sorry have to re-write my comment the tags not displayed in your comments)

    Hi Mark thank you for the script however I have a big problem when using it and I would like you to suggest a possible upgrade to it…

    I never used FIGURE tags before first time. When I installed the script into a specific DIV area I want to fill the whole area of the DIV but I am getting a stupid css margin. Then I see that it is a default in many browsers:

    figure {
    display: block;
    margin-top: 1em;
    margin-bottom: 1em;
    margin-left: 40px;
    margin-right: 40px;

    I wanted to basically have all the margins set at zero px. Of course this not your fault but more of silly html language, but is there a replacement tag to FIGURE I could use so I dont have a white gap going round the sliding images.

    Many Thanks.

    Will be checking on your reply, hopefully you can help me out on this problem, otherwise will have to look for a different script.

  30. Hi Mark, I’ll try your code for the slideshow and it seems a great job but I have a question: if I wanted to load images automatically from a folder using PHP? Did you think about this opportunity or not? Do you know how to do this add?

  31. Hi Mark,

    thank you so much for your work!

    Would it be possible to restart the background counting in auto mode from the moment when someone clicks to go back or forth (mouse and touch)? You get the un-intuitive effect of an image suddenly changing when the counting continues in the background and this is not synchronised with the clicking. When I set the slide show to ‘pause on hover’ it completely stops on iOS….

    Thanks so much for answering all these questions here in the forum!

  32. Hi, love it! But i wonder what the next one will be :) I would love to have a preview window at the botom so you can se what images is coming up next.

  33. Is it possible to remove the PREV-NEXT tags?

    I do not want the customer or user to click on next or prev but just use the fantastic script code you have made. Easy to implement on your website and easy to use – thanks for that.

    Jesper Storm

  34. Hi Mark!

    Thank you for all your work on this slider! I love it!

    I do have a question: Is it possible to have the navigation buttons resize so that one could use horizontal and vertical images? I got it to position everything properly by using a height tag instead of width tag on the vertical images; however, the sizing of the navigation buttons reflects the first image.

    Have a wonderful day!

  35. Hi there Mark, I wanted to first say, I love your slideshow, its perfect for my personal website I am working on. I am on a quest to add more functionality to it by adding audio to each slide (HTML5) but am struggling to get that working. I am willing to pay you (or “donate”) to your cause to help me find the solution. Thanks in advance!

  36. Hi Mark, I really like your work and I was looking for something simple that I could use to replace the ultra basic random background images that I am using here: pearsonappstore.com. The problem that I’ve been having is that I’m using jquerymobile and I only want the slideshow to run on the 1st page of the jquery code. Right now, I use the following simple .php style and the random image name: It covers the background behind my text content just fine:

    #home.ui-page {
    background: url(pics/) no-repeat fixed left top;
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;

    And as you can see, the #home.ui-page is the only jquery page that displays the background image and this is correct. I’ve tried implementing some slideshows, but they either run on all jquery pages, or they run on top of my #home content or below it.

    Do you have any suggestions on how to add your slide show so that it runs in the background of #home.ui-page only and behind the page text / content?



  37. hello mark,

    I am a complete beginner trying to create a website.
    While making my website, I realized my pictures took too much space so I searched for a slideshow and found yours.

    I have 3 problems which I hope I can get some help with..
    These will probably seem like really silly questions :

    1. The pictures arent moving. (The arrows do work) .
    2.The window is too big. Can it be made smaller?
    3. The arrows on the sides work but are slightly misplaced (too much to the left).
    4. Does the div class need to be

    Thanks :)

    Kind regards,

  38. Great post, thank you! I’m JavaScript beginner, so the post was very helpfull.

    One thing that bothers me is that auto transition keeps going on on its own rate even if user clicks on forward or backward button, so sometimes it just skips two images or transiton happens in too short time. I think that after user moves slides in any direction, the automatic transion (setInterval) should be reset, so the next slide automaticaly appears after auto.speed miliseconds.

    Somehow I managed to get that effect but I,m not sure if that is the right way (as I said I’m not very expirienced in object programming).

    Anyway, this is what I did:

    1. Modified autoCycle method so it returns handle of the interval:

    return interval;

    2. Defined new property of the Slideshow object, timerRef, that keeps the handle of the interval:

    if (this.opts.auto) {
    this.timerRef = this.autoCycle(this.el, this.opts.speed, this.opts.pauseOnHover);

    3. Modified showCurrent method to reset the timer if forward or back button was clicked:

    if (this.opts.auto) {
    var that = this;
    this.timerRef = clearInterval(this.timerRef);
    this.timerRef = window.setInterval(function () {
    }, this.opts.speed)

    And it worked, but I’m pretty sure there must be a more ellegant solution. If you could sugest one, it’ll be very nice of you.


  39. Great SlideShow Tutorial Mark,

    I had to change this,
    .bss-slides figure{
    position: absolute;
    top: 0;
    margin: 0 auto;
    width: 100%;
    To make the SlideShow super perfect, it would be nice to have the dots
    to skip several slides in advance.

    Can’t wait to use it,
    Thanks Mark


  40. Greetings,

    Just wondering how to set the number of cycles.
    Suppose I want to run the slideshow in autopilot only once.
    How can I do that?


  41. First of all thank you for your great help, it really looks great but i have a problem.
    I’m trying to make a website as a project and i wanted to add this slideshow, but it won’t work, i tried everything but still it won’t, do you know why ?

  42. Hi Mark;

    Apparently the slideshow tries to load all the slides at once. If there are only a few, it works fine.

    I’ve been testing with only 4 slides, with a voice over track for each slide. When I loaded it up with 200 slides, Firefox would only display a black screen, Chrome and IE would display about 150 slides.

    Is there a way to control the number of slides it pre-loads? (like pre-fetch = 4, user adjustable.) Actually, if the program would know on it own when to stop pre-loading before it gets into trouble, that would be even better.


  43. Good evening,

    I’d like to thank you very much Mark for this complete work and documentation. I wonder if there is a way to place 2 or more slides side by side since we have ultra wide screen monitors nowadays?
    Anybody an idea?

    Thanks in advance!

  44. Good evening Mark Lee,
    I’m not very good in English and a dummy in Javascript. And I’m impressed by your slideshow.
    You write under “Features” : “multiple slideshows per-page” and I thought you meant that the screen can be divided in some parts, each of them displaying a different slideshow. I think I’m wrong but it’s what I would like to do. It’s not on a wwebsite but as an offline app.
    In fact I grabbed pieces of code on various places on the web and tried to customize them. With almost no knowledge at all in javascript I managed to have two slideshows running one upon the other on the screen but there are some issues.
    1) My model was an automatic slideshow but the running of both slideshows musn’t be automatic, but trigged by a footpedal.
    2) The changes of pictures in both slideshows musn’t happen simultaneously but alternatively, on a press on the pedal.
    3) The pedal should trigger alternatively (kind of a toggle) the upper slideshow and then the lower one.
    The question is: if I download your entire code, will it be possible with no big effort to modify the features in the way I explain under 1, 2 and 3 above ? Do you think that a dummy like I am would achieve this `?
    Thank you in advance for your expert’s advice.
    Kind regards
    Pierre Ruel

  45. Hi Mark,

    Thank you for the ecxellent tutorial.
    This was the basics of my own slideshow.
    I’ve changed a lot, mostly with “try and error!”, and after asking “selfhtml”.
    Because I’m not a programmer, the code is maybe not really fine :-(
    But hey … it works:
    The code is here:
    But, sorry, no support, I really don’t now how this works :-)

    LG Peter

  46. Hi,

    Can there be Text on these Slide Shows?
    That is are we sliding a DIV with these images as Background and can hence add Text on these images as we want? Or is this Slide show limited to image sliding only?

    Dean @ Anoox.com

  47. Great slideshow !!!!!!!!! I had two issues;

    Image moving could be fixed by

    .bss-slides figure{
    position: absolute;
    top: 0;
    width: 100%;
    margin: 0; /* added to fix image moving */
    padding: 0; /* added to fix image moving */

    The other issue is this doesn’t work on IE7, IE8, and probably not on IE9. It works on IE10, IE11, Edge, Chrome, Safari. I couldn’t blame visitors but used

    …. (normal slide show)

    …. (normal slide show)

  48. Great Work!

    How to use multiple slideshows on single page? Below is my js code but only first slideshow works and others don’t work.

    var opts = {
    auto : {
    speed : 3000,
    pauseOnHover : false
    fullScreen : false,
    swipe : true
    makeBSS(‘.slide1’, opts);
    makeBSS(‘.slide2’, opts);

    Here only slide1 works and slide2 shows nothing.

    Please help me out!

    Regards & Thanks in advance!

  49. First things first – great slideshow. Next, a question. Have you made it into a plugin for WordPress? I see you use it here with your WordPress site.
    Thanks for all this work.

  50. Mark…you are a beautiful man for posting and sharing this library. Doing a favor for a friend on his site and this fit the bill for an simple straight forward slide show of work he’s completed.

    You have my thanks.

  51. Mark — I love your simple, plain JS slideshow. Precisely what I need including support for forward and back using the keyboard. I’ve adapted the look and feel to suit my customer’s needs, however, there’s one operation I can’t seem to implement. You have the slide show pause or stop on hover — which is perfect — but I need the slideshow to also pause when a popup opens above the image and then restart when the popup closes. I’m an intermediate JavaScript programmer. Is there a way to extend your Slideshow to add a pause and resume feature that I can call from another function?

  52. Hello Mark,

    thanks for this very good slideshow! I very much like the touch support.

    I just have one question about IE9: I cannot get the slideshow to work in it.
    I see this error:
    SCRIPT5007: Unable to get value of the property ‘add’: object is null or undefined
    better-simple-slideshow.min.js, line 1 character 506

    –> I think the problem is with this line, could it be that IE9 does not support el.querySelectorAll(‘figure’)?

    this.$items = el.querySelectorAll(‘figure’); // a collection of all of the slides, caching for performance

    My document is html5 and IE9 is in standards mode.

    If you would have the time to look into my question, I would be very grateful!

  53. I have not done anything like this in over 10 years. I really would like to add this to our site but am a little confused on what I actually need to do. What files do I need to download and where do I put what? Any help with this would be appreciated

  54. Cool, can I get something that people that can really use? What snippet goes where, what is the file name, how do you modify it, how does it work together, what is the file name you should save and where, what background do you need to understand what you are doing? How can this translate to someone new to this actually get into a working format and structure for their web sites? Why is it that some line of texts pasted means something on it’s own, what are you supposed to do with what you shared?

    Is there any background and assumptions made towards the programmer to use this information, what is it supposed to apply towards, how is it supposed to work in a web page on it’s own? On and on and on like this. Do you want some Pov Ray code to compare with?

  55. I am so confused – I’ve implemented the code exactly as is in the ‘getting started guide’ but my page loads to a blank image. The image works fine, was loading fine before trying this code out. Why is it not showing up? I copied and pasted from the source code, only changing the file names (and yes there aren’t typos)

        1. Yes but maybe you can also help me with this – My portfolio is a work in progress and my domain hasn’t yet transfered from Squarespace (from the days before I learned any dev skills lol). Is it safe to share the IP (on siteground I can access my site by its IP).

  56. After I initially commented I appear to have clicked the -Notify me when new comments are added- checkbox and from now on every time
    a comment is added I get 4 emails with the same comment.
    Is there a way you are able to remove me from that service?
    Thank you!

    1. The comment notifications are handled by wordpress.com. If you have subscribed to be notified when new comments are posted, then there should be a link that the bottom of the notification emails that you receive, which you can click through to manage your subscriptions. Here’s a direct link to where you can remove yourself: https://subscribe.wordpress.com/

      Best of luck!

  57. Hi Mark,

    Hopefully you can answer this one too – If an image in the slideshow is in portrait as opposed to landscape, it will often overlap my footer. Is there a way to avoid this? I’ve also noticed that when adjusting the width to say 80% as opposed to what you’ve set it as 100% the image will no longer be centered.

    1. It appears to go by whatever the first image’s height is.. So if I have a landscape image followed by a portrait image, my site won’t resize and it will eat up the footer. But if the first image is really tall, the footer will be lower (but also so will the arrow left and right buttons.

  58. Hello Mark, thanks for the excellent slider!

    Now, I have an issue in IE9, that I cannot solve.
    I get this error message:
    SCRIPT5007: Unable to get value of the property ‘add’: object is null or undefined
    better-simple-slideshow.js, line 22 character 17
    My document is html5, my browser mode is IE9 standards.

    I know that supporting IE9 is not common anymore, but my client would like to have it supported.
    Maybe if you have some time, would you know how to fix this?
    Kind regards!

  59. I am trying the better simple slideshow. Having a problem. The image is being displayed to the left of the “prev” arrow. This moves the image to the right and off the screen a little.
    Also, the first image is displayed a little higher than the rest of the images.
    I first tried this within the template of a website. To make it easier I created a simple page that only displays the slideshow. But, the simple slideshow also has the same problems.

  60. Hi,

    You have done a great job for just an afternoon of work and it does function well as drop-in code.

    I believe I may have improved on your work in a small way, which you will be able to see on my website however if you are still developing this I can create a simplified version in terms of having no extraneous elements.

    It seems the best ideas come from those who can make form follow thought and I feel you have this ability in spades.

    Kind regards

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.