simple CSS slideshow…

…recycled and partly polished.

As more and more end‐users upgrade their browsers, we don't have to worry about adding support for old and obsolete browsers anymore. Time has come to implement more pure CSS design techniques up front.

Here I am presenting, and to some extent dissecting, the “looping CSS slideshow” I call Sketch. That it is “looping” simply means there is no apparent beginning or end to the slides – you can go round and round in circles in my slideshow as much as you like.

IE9, IE10, Chrome, Opera, Safari, and Firefox handle my slideshow more or less as intended – no real problems observed.

Old browser versions like IE8 won't allow you to slide through much of anything, and if I have done my job they won't show much either.

Note: validity remarks…The W3C markup validator correctly flags lots of errors related to iframes (found in two slideshows) used in an XHTML Strict declared document.
No big deal in this case in my opinion, but in true recycling spirit: here is same document with same markup as valid HTML5 for those who insist on valid markup for whatever reason.
No use checking validity of CSS on this site.

not just another slideshow.

Keeping a sharp eye on everything in the area…
…making sure nothing of importance slips by.

Sketch is a looping CSS slideshow for inserting additional content and whatnot almost anywhere in a page.

Not much CSS behind the slideshow function itself, and no script – it is a pure CSS slideshow.

I can think of a few things Sketch may come handy for, so I think I'll keep it.

NOTE: some content is hidden from (mainly) older browsers because they simply can't handle it.

This first slideshow demonstrates how overflowing content in slideshow slides interacts with regular content further down on a page. Can lead to interesting design‐considerations.

Keeping a sharp eye on everything in the area…
…making sure nothing of importance slips by.

Sketch is a looping CSS slideshow for inserting additional content and whatnot almost anywhere in a page.

Not much CSS behind the slideshow function itself, and no script – it is a pure CSS slideshow.

I can think of a few things Sketch may come handy for, so I think I'll keep it.

NOTE: some content is hidden from (mainly) older browsers because they simply can't handle it.

This second slideshow contains its children, thus no interaction with other elements on the page. On rare occasions I like it this way, but in most cases / designs I prefer overflowing over “framed” content.

Can declare fixed height on the slideshow, or give it same‐height slides. Might work for showing pictures but not for much else, and I want to be able to include all kinds of content in any order in it. Thus, I usually only set min-height when it is necessary to “calm down” overall page designs a bit.

1(11)looping CSS slideshow dissected.

First I want to present the basics, where a very simple bundle of HTML gets a set of even simpler CSS styling. “KISS” (Keep It Simple Stupid), is very much at the back of my mind when coding web designs.

To demonstrate how my slideshow works as much as laying out what makes it work, this presentation is also a slideshow.

NOTE: code-snippets in this presentation only contain essential code, and none of the test styles and whatnot I spice up things with.

Stylesheets behind this site are full of test‐styles under constant change – this is after all not a regular production site. Thus, not much use copying my real slideshow styles verbatim for use on other sites.

The code-snippets presented in these slides should be enough for anyone to find out how things work, and from there build up their own HTML and CSS code and solutions. I encourage anyone with an interest in CSS based web design and solutions to go ahead and play around with the code provided in these slides.
It is free.

2(11)basic HTML.

Any element can in principle be used as slide. To contain video container + one or more paragraphs and/or other elements in any order, I normally use a <div> as slide‐container.

<div class="sketch" id="sketch">
   <input type="radio" name="sk" checked="checked" />
   <input type="radio" name="sk" />
      <img src="../imagefolder/picture.png" alt="" />
   <input type="radio" name="sk" />

Note that individual slides are single elements or containers that follow directly after an INPUT element. This “INPUT+slide” relationship is what I use to style a functional slideshow.

Note also that at least 3 INPUT elements with corresponding slides must be coded in – as in the example above, as selection won't work properly with fewer.

3(11)basic CSS.

INPUT elements are initially made invisible so they won't show up in older and out‐of‐range browsers, and then the entire slideshow styling is wrapped in a mediaquery that sets how narrow a window it will be shown in.

