How I made my page load effect

I wanted a pretty pure-css load animation for my site, but I also didn’t want it to feel slow. I decided to start with a fade-in:

body * {
	opacity: 0; /* Start at 0 opacity */
	animation: fadein 0.8s ease-out forwards /* Don't go back to 0 opacity once the animation is done*/;
}
@keyframes fadein {
	100% {
		opacity: 1;
	}
}

However, it just felt.. boring. I decided that I wanted to add an animation with all of the elements sliding up onto the page. But after implementing the animation, it felt stiff with the whole page sliding at once. So, I used a fish script to generate some css:

/* for i in (seq 1 15); echo "body *:nth-child($i) { animation-delay: $(math $i x 0.025)s; }"; end */
body *:nth-child(1) { animation-delay: 0.025s; }
body *:nth-child(2) { animation-delay: 0.05s; }
body *:nth-child(3) { animation-delay: 0.075s; }
/* ... */

The generated CSS will cause the elements to slide into place one after another, in order from top to bottom. The new animation was great, but it still felt slow. I decided to use a cubic bezier curve to give me more control over the animation speed:

animation: fadein 0.8s cubic-bezier(0.33, 0.8, 0.69/*Nice*/, 1) forwards;

This curve will start quickly and ease out slow, which lets content become visible as early as possible while not making the animation feel ‘rushed’.

Final code:

main.css:

@import "stagger.css";

body *:not(li) { /* Page load animation */
	opacity: 0;
	transform: translateY(20px);
	animation: fadein 0.8s cubic-bezier(0.33, 0.8, 0.69/*Nice*/, 1) forwards;
}
@keyframes fadein {
	100% {
		opacity: 1;
		transform: translateY(0);
	}
}

stagger.css:

/* for i in (seq 1 15); echo "body *:nth-child($i) { animation-delay: $(math $i x 0.025)s; }"; end */
body *:nth-child(1) { animation-delay: 0.025s; }
body *:nth-child(2) { animation-delay: 0.05s; }
body *:nth-child(3) { animation-delay: 0.075s; }
/* ... */