Get started with WFL

Just pick something below to explore my work, services and more.

Latest Articles
Latest Art
Latest Photo
Latest Music

CSS Animation Tutorial: How I created the live with coal homepage CSS entrance animation

June 12, 2019Will Leffert

It has been a while since I've shown my work, so to speak, so I thought I'd document the CSS entrance animation for my June 2019 homepage. You can read additional details about the redesign here, or just jump to the codepen example of the CSS entrance animation. Without further ado, here's the breakdown.

HTML Markup

The HTML is really simple, honestly. I use a container div for the overall art, an h3 for each text object (plus spans for the bolding), divs for the rules, and just an image tag for the SVG art. Here it is below:

<div id="wfl_artcontainer">
<h3>Live with <span>coal</span></h3>
<div class="wfl_homerule"></div>
<img src="imgsrc/WFL-DiamondArt.svg" alt="," />
<div class="wfl_homerule"></div>
<h3>plan for a <span>diamond</span></h3>

See? Simple.

CSS Animation

I'm not going to go into great detail on the overall CSS for layout and styles; If you want that, you can take a look at the codepen. Instead, I'm going to focus on a couple of the more important bits for this.

First off, the h3s and the image all start off with opacity:0 in the default stylings for the objects. This is absolutely critical. Next, the rule starts off with width:0 (or height:0 on mobile sizes) in its own default styles.

Next, I created 2 classes; one called "show", and one called "expanded_rule". You can see what these do below:

.show {
opacity:100 !important;
-webkit-transition: all 1.5s;
transition: all 1.5s;

.expanded_rule {
-webkit-transition: all 2s;
transition: all 2s;

These just set the end-state for the objects they get applied to.

Finally, I have the floating animation for the image, which is applied to the CSS via

animation:diamondhover 7s infinite;

and utilizing the following CSS animation declaration:

@keyframes diamondhover {
0%, 100% {
transform: translate3d(0, -10px, 0);
50% {
transform: translate3d(0, 10px, 0);

You'll notice that I use translate3d, rather than playing with margins or anything else. I do this because translate3d renders a smoother animation, allowing for anti-aliasing rather than pixel-by-pixel movement.

Javascript Triggering

Finally, we trigger the states utilizing Javascript (jQuery, to be exact). jQuery allows us to write MUCH simpler markup for readability purposes, and honestly, the performance impact is negligible (especially since we're not utilizing jQuery to handle more than just the triggers). It is literally this simple:

$(document).ready(function() {
$("#wfl_artcontainer img").addClass("show");
window.setTimeout(function() {
}, 1000);
window.setTimeout(function() {
$("#wfl_artcontainer h3").addClass("show");
}, 2000);

Breaking this down, we just look for when the document is ready to go (the necessary objects are loaded in the browser), and just call functions inside functions for everything. First, we add the show class to the image to pull it in first. Next, we use window.setTimeout to delay the triggering of the rule animation (addClass("expanded_rule") - isn't jQuery so easy to read?), and then another setTimeout to show the h3s. I purposefully ensured that the h3s will show before the expanded rule animation finishes to give a "fade & slide in" look.

That is it. Utilizing CSS animations, makes this, quite possibly, the simplest animation I've ever done.

You can see the full markup and play with it over at the codepen here. Enjoy!