.sketch input {display: none;}
@media screen and (min-width: 300px) {

.sketch input {display: block;}
.sketch {position: relative; min-height: 200px;}

…here goes all slideshow styles…


Inside the mediaquery INPUT elements are made visible again, and then the slideshow container is defined as simple as possible – see following slides.

Whatever additional styling the slideshow container needs to fit in at a specific place in a page, is either taken from site‐wide classes, or added to the container in each case. This makes the slideshow much more “portable as is” than it would be with a full set of dedicated styles.

4(11)visually and functionally.

Arrows provide visible cues for where to click to switch slides, and both arrows are in one picture since it doesn't matter which way you go in a looping slideshow. Generated content carrying the image is floated in place so slide‐content can interact with it and stay out of its space.

.sketch::before {content: url(../imagefolder/arrowimage.png); float: right; 
   margin: -8px 3px 3px 5px; width: 72px; height: 33px; width: 72px; 
   position: relative; z-index: 2;}

All INPUT elements before the “checked” one are positioned over the left arrow and stacked in sequence. This assures the “previous” INPUT element is always on top and clickable, without further stacking concerns.

The INPUT element after the “checked” one is positioned over the right arrow. Then all INPUT elements further out in the sequence that are naturally stacked higher but should not be clickable, are simply hidden.

.sketch>input {height: 33px; width: 30px; top: -10px; right: 46px; 
   margin-right: 1.5%; position: absolute; z-index: 10; opacity: 0.01;
   background: url(../blank.png) /* IE opacity-bug fix */;}	 
.sketch>input:checked+*+input {right: 4px;}
.sketch>input:checked+*+input~input {display: none;}

Opacity is set low to make the INPUT elements invisible while fully functional. Setting opacity to zero caused buggy behavior in some browser, which is why it is set a little higher.

5(11)looping slideshow – part one.

To make the CSS slideshow loop around from last to first slide, or the other way from first to last, I made special cases of first and last INPUT element.

This was the slightly tricky part as CSS can't be used to select outwards (or backwards), but some logical sequence‐selection and stacking of INPUTs is all it takes.

.sketch>input:first-of-type {display: block; width: 70px; right: 4px;}
.sketch>input:checked:first-of-type~input:last-of-type {display: block; right: 45px;}

First INPUT is extra wide to cover arrows for both directions, and will therefore become clickable over the correct arrow both when second INPUT or last INPUT is “checked”. The other arrow is covered by INPUT element for the other direction, as shown in previous slide.

Last INPUT is positioned over left arrow only when first INPUT is “checked”. Normally it is positioned in sequence over right arrow, as shown in previous slide.

6(11)looping slideshow – part two.

Having the very wide first INPUT permanently covering both visual arrows, creates a problem in that it is always clickable in the middle area – between the arrows. To prevent faulty selections of first slide from any slide, I stacked a suitable sized image as “cover” on top of that middle‐area.

.sketch::after {content: url(../blank.png); position: absolute; top: -10px; 
   right: 28px; margin-right: 1.5%; width: 18px; height: 38px; opacity: 0.01; 
   z-index: 30;}

Now the first INPUT works when sliding in both directions, and the area between the arrows is never clickable. To me this behavior makes most sense, and the “cover” makes exact positioning and size of INPUTs either side less critical.

Of course, some may find it practical to be able to go to first slide from anywhere without having to step through many slides. No problem: just leave out the “cover”, use an arrow image that indicates the extra function when appropriate, and line up INPUTs accordingly.

7(11)show/hide slides.

Slides are hidden off‐screen, and moved on‐screen as their associated INPUT get selected. Once on screen there is a transition from low to full opacity, just as an unnecessary effect.

(Not all browsers support opacity‐effects on video yet, so transition may not work in some browsers that otherwise handle my slideshow just fine.)

.sketch>input+* {height: 1px; overflow: hidden; position: absolute; 
   display: block; top: 0; left: 0; opacity: 0.01;}   

.sketch>input:checked+* {height: auto; overflow: visible; position: relative; 
   top: 0; left: 0; opacity: 1; transition-property: opacity; 
   transition-duration: 1.5s;}

My “hide” method may be seen as a bit overdone, as slides get moved off‐screen and also shrinked to a very small height and overflow hidden. This hiding method is in part borrowed from an older slideshow, where slides are “hidden in plain view” packed next to the selected slide.

The off‐screen hiding was added because overshots in some page designs could become visible artifacts when hidden in plain view, and then the original “shrink and hide” method was kept because it prevented very large elements from ending up with on‐screen tails.

8(11)embedding YouTube video.

Here is an example. Next two slides show how video scaling works.

As there is no real limit to how many slides one can have in a slideshow, the number of videos one can embed in a page without running out of space can be truly “astronomical”. Show restrain.

9(11)HTML – embedding YouTube video.
<input type="radio" name="sk" />
   <p>maybe some text.</p>
   <div class="v-container">
      <iframe width="640" height="480" 
   <p>some more text, maybe.</p>

As for all slides the INPUT comes first, and to contain both embedded video and paragraphs, and maybe other elements, a <div> is used as slide container.

Inner video container – “v-container” – provides flexible space for <iframe> to scale on – see next slide.

I keep “width” and “height” on <iframe> as fallback and for future use. CSS overrides HTML attributes anyway so no problem having them there.

The video container – “v-container” – with <iframe> do of course work just as well for scaling embedded video anywhere in a page.

10(11)CSS – embedding YouTube video.
.v-container {position: relative; width: 100%; height: 22px; margin: 0 auto 5px; 
   clear: both; padding-top: 58%;}
.v-container.res1 {padding-top: 76%;}
.v-container.res2 {padding-top: 60%;}
.v-container.res3 {padding-top: 52%;}
.v-container iframe {position: absolute; top: 0; left: 0; 
   width: 100%; height: 100%;}

Video container is full width and gets spaced vertically with a fixed height to account for the video chrome. Vertical padding is then added with a percentage value roughly calculated from video's width/height ratio.

Have also included a few alternative vertical padding values as CLASSes to choose from to cover most encountered video width/height ratios. In my experience: a “slightly too high” video container is just right for embedded YouTube videos.

The iframe is absolute positioned top/left in video container and given full width and height, which assures it is automatically scaling with the slideshow's width with width/height ratio intact.

Sigh: video's width/height ratio calculated from <iframe>'s “width” and “height” attributes and ported to its container, may work – one day.

11(11)open entire slideshow.

To open an entire slideshow directly I ID:target its container. I use “sketch” as ID on this slideshow, so you can add “#sketch” to filename in your browser to test how it works. Or, you can just click here to open and here to close.

#sketch:target>input {display: none;}
#sketch:target::before {content: url(../imagefolders/grayarrowimage.png);}
#sketch:target>input+* {height: auto; overflow: visible; margin: 0 auto;  
   position: relative; opacity: 1; transition-property: opacity; 
   transition-duration: 1.5s;}

