…are built with our regular components, but there are some special requirements due to their multi-layered nature. For the images we can use the same multiple aspect-ratio picture/srcset setup, and we can overlay text and interaction with .imgteaser-content. Just plain images are fine, too, but then you probably can go with the css-only version.
The only requirement is that these images have to match the aspect ratios of the #slides container, because the whole thing uses absolute positioning. 16:9 for desktop, 1:1 for tablet and 2:3 for mobile. It can be changed in res/scss/_slideshow.scss
This section also can be moved underneath the header bar by adding the .intro class to the outer #slides section like here. The left/right controls can be switched off by looking into line 3 of the script, but then again, the css-only version would be fine, I guess.
The advantages over the css-only version are: playback-controls, works with any number of slides. The disatvantage obviously is that you have to maintain formats and timing in the script and in the _slideshow.scss in parallel.
Missing or DIY: more positioning options for content inside the slides, which is potentially endless as are any contrast-aware features for text on picture backgrounds. These should be adjusted to the real environment where they appear.
Slideshow structure as shown above
<section class="intro" id="slides">
<div class="co-1 img-fill slide showing">
<picture>
<img …>
</picture>
<div class="imgteaser-content col top">
content
</div>
</div>
<div class="co-1 img-fill slide">
<picture>
<img …>
</picture>
<div class="imgteaser-content col top">
content
</div>
</div>
…
<buttons> etc. as play/pause controls go here
</section>
<footer> </footer>
<script> should be placed at the end
I‘m not quite sure where the script originally came from, and how much of it has been changed. Maybe from sitepoint.com, but I guess from an even older, simpler version. If you plan to make it more accessible and production-ready you should absolutely read the whole article from 2016.
Since I often used slideshows without playback-controls, I tried a »one-pager«-approach where everything happens in one place. To my delight it just worked, good-bye javascript, good-bye z-index, good-bye syncing timing and aspect-ratios in different places.
The animation here is just a css-animation with @keyframes – right in the head-section of the page.
The »slides« still need absolute positioning in order to sit on top of each other, but use their native z-index from the html source. So nothing gets in the way of navigation layers or modal dialogues. Unfortunately they don‘t stretch the container section to their size this way.
The solution: Slide No. 0 is a matching blank regular image (or picture / srcset ) which does expand the container to the desired dimensions. It's not part of the animation and never visible, because the actual slides are on top of it.
All the animation does is change the opacity of the slides / images. The first one stays visible all the time, the second fades in and is made invisible again when the third one has faded in, and so on…
All settings for the animation(s) are grouped in one place where you can change the duration and other features.
basic setup
<head>
<style>
#slideone, #slidetwo, slidethree, … {
postion: absolute;
top: 0;
left: 0;
}
#slidetwo, #slidethree, … {
opacity: 0;
animation-duration: 10s;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-direction: forward;
}
#slideone { /* no animation */ }
#slidetwo { animation-name: twoOfThree }
@keyframes twoOfThree {
16.7% {opacity: 0 }
33.3% {opacity: 1 }
66.6% {opacity: 1 }
66.7% {opacity: 0 }
}
#slidethree { animation-name: threeOfThree }
@keyframes threeOfThree {
50% {opacity: 0 }
66.7% {opacity: 1 }
88.3% {opacity: 1 }
100% {opacity: 0; }
}
</style>
</head>
<body
<section class="img-fill">
<div class="co-1">
<img src="dummy-3x2.jpg">
<img src="i1-3x2.jpg" id="slideone">
<img src="i2-3x2.jpg" id="slidetwo">
<img src="i3-3x2.jpg" id="slidethree">
<img …>
</div>
</section>
</body>
picture srcset instead of plain img
<head>
…
</head>
<body
<section class="img-fill">
<div class="co-1">
<picture>
<source media="(min-width: 90em)"
srcset="img/dummy-2x1.webp">
<source media="(min-width: 62em)"
srcset="img/dummy-16x9.webp">
<source media="(min-width: 48em)"
srcset="img/dummy-3x2.webp">
<source media="(min-width: 40em)"
srcset="img/dummy-1x1.webp">
<source media="(min-width: 20em)"
srcset="img/dummy-2x3.webp">
<img src="img/dummy-3x2.jpg" alt="dummy">
</picture>
<picture>
<source media="(min-width: 90em)"
srcset="img/i1-2x1.webp">
<source media="(min-width: 62em)"
srcset="img/i1-16x9.webp">
<source media="(min-width: 48em)"
srcset="img/i1-3x2.webp">
<source media="(min-width: 40em)"
srcset="img/i1-1x1.webp">
<source media="(min-width: 20em)"
srcset="img/i1-2x3.webp">
<img src="img/i1-3x2.jpg" id="slideone">
</picture>
<picture>
<source …> and so on
</picture>
<picture>
<source …> and so on
</picture>
</div>
</section>
</body
The @keyframes have to match the number of slides which is a pain in the butt to figure out but here are the values for three, four and five images. (For more than five you might want to use the js-version…)
For all sequences image No.0 is ignored, and the first real image #slideone sits on top of it, but doesn‘t change during the animation. All other slides are set to opacity: 0; from the start.
So the animation @keyframes only deal with the second to the last image:
three images
@keyframes twoOfThree {
16.7% {opacity: 0 }
33.3% {opacity: 1 }
66.6% {opacity: 1 }
66.7% {opacity: 0 }
}
@keyframes threeOfThree {
50% {opacity: 0 }
66.7% {opacity: 1 }
88.3% {opacity: 1 }
100% {opacity: 0; }
}
four images
@keyframes twoOfFour {
12.5% { opacity: 0 }
25% { opacity: 1 }
50% { opacity: 1 }
50.1% { opacity: 0 }
}
@keyframes threeOfFour {
37.5% { opacity: 0 }
50% { opacity: 1 }
75% { opacity: 1 }
75.1% { opacity: 0 }
}
@keyframes fourOfFour {
62.5% { opacity: 0 }
75% { opacity: 1 }
87.5% { opacity: 1 }
100% { opacity: 0 }
}
five images
@keyframes twoOfFive {
10% { opacity: 0 }
20% { opacity: 1 }
40% { opacity: 1 }
40.1% { opacity: 0 }
}
@keyframes threeOfFive {
30% { opacity: 0 }
40% { opacity: 1 }
60% { opacity: 1 }
60.1% { opacity: 0 }
}
@keyframes fourOfFive {
50% { opacity: 0 }
60% { opacity: 1 }
80% { opacity: 1 }
80.1% { opacity: 0 }
}
@keyframes fiveOfFive {
70% { opacity: 0 }
80% { opacity: 1 }
90% { opacity: 1 }
100% { opacity: 0 }
}
Well, actually it is. Here we just see everything in parallel, three times. You only use one set, I would assume, and the image stack (be it single images or srcset arrays) is the same for all versions. (And I didn’t repeat the script for the js-version here, you’ll find it in the html source of this page.)
If you don‘t need the js-version at all, you can exclude _slideshow.scss form styles.scss. Vice versa you can take all the slideshow-css from this page and move it to a new _cssslides.scss if you plan to use it in various places.
The only thing left is to assign the animations like fourOfFour to the respective slides – in the example the fourth (or last) of a four-image stack. The slides 1–5 can keep their ID-names #slideone … #slidefive no matter how many you want to use.
#slidetwo { animation-name: twoOfFive; }
#slidefour { animation-name: fourOfFour; }
Disclaimer: Everything here is free to use, but no responsibility is taken for any outcome. Questions & Suggestions: ak at alexkoch dot net (you‘re not a robot, I know). And I don‘t use cookies. Version history