We love gifs on the HipChat team. We love them so much that we were temporarily
misled by their sirens’ call. Here’s how we plugged our ears and continued on to
the fabled land of SVG, optimizing our loading screen and reducing its size by
95%.
Fatty the gif and the loading screen
Our original loading screen was a thing of beauty. A pure white screen sporting
an animated, retina HipChat logo rolling over its tail into the future and
beyond.
This retina gif’s size (a chunky 53KB) was the source of its demise. It was
simply too big for a loading screen, often arriving late and missing the party
entirely.
Size aside, the old loading screen was a part of the greater web app. This meant
it would not appear until React and all of
the other dependencies of the web client were loaded. That sounds
counter-intuitive, but when we first launched the beta, the javascript payload
was smaller. The loading screen was simply used to hide the UI whilst we
fetched the initial HipChat session data. Since then we’ve added countless
features, like inline file previews, increasing the download size.
We’ve gone one better. The loading screen now loads before
React. Infact, the SVG HipChat logo and
animation CSS are inline in the HTML, so there’s no additional requests to make
to show the loading screen.
Captivating new users
New users are precious and first impressions last. If you have to keep them
waiting, captivate them. Quickly.
After our initial web client beta release, we conducted an intense study of the
new user on-boarding flow. It was then that we discovered our gif issue. In
production, new users with an empty cache on a typical internet connection,
often didn’t see our fancy loading gif at all.
Farewell gif. Hello SVG.
Our new web client already uses SVG symbol definitions
for our status icons, so it was a no-brainer to add a HipChat logo along-side
them.
With this HTML and CSS:
<svg height="0" style="display:block;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="icon-hipchat-logo" viewBox="0 0 1024 1024">
<title>hipchat-logo</title>
<path class="path1" d="M791.552 ..."></path>
<path class="path2" d="M932.864 ..."></path>
</symbol>
</svg>
#icon-hipchat-logo .path1, #icon-hipchat-logo .path2 {
fill: #205081;
}
It looks a little like this:
Let’s dance!
Advanced CSS animations are tricky. The animation loop needed to account for the
logo’s tail striking the ground. Piecing something intricate like this together
with the provided transition types (ease-in, ease-out, etc) is a great recipe
for a self-induced lobotomy. Instead, thanks to
Joel Unger on the design team, I was
able to create rotation and translation keyframe
rules from the original After Effects timeline.
The loop is 49 frames at 29.97fps giving us a total length of 0.6 seconds. From
here we can create percentage-based keyframes.
i.e. At frame 22 (46% through the loop), when the tail hits the ground, we want
to apply a rotation of 20 degrees and translation of 7 pixels up.
* Please note this snippet does not include browser-prefixes currently
required to work in all browsers.**
.loading-message .loading-outer {
animation: translationFrames linear 0.66s infinite;
transform-origin: 50% 50%;
}
.loading-message .loading-inner {
animation: rotationFrames linear 0.66s infinite;
transform-origin: 50% 50%;
}
@keyframes translationFrames {
42% {
transform: translate(0, -7px);
}
}
@keyframes rotationFrames {
42% {
transform: rotate(20deg);
}
}
The result
From a 53KB gif to 1.8KB of HTML and CSS (both sizes gzipped).
You can find all of the code for this CSS animation by viewing the source of
this blog post (or by signing up for a HipChat account).