In a previous tutorial we created a full-screen responsive page with flexbox. Today, we’ll make this page more attractive by adding a few CSS animations to it.
Here's what we're going to build:
1. The HTML
In order to add the desired animations, we’ll slightly update the initial page markup. In the previous tutorial, the markup of our main
element looked like this:
<main class="page-main"><div><h1>...</h1><p>...</p><p>...</p></div></main>
For the purposes of this tutorial, we’ll add some extra wrappers, changing it to this:
<main class="page-main"><div><div class="text-wrapper"><h1>...</h1></div><div class="text-wrapper p-wrapper"><p>...</p></div><div class="text-wrapper p-wrapper"><p>...</p></div></div></main>
Below is the overall page markup after this modification:
<div class="wrapper"><header class="page-header"><nav><h2>...</h2><ul>...</ul><button class="cta-contact">...</button></nav></header><main class="page-main"><div><div class="text-wrapper"><h1>...</h1></div><div class="text-wrapper p-wrapper"><p>...</p></div><div class="text-wrapper p-wrapper"><p>...</p></div></div> </main><footer class="page-footer"><small>...</small><ul>...</ul></footer></div>
2. Adding Initial CSS Styles
With the HTML in place, let’s focus our attention on the important stuff: the CSS.
To begin with we’ll do four things:
- Hide all the page elements.
- Set styles for the
header
andfooter
elements and their sub-elements. - Define styles for the
::after
pseudo-element of theheader
. - Specify styles for the text wrappers and their sub-elements inside the
main
.
Here are the associated styles:
/* variables */ :root { --main-purple-color: #9e89b8; } .page-header nav > *, .page-main, .page-footer > * { opacity: 0; } .page-header, .page-footer, .page-main .text-wrapper { overflow: hidden; } .page-header nav > * { transform: translateY(-30px); } .page-footer > * { transform: translateY(30px); } .page-header { position: relative; } .page-header::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 2px; background: var(--main-purple-color); z-index: 99999; transform: scaleX(0); } .page-main .text-wrapper + .text-wrapper { margin-top: 10px; } .page-main .text-wrapper * { transform: translateY(120%); } .page-main .p-wrapper * { transform: translateY(-120%); }
3. Firing CSS Animations
With the HTML and basic CSS ready, we can now concentrate on the page animations.
However, before doing that, let’s make sure we understand when they should run: ideally, as soon as the page is fully loaded. This ensures that all page assets will be ready, sitting in the correct position, and we won’t lose any of the animation effects.
With that in mind, we first wait for the page to load, and when that happens we use JavaScript to add a loaded
class to the body
.
Here’s the related JavaScript code:
window.addEventListener("load", () => { document.querySelector("body").classList.add("loaded"); });
Any animations we apply will be done to descendants of the loaded
class.
So, our first scale-in animation targets the ::after
pseudo-element of the header
:
.loaded .page-header::after { animation: scaleIn 1.3s ease-in 0.2s forwards; } @keyframes scaleIn { 100% { transform: scaleX(1); } }
Tip: By default the transform origin of an element is its center, which is why the animation of the pseudo-element starts from its center. If you want the animation to start from another position, just change the transform-origin
property value of the target element.
Below you can see how our animation changes where we apply a different transform-origin
:
Next, we use a fade-in effect to display the page elements. In addition to this animation, we also use a slide-in animation to show the header
and footer
contents:
.loaded .page-main { animation: fadeIn 1s ease-in 0.7s forwards; } .loaded .page-header nav > *, .loaded .page-footer > * { animation: fadeIn 1s ease-in 0.7s forwards, slideIn 0.8s ease-in 0.9s forwards; } @keyframes fadeIn { 60% { opacity: 0; } 100% { opacity: 1; } } @keyframes slideIn { 100% { transform: translateY(0); } }
Finally, the elements of the main
become visible through a slide-in effect:
.loaded .page-main .text-wrapper * { animation: slideIn 0.6s cubic-bezier(0.54, 0.46, 0.54, 0.94) 2s forwards; } @keyframes slideIn { 100% { transform: translateY(0); } }
Now let’s look again at what we’ve just built:
Conclusion
In this quick tutorial, we managed to animate an HTML flexbox page by taking advantage of CSS animations.
A few notes before closing:
- Instead of CSS animations, we could equally have used CSS transitions (almost all our animations go from a beginning state to an end state). The fade-in animation is the most complicated one because it includes three animation steps (0%, 60%, 100%).
- Instead of 2d transforms, we could equally have used 3d transforms.
- Play with the
animation-duration
andanimation-delay
property values to modify the animations according to your needs. - On mobile screens you might want to limit the number of animations that occur (e.g. remove footer animations). The demo animations work well especially on screens where all page contents are visible.