Random fly-in animation using Sass

“It’s a cruel and random world, but the chaos is all so beautiful.”
― Hiromu Arakawa

One of the things that’s changed in the CSS world over the past several years is the rise of CSS preprocessors, and Sass is one of the most popular (LESS is another big one, if you’re interested here’s a comparison between the two from Smashing Magazine; here’s another comparison from CSS Tricks).  I hadn’t explored either much until recently, as useful as they are they have to fit into your workflow, and I just haven’t had the opportunity to use either in the context of my day job, but coding playground Codepen makes it super-easy to try out Sass (LESS too, if that’s more your thing).

Sass adds some really helpful features that aren’t available in current version of CSS, like variables (which appear to be on the horizon for CSS), math functions, inheritance, mixins, and control structures.  If you’re looking for a quick introduction to Sass this is a good one. But what I want to focus on today is the random() function.

The thing about random()

Here’s the thing though, random() isn’t part of core Sass, you have to install it yourself! Or if you just want to try it out quickly and easily, I can’t recommend Codepen enough. Seriously if you aren’t already a user you should go make yourself an account right now, make a cool little “pen” to try it out, then come back here and finish reading this. Also, if you do that, post your  first pen in the comments below :-)

Okay, let’s see the result first…

Here’s what we’re building, letters fly in, each from a random direction and distance. This only happens once, on page load. The quote is from George Eliot.

flyin

The html

As you can see from the image above, we need to be able to manipulate each character individually. Unfortunately, that means unless we want to use javascript, we have no choice but to wrap each letter in its own html element (at least for now, until we have something in CSS like an nth-letter selector). In this case I’ve chosen to use spans, so the markup ends up looking like this:

[html]

Our
words
have
wings,

but
fly
not
where
we
would.

[/html]

The <div> wrapper is just for convenience in positioning the whole quote, really the only necessary part of the markup is the <span> around each letter.

Some basic styles

This is all to provide the basic styling for the page and the quote, it should be mostly self-explanatory but I’ve added inline comments below:

[css]
html{
box-shadow: inset 0 0 30px 0 #000;
/* the above line provides a sort of subtle gradient around the periphery of the page */
min-height: 100%; /* necessary for the above */
}
body{
/* basic look & feel stuff */
background: #111;
color: limegreen; /* I like named colors */
font-size: 1.8em;
font-family: “Courier New”, Courier, monospace;
}
div{
/* these just position the quote in the page */
margin-top: 15%;
text-align: center;
}
span{
display: inline-block; /* necessary for the transform later */
opacity: 0; /* hides the letters so they are not visible when page first loads */
}
[/css]

Maybe the only really interesting detail above is that CSS transforms don’t appear to work reliably with inline elements, but of course if we make the spans into block-level elements that will make them each stand-alone blocks one atop the other. I suppose you could then write more CSS to properly size and position all those blocks back into forming words and sentences, but just using inline-block seems to be a good solution here.

Bring out the Sass

Again, comments inline explain:

[css]
/* there are 41 spans so we need to loop through 41 times */
@for $i from 1 through 41{
span:nth-child(#{$i}){
/* now we apply a separate animation to each of the spans individually, using nth-child */
animation: flyin#{$i} 4s 1 forwards;
}
/* define the keyframe animations here, remember each one will be different */
@keyframes flyin#{$i}{
0%{
/* and here’s where we use random(), to move each letter to a different starting position */
transform: translate(random(700) – 350 + px, random(700) – 350 + px);
}
25%{
opacity: .1;
}
100%{
/* and each letter ends up at its original position, and fully opaque */
transform: translate(0,0);
opacity: 1;
}
}
}
[/css]

First, everything is wrapped in a Sass @for loop so we can generate unique styles for each letter. We’re going to end up with 41 different @keyframe animations, one for each span, named flyin1, flyin2, flyin3, etc. Then we use nth-child to apply each unique animation to a different span. Each letter gets moved to its starting position using the translate() CSS transform, which is preferred for shifting elements around the page versus using position:absolute and top/left. Then of course we pass random X and Y coordinates into the translate function. random() accepts a single parameter defining the upper limit of the range (here 700), but by subtracting half of that limit (i.e. 350) from the result you end up with a value between -350 and 350. Make sense? So it basically says, shift this span anywhere from 350px up to 350px down and anywhere from 350px to the left to 350px to the right.

The result

And here’s the codepen, so you can see how it all comes together. It’s important to note that the individual letter coordinates (starting points) are set only when the CSS is generated from the Sass, so the animation won’t look different each time it’s run in the browser, but the letter coordinates are randomly generated each time the Sass is edited and new CSS is generated.

Check out this Pen!

So there you go, thank you for reading! Any questions, suggestions for improvement, other feedback, hit the comment form below!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.