Blog Post

Excerpt – Even Further Expand Your First Website (And Thwack those Zombies Into the Next Apocalypse with HTML and CSS)

Grab the starter files and follow along.

Transitions and Fades

In mug.html we have a CSS and HTML only image gallery. We could punch zombies in the gullet more effectively if the images faded into each other as we transitioned from one to the next. We can do this by adding a transition property, which will change the image’s opacity. Transitions, like those legless crawler zombies, are low-level animations that state changes can trigger (for zombies, losing their legs is the state change). Hover is often used, but we can also use our :checked pseudo-class. We’ll set the transition on :checked to one second (1s), to trigger a one second long animation, but before we’re ready to go we need to set up the fading mechanism.

CSS does not allow us to animate display: none to display: block (yet). So instead of using the display property as we did before we’ll use the opacity property. When opacity is set to 0 the element is completely see through. When it’s set to 1 it’s completely opaque. Anywhere between 0 and 1 has some amount of transparency. We’ll animate the opacity of the image we’re switching to from 0 to 1 and the image we’re replacing’s opacity from 1 to 0. We’ll change display: none to opacity: 0 (transparent) and display: block to opacity: 1 (opaque). We’ll also add the transition to each rule. So take this code from style.css:

.lrgimg {
    display: none;
}
#gallery1:checked~.product .largeimgs .lg1 {
    display: block;
}
#gallery2:checked~.product .largeimgs .lg2 {
    display: block;
}
#gallery3:checked~.product .largeimgs .lg3 {
    display: block;
}
#gallery4:checked~.product .largeimgs .lg4 {
    display: block;
}
#gallery5:checked~.product .largeimgs .lg5 {
    display: block;
}

and change it to:

.lrgimg {
    display: block;
    opacity: 0;
    transition: 1s;
}
#gallery1:checked~.product .largeimgs .lg1 {
    opacity: 1;
    transition: 1s;
}
#gallery2:checked~.product .largeimgs .lg2 {
    opacity: 1;
    transition: 1s;
}
#gallery3:checked~.product .largeimgs .lg3 {
    opacity: 1;
    transition: 1s;
}
#gallery4:checked~.product .largeimgs .lg4 {
    opacity: 1;
    transition: 1s;
}
#gallery5:checked~.product .largeimgs .lg5 {
    opacity: 1;
    transition: 1s;
}

This works great—except for one rather big thing. Opacity doesn’t pull the images out of normal flow, so they’re aligned in a vertical column down the page rather than appearing directly on top of each other like a stack of zombified baseball cards. Because we set the opacity of each lrgimg <div> to 0, the place where the images are just looks like a lot of empty space.

Screenshot showing space between visible image and thumbnails

This pushes the thumbs <div> way down the page, likely below the bottom of the browser window. If so, scroll down to see the thumbs <div>. We can fix this by using positioning. Add position: relative to the largeimgs <div>, and then add position absolute to each image.

However, if we make all the images position: absolute, they all come out of the natural flow, and the thumbs <div> will flow up underneath the gallery images, preventing us from changing the image.

To fix this, we set the first image to position: relative, keeping it within flow, and set the top property for all images to 0 so that they will sit on top of the first image like zombified baseball cards stacked on each other.

.largeimgs {
    position: relative;
}
.lrgimg {
    /* Other styles */
    position: absolute;
    top: 0;
}
.lg1 {
    position: relative;
}
screenshot showing thumbnails directly below  image

While the fading effect is pretty neat, we can ratchet up its zombie fighting effectiveness by using easing functions. By default, animations use a linear function, which means that they go at the same speed throughout the entire animation. While that can work for some things, it doesn’t look or feel natural because when something moves, it takes time to get up to speed. Similarly, unless it’s stopped by a wall or other obstacle, an object takes time to slow down and stop.

We can mirror getting up to speed with an ease-out function that speeds up the object from a low speed to a top speed near the middle of the animation. On the other end, we can slow the object down with an ease-in function that slows to 0 at the end. We can do both with an ease-in-out easing function. Change each transition property from:

transition: 1s;

to:

transition: 1s ease-in-out;

But that isn’t the only way to animate in CSS.


Find out more in Even Further Expand Your First Website (And Thwack those Zombies Into the Next Apocalypse with HTML and CSS)