birdwrongs
.games

Javascriptless Image Slideshow

2025-08-06

I made one of these for my games pages and realized it might be handy to other people. I learned to do this for code on Dreamwidth, actually, since you can't insert javascript into a post but you can do this if you need a tabbed/multipage interface. It can be really nice for when you want to show a bunch of screenshots but don't want to make your page super long! You can see an example on the page for Signal Strength on this website.

Now, it does have some limitations:

  • It doesn't do any kind of smooth animated transition between slides
  • It'll jump the slideshow to the top of the visible window unless you sprinkle in a little javascript, which may be a little annoying to some users
  • Uses slightly more HTML code/DOM nodes than javascript slideshows due to needing a forward/back button for every slide, which in extreme cases might slow down a page but I don't think anyone is going to put that many slides in it, honestly.
  • Kind of hard to do anything funky where you have multiple images showing at a time or want to scroll the slider or have slides that aren't 100% width
<div class="gallery">
	<div id="gal-1" class="gallery-item">
		<a href="#gal-3" aria-label="Previous"><i class="fa-solid fa-arrow-left"></i></a>
	  <a href="img-full-url.jpg" target="_blank">
	    <img src="img-full-url.jpg" />
	  </a>
		<a href="#gal-2" aria-label="Next"><i class="fa-solid fa-arrow-right"></i></a>
	</div>
	<div id="gal-2" class="gallery-item">
		<a href="#gal-2" aria-label="Previous"><i class="fa-solid fa-arrow-left"></i></a>
	  <a href="img-full-url.jpg" target="_blank">
	    <img src="img-full-url.jpg" />
	  </a>
		<a href="#gal-3" aria-label="Next"><i class="fa-solid fa-arrow-right"></i></a>
	</div>
	<div id="gal-3" class="gallery-item">
		<a href="#gal-2" aria-label="Previous"><i class="fa-solid fa-arrow-left"></i></a>
	  <a href="img-full-url.jpg" target="_blank">
	    <img src="img-full-url.jpg" />
	  </a>
		<a href="#gal-1" aria-label="Next"><i class="fa-solid fa-arrow-right"></i></a>
	</div>
</div>

This is roughly the structure of the HTML code, although I have mine set up in a static site generator, so I don't have to manually code every slide. The important parts are:

  • There's a container div to put all the slides in
  • Every slide has a unique (probably numbered) ID on the outer container
  • Every slide has its own back button and forward button. If you don't want it to loop, you don't need to include a back button on the first slide or a next button on the last slide. These link to the ID of the previous and next slides. (I guess they could link to slides in whatever order. Embrace chaos) In my case, I'm using Font Awesome's arrow icons.
  • Also make sure either the prev/next buttons have text, a title, or an aria-label for accessibility!

When you put this markup in, it'll just show the images sitting on top of each other in the container, so it gracefully degrades if for some reason someone is in a CSS-less browser or on a like, really slow connection.

Now, the sauce that makes it all work:

.gallery {
  display: flex;
  overflow: hidden;
}
.gallery .gallery-item {
  min-width: 100%;
  position: relative;
}
.gallery .gallery-item img {
  max-width: 100%;
}
.gallery .gallery-item [aria-label] {
  position: absolute;
  top: 0;
  height: 100%;
  padding: 20px;
  z-index: 5;
  color: var(--background);
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}
.gallery .gallery-item [aria-label="Previous"] {
  left: 0;
}
.gallery .gallery-item [aria-label="Next"] {
  right: 0;
}

What this is doing:

  • Sets the container div to display: flex, which without any flex-wrap value, puts all the images into a long horizontal strip that'll overflow the container.
  • Hides the overflow with overflow: hidden
  • Sets all the slides to be 100% the size of the container, and all the images to be the width of the slide
  • Gives each slide position: relative so we can position elements inside the slide relative to the slide
  • Positions the back/next buttons on either side of the slide using absolute positioning, and horizontally centering them by setting display value to flex and align-items to center

At this point, you'll have a container that shows exactly one image, and its back and next buttons. Since container IDs are also considered anchors by the browser, when you click on a prev/next link, it'll try to scroll to the element with that ID... and since it's in this overflowed box, it'll scroll the position of the elements inside automatically to have the item with that ID at the "top" of the container—that is, visible to the reader.

Tags: Website