By: Paul S. Cilwa | Viewed: 5/4/2024 Posted: 3/27/2023 |
Page Views: 420 | |
There are a lot of hints on the Web how to create CSS-only slide shows. This one works. |
I recently posted a blog entry inspired by our addition of a new doggie door. I had taken three pictures of my grandson, Dominic, demonstrating the doggie door to the dogs, who understandably were taken aback by it. To display the three photos, I wanted to fade one over the other, as opposed to simply displaying one below the other. However, to my surprise, I found that the instructions to do what I would call a pretty basic function, were murky at best, or very specifically aimed at special circumstances: two or four pictures but not three; or photos of a specific and unchangeable size (not the size of mine). Modifications didn't seem to work; so the only remaining option was figuring it out on my own. But I did, so now you won't have to.
To be clear on what we're working with, here are thumbnails of the three images:
I took all three photos from the same position, and used my preferred software (Zoner Photo Pro to align the three as closely as possible with a handheld phone camera.
When I was looking up how to do the mini-Carousel I wanted, I encountered references to both CSS Transitions and Animations. Both are used to create animations and dynamic effects on web pages, but they work in different ways.
CSS Transitions allow us to create a transition between two states of an element. For example, we can use a transition to smoothly change the background color of a button when the user hovers over it. Transitions are triggered by a change in the state of an element, such as a hover, click, or focus.
CSS Animations, on the other hand, allow us to create more complex animations with more control over the timing and sequence of events. Animations are not triggered by a change in the state of an element, but instead can be set to run automatically or on a loop. In addition, we can use animations to create more complex effects such as a slide show or an animated loading spinner.
When creating a slide show with multiple images that repeat on an infinite loop, CSS Animations would be a better choice than Transitions. With Animations, we have greater control over the timing and sequence of events, allowing us to create more complex and dynamic effects. Additionally, Animations can be set to run automatically, without requiring user interaction.
Using the animation-iteration-count: infinite
property, we can set our
slide show to run on a loop indefinitely, and can control the duration, delay,
and timing function of each animation to create a seamless and visually appealing
effect. Being able to repeat the effect indefinitely, alone, makes CSS Animations
the better choice in this case over Transitions.
Using CSS to create a Carousel that fades or dissolves from one photo to another is a great way to showcase a series of images in a visually engaging way. The terms "fade" and "dissolve" were originally used in movies to describe the transition from one scene to another. In movies, a fade occurs when the screen gradually becomes black or white, and a dissolve occurs when one image gradually replaces another. Nowadays, these terms are often used interchangeably in online graphics and refer to a smooth transition from one image to another.
We can do this all within CSS (no need to resort to Javascript), and the HTML is simple and intuitive. You should be able to remember the class name and syntax without having to look it up every time.
To start, create a <div>
element with the class
name "Carousel" and place each photo inside an <img>
tag,
like so:
<div class="Carousel">
<img src="20230130_152036.jpg" ⁄>
<img src="20230130_152038.jpg" ⁄>
<img src="20230130_152041.jpg" ⁄>
<⁄div>
Until we define a Carousel style for <div>
tags,
the above code will display the three photos inline, one after the other. In order
to place the photos on top of each other instead, we must start by making
this <div>
relative rather than the default of static.
That's because we want the contained photos to all appear in the same space,
which we'll do by giving the images an absolute position. If the containing
division was static, the left and right properties would position the
image relative to the page as a whole, instead of within that division.
When you set an element to position: absolute
, it is positioned relative to the
nearest positioned ancestor element. If there is no positioned ancestor element,
it is positioned relative to the initial containing block (usually the <html> element).
So, if the parent <div> element is position: static
,
the child <div> element with position: absolute
will be
positioned relative to the initial containing block. However, if you set
the parent <div> element to position: relative
,
the child <div> element will be positioned relative to the parent element.
So, in our CSS, that's the first definition we provide:
div.Carousel
{
position: relative;
}
I saw some examples online of having two nested <div>
s,
but that's unneccesary because CSS selection rules let us specify any images contained
within the Carousel
<div>.
Next, we have this CSS code which selects all img
elements that are descendants
of a div
element with the class "Carousel". The position property
is set to absolute
, which means that the images will be positioned relative
to their closest positioned ancestor, which in this case is the div element with
the class "Carousel".
div.Carousel img
{
position: absolute;
top: 0;
left: 0;
opacity: 0;
box-shadow: none;
animation-name: Carousel;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 4s;
}
There's a significant technique shown here. Some other examples I saw required
each image to have its own class name! But CSS allows us to specify "any
image inside a <div>
of the "Carousel" class.
The top and left properties are set to 0, which means that the images will be positioned
in the top left corner of the div
.
The opacity
property is set to 0, which means that the images are
completely transparent and will not be visible until the animation is triggered.
This is the behavior we want from all the images except the first, which is something
we'll address in a moment.
Now, on this, my personal web site, as of 2023, images are, by default, given a shadow to make them sort of jump out off of the page. If I position other images on top of the first one, the shadows, which are semi-transparent, add up and wind up looking too dark. So, I have to turn off shadows for images in this container; I'll turn it on for the first image shortly.
The animation-name
property connects this object to a CSS keyframes
function. We'll come back to this shortly.
The animation-timing-function
property is set to ease-in-out,
which specifies the speed curve of the animation. The ease-in-out value means that
the animation will start slow, accelerate in the middle, and slow down again at the end.
I find the fades look a little more natural this way.
The a nimation-iteration-count
property is set to infinite,
which means that the animation will repeat indefinitely.
The animation-duration property
is set to 4s,
which means that the entire animation will last for 4 seconds.
Let's talk about that four seconds for a moment. In this example, we have three
pictures. I want to fade each into the other for a full second, with the final
image showing for a full second before fading back to the first image. That means that
the first image must always be opaque (visible) since the other images will be
displayed "on top of" it. In the code above, all images are set to invisible
(opacity: 0
).
But we can also reference images within that division by their
ordinal position. For example, we have to make the first image always visible;
and I also want to replace the standard box-shadow
values that
we nullified in the vanilla Carousel image style block.
div.Carousel img:nth-of-type(1)
{
position: relative;
opacity: 1;
box-shadow: 5px 5px 10px black;
animation-name: none;
}
We also have to overridde the position
property. The reason for this isn't obvious.
But the enclosing <div>
will not take up any space unless it contains
at least one relative
or static
object; and it sizes itself for
exactly that much room.
Finally, we override the vanilla div.Carousel img
properties by specifying that
this image, the first within the <div>
, will not participate in
any animation. Instead, it's just gonna sit there while the other images appear on top of it.
When they have faded away, this first image will remain.
div.Carousel img:nth-of-type(2)
{
animation-delay: 1s;
}
div.Carousel img:nth-of-type(3)
{
animation-delay: 2s;
}
The remaining images, then, merely need to have the animation-delay
property adjusted. The first image is already there; the second will start to fade in
after the first second; the third will start at the second second.
To do the rapid image switching I want, the animation-duration
will always be 1 greater than the number of images. If you have more than three images,
just repeat the above :nth-of-type
snippets for as many as you like.
(Note that there's no practical downside in creating extras for as many images
as you can imaging wanting to appear in this manner.
Our last step, the, is defining the animation-name
keyframes
rule:
@keyframes Carousel
{
0% { opacity: 0; }
25% { opacity: 1; }
50% { opacity: 1; }
90% { opacity: 0; }
100% { opacity: 0; }
}
This CSS code defines a @keyframes
rule with the name Carousel
.
This rule contains a series of keyframe selectors, each specifying whatever styles that
should be applied at a certain point during the animation. Don't be fooled into thinking
the @keyframes
rule only applies to transparency. You can do movements or
practically anything else you can think of.
The first keyframe selector 0%
sets the initial state of the element
with opacity: 0
, which means it will be completely transparent.
The second keyframe selector 25%
sets the opacity
to
1
, which means the element will gradually become totally visible from
0% to 25% of the animation duration.
The third keyframe selector 50%
keeps the opacity
at 1
for the middle portion of the animation, from 25% to 50% of the animation duration.
The fourth keyframe selector 90%
sets the opacity
back to
0
towards the end of the animation, at 90% of the animation duration.
This means the element will gradually become transparent again, so that it will
disappear completely by the end of the animation, revealing at the point the
always-visible-when-not-hidden underlying first image.
The fifth keyframe selector 100%
also sets the opacity
to 0
, but it is redundant since it repeats the style from the fourth selector.
It is included for clarity and completeness.
Together, these keyframe selectors define the steps of an animation that will cause an element to gradually fade in and out over the course of the animation duration.
The order of what actually happens is this:
The page loads, and image 1 appears. One second later, image 2 begins to fade in on top of image 1. A second after that, image 3 begins to fade in on top of image 2.
But then, while image 3 remains visible, image 2 fades back to invisibility
beneath it. So, when image 3 fades a second later, it reveals the first image
that was beneath them all. So if you want to change the length of time between
images being displayed, do that by altering the animation-delay
value for the appearing images, and the animation-duration
property
accordingly.
In conclusion, creating a Carousel with CSS animations is an effective way to
display a series of images on a web page. With CSS Animations, you have greater control
over the timing and sequence of events, allowing you to create more dynamic and
visually appealing effects. By using the animation-iteration-count: infinite
property value, you can set your slide show to run on a loop indefinitely, without requiring user
interaction. Remember that when positioning images, it is important to set the parent element
to position: relative
, so that the child elements are positioned relative to it.
With these tips in mind, you can easily create a beautiful and engaging Carousel.