INPUTs get turned off to avoid sequence‐clutter, and arrow image gets replaced with a grayed‐out one to indicate that they are no longer clickable.

Adding the ID:targeting selector‐chain to the styles used to open single slides (see slide #7) takes care of the rest – open all slides in the slideshow.

recycle, reinvent and evolve.

My simple CSS slideshow is primarily built on recycled HTML, CSS and ideas from my many projects over the years, and will continue to evolve in my sandbox.

I see many possible uses for it, but also the risk of overusing it in its present form. That's how it is with all new building blocks in web design.

One interesting use I see for my slideshow is to let it act on larger parts of a page. My own pages are of course especially well suited to become slideshows, as the main section is already divided into reasonably sized blocks … Oh, alright, it looks like I have already tried that.

sincerely  georg; sign

Hageland 25.oct.2013
11.nov.2013 - added link to W3C's old test page.
30.sep.2016 - minor corrections related to site-wide CSS upgrade.
last rev: 30.sep.2016

side notes.

slideshows abound.

I am sure you have seen and played with slideshows on many sites. Most are driven by a mixture of CSS and Javascript, and a few are CSS‐only slideshows. Enough slideshows available on-line to satisfy any web designer and front‐end coder, and here is another one.

My slideshow is based on some old and obscure browser test pages on the W3C site (here is actual test page), where browsers' CSS support for INPUT elements' status were tested.

Since those tests worked fine in one of my browsers, I have over a number of years developed several CSS slideshows and other “fancy” play‐things. Didn't find much use for them outside my sandbox though since not all major browsers supported the relevant CSS at the time. Now, finally, I can implement some of them.

look ma, no borders … but have YouTube videos.

Keeping a sharp eye on everything in the area…
…making sure nothing of importance slips by.

Sketch is a looping CSS slideshow for inserting additional content and whatnot almost anywhere in a page.
I came up with Sketch for a project, and now I am trying (very hard) to find suitable uses for it on my own site.

Sketch and its child-elements do of course pick up site‐wide styles. Thus, it is pretty easy to match everything to existing site design.
Not much CSS behind the slideshow function itself, and no script – it is a pure CSS slideshow.

Sketch does for instance work well to embed a number of videos on a page without having them take up too much space.

the lighthouse tale

Tweaking video‐container's height in steps for different video width/height ratios.

No serious limitations on what can be served in Sketch.

Continuing to test Sketch to find practical uses for this form of looping CSS slide‐show.
I can think of a few things it may come handy for, so I think I'll keep it.


NOTE: some content is hidden from (mainly) older browsers because they simply can't handle it.

As no two slides are identical in size (height) and content (floats, etc.), they push following elements and content down and around to varying degree, which I kind of like. Maybe I am a bit fed up with all the squares found in my own and others' web pages.

One possibly negative side‐effect of having no borders, is that you can't easily see where the slideshow ends and the text or whatever is following it begins. Can be confusing at times…


So far I haven't found any real restrictions in what my looping CSS slideshow can be used for and where in a page it can be used. I am sure that as I continue to explore use‐cases I will find some minor weaknesses, but don't expect to find any real show‐stoppers.

Have “injected” the slideshow in several older pages on this site, and found it easy to rearrange appearance and how it presents content to go with its surroundings.

My looping CSS slideshow is also “injected” into other people's designs, and it seems to work OK for them as well.

One reason “injecting new HTML” works so well is that to a degree I am arranging CSS and HTML like my friend Thierry Koblentz describe in this Smashing Magazine article.

This means lots of tiny bits and pieces of CSS code are always available, and stylesheets won't have to be altered along with changes in the HTML all the time. Very practical not only for styling slideshows.


Although I originally had no intention to let my looping slideshow work on small screens, it seems to work reasonably well also on those while adapting to changes in overall page layout for various window sizes.

So far I am OK with what I see on screens as narrow as the present limit of around 175. See no reasons to go further down, as screens smaller than that are in my opinion not well suited for slideshows in any form.

Note: additional remarks…Tested and found OK in… Firefox & Chrome on Android 4.1.2 Samsung Galaxy Note 2
Not OK in… default browser on Android 4.1.2 advice upgrade advice upgrade navigation