|
By: Paul S Cilwa |
Posted: 3/27/2023 |
|
Page Views: 599 |
| Hashtags: #Programming #CSS #HTML #WebDesign |
| There are a lot of hints on the Web how to create CSS-only slide shows. This one works. |
| Estimated reading time: 9 minute(s) (2085 words) |
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 unnecessary 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 animation-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 override 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 imagine wanting to appear in this manner.)
Our last step, then, 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 that 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.