Let It Snow

I wanted to make the Carpenter series of posts look ridiculously romantic, so I got the swashiest font I could find.  But it’s not enough: I wanted to make it snow, too.

Now, this blog is on WordPress.com, which adds limitations to what is easy or even possible to do.  I wanted a CSS-only snowing solution that didn’t involve adding any new HTML elements, and that turns out not to be the common thing to do?  There are approximately five hundred thousand blog articles out there about making web pages snow, but they are either snowing in the background, or is a mess of <div> <div> <div>s to make it snow in front of an image.

Looking at this pretty snowing effect, I wanted to do the same, but by just adding a class: snow to the <a> element already surrounding the <img>s in this blog.

Presto:

This, as anybody who’s done CSS knows, took way too long and went down many blind alleys before I got it to work properly.  (So it’s a good thing I did it while I was on holiday.)  Here’s the CSS I ended up with:

.snow {
  display: inline-block;
  position: relative;
}
.snow::after {
  content: '';
  position: absolute;
  display: block;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  background-image: url('https://lars.ingebrigtsen.no/wp-content/uploads/2017/11/pl2.png'), url('https://lars.ingebrigtsen.no/wp-content/uploads/2017/11/pm2.png'), url('https://lars.ingebrigtsen.no/wp-content/uploads/2017/11/pm2.png'), url('https://lars.ingebrigtsen.no/wp-content/uploads/2017/11/ps2.png'), url('https://lars.ingebrigtsen.no/wp-content/uploads/2017/11/ps2.png');
  animation: snow-fall 5s linear infinite;
}
@keyframes snow-fall {
  0% { background-position: 0 0, 0 0, 30px 40px, 0 0, 10px 0;}
  33% { background-position: 0 137px, 0 70px, 45px 100px, 0 30px, 20px 30px; }
  66% { background-position: 0 274px, 0 140px, 35px 200px, 0 60px, 20px 60px; }
  100% { background-position: 0 413px, 0 200px, 30px 240px, 0 100px, 10px 100px; }
}

So: What’s going on here is that I’m adding an :after element to the <a> element, and that element has en empty content, but several background images.  (Five of them, to be precise.)  These images are mostly transparent, but has snowflakes of various sizes and blurrinesses.  In the original version, all these “layers” are of the same size but animated in different speeds so that the closest layer is fastest.  That’s not possible with the :after thing, because there can only be one :after, and therefore only one animation speed.

So instead I chopped the different layer images into different sizes, and then I can animate one from 0px to 100px while I animate a closer, faster layer from 0px to 200px, and so on.  The important thing is that the animations have to be the same sizes as the images, because otherwise you’ll get a shuddering effect when the animations restart.

And then you can do any number of things, like adding some slight wobble and windiness to the scene.

The more layers you add, the more CPU intensive the result will be.  Depending on whether the user’s browser uses hardware acceleration for the CSS animation, of course.  But think of it this way: It makes the computer nice and toasty warm: Perfect for winter.

(One complication to getting this to work on this blog is that I had called the animation “snow”, so the CSS read “animation: snow 5s linear infinite”.  WordPress.com helpfully auto-translated this to “animation: #fffafa 5s linear infinite”.  Presumably because “snow” is a colour name.  And that doesn’t work.  Thank you, WordPress.com.)

So when I grow up, my job is definitely going to be for restaurants that specialise in weddings in December.  I’ve already got the CSS and the font!

Leave a Reply