Chris Ward

@chris_82106

A glowing, crackling fire effect with CSS animations

Initial background image from Pexels

This story likely won’t be revolutionary to any real artists or CSS ninjas, but was a fun side project for winter. Enjoy.

To celebrate the upcoming holidays, we recently added a winter background theme to our Locus video conversation app. We first found a cozy winter image from Pexels. Nice start, but not enough ambiance yet. OK, add the sounds of a crackling fire. Simple enough to find a nice recording from freesound.org, such as this one “Fireplace 3 hours”. Or there is a video version of the same sound on YouTube, embedded below.

Fireplace sound with video!

Ahh… now we’re starting to feel a bit more cozy. And yet, looking at the still photo and listening to the crackling fire feels a bit too static. Let’s use some CSS3 animation magic and make the fire glow!

We want to make sure our animation runs smoothly and does not eat too many cpu cycles. Our video conferencing web app already has enough computational appetite. From the article Smooth as Butter: Achieving 60 FPS Animations with CSS3, we see:

Modern browsers can animate four styles pretty, pretty well, making use of the transform and opacity properties.
Position — transform: translateX(n) translateY(n) translateZ(n);
Scale — transform: scale(n);
Rotation — transform: rotate(ndeg);
Opacity — opacity: n;

OK, great. We can make use of opacity animation to create a glowing effect. Our background image already has a brightly lit fire scene. We can add a semitransparent overlay to selectively darken this scene, and animate the opacity to make the glowing effect.

Our simplified goal, darken the fire

Great. Except we don’t want to darken our whole image, we only want to darken the flames and the areas lit by the fire. Something more like this:

Tailored fire darkening overlay

To create an overlay for the actual scene, I used Photoshop. I am definitely not a master at Photoshop, so will keep this high level. Basically we want to create an image that is darkest where there is fire or glow from the fire, and light / fully transparent everywhere else. The end result we’re aiming for is:

Final overlay image for winter scene

First we remove any part of the image we don’t want to be affected and replace that with black. And smooth the edges a bit.

Just the image portion we want to affect

Now, we want our overlay image to preferentially darken areas that are lit by the fire. At this step, this means we want all the glowing parts to show up whiter, and the rest to show up blacker. I did this primarily using hue/saturation/lightness filters on specific colors. Lightening the reds and yellows, and darkening the remaining colors.

After tweaking colors

Now we invert the image:

Inverted

Almost there. But wait… look what happens when we overlay this image semi-transparently over the base image:

That’s not right!

Oops, the whole image gets washed out. This is because, the background of the overlay image is white. If we simply overlay this image and give it a CSS opacity, the dark areas will darken the base image, but the white areas will lighten the base image. What we need instead of a color variation is a transparency variation. We want to convert the image to greyscale and then map from greyscale intensity to opacity, creating a new image that is all black with varying opacity levels. As far as I could tell, Photoshop doesn’t have a simple method to do this. But the free and open source editor GIMP does. And this post, quoted below tells us how to do it.

1) Open your document (i.e. black and white photo)
2) Right click on the photo in layer menu select “add Alpha channel”
3) Go to the Color Menu at top and select “Color to Alpha” a window appears showing the color and hit okay.
That’s it. Your done. Takes like one minute.

Great. Now we finally have our final overlay image.

There we go! Dimmed fire.

Great, now for the CSS part, which turns out to be relatively simple. We just absolutely position the 2 images, with the overlay on top. Then animate the opacity of the overlay. The CSS looks something like:

img.base{
position: absolute;
/* position, height, width, etc as appropriate. */
z-index: 0;
}
img.overlay{
position: absolute;
/* position, height, width, etc as appropriate. */
z-index: 1;
opacity: 0.0;
animation-delay: 0.5s;
animation-duration: 15s;
animation-direction: normal;
animation-iteration-count: infinite;
animation-name: fireFlicker;
animation-timing-function: linear;
}
@keyframes fireFlicker {
0%, 10% { opacity: 0; }
15%,20% { opacity: 0.13; }
22%,23% { opacity: 0.026; }
25%,35% { opacity: 0.08; }
39%,42% { opacity: 0.22; }
44%,47% { opacity: 0.13; }
49%,50% { opacity: 0.026; }
52%,54% { opacity: 0.08; }
57%,58% { opacity: 0.24; }
60%,63% { opacity: 0.17; }
65%,72% { opacity: 0.08; }
77%,85% { opacity: 0.026; }
90%,95% { opacity: 0.17; }
100% { opacity: 0; }
}

Obviously there is a room for a lot of variation here. I chose to have an animation that starts and ends with 0 opacity, and infinitely loops forward. Alternately you could have an animation that alternates forward and backward. The animation-timing-function of linear was selected because it had lower computational cost vs. other options. However I did think ease-in-out looked a little nicer. The animation key frames hold constant values for some time (ie. each row has 2 percentage values, indicating the opacity level is held constant between those values). This is also done to reduce computational load vs. constantly changing animation. And 15 second animation time seemed long enough to not be really obvious the animation is looping.

That’s it! I’m sure more can be done to improve the effect. I considered adding another overlay layer to add a bit of flicker to the fire, but didn’t have the time or art skills! The effect is purposely relatively subtle, but can be exaggerated by tweaking the animation values.

See the effect live by going to Locus and clicking “Get Your Room”. Then click the “Enter Room” button and you’re all set. This scene should stay live at least during the winter of 2016/2017. Or to make it even easier, a CodePen is available below.

Thanks for reading! If you like what you read, be sure to 💗 below. And if you’re curious why we’reworking on yet another video conferencing app, check out my article “It’s 2016, why is video conferencing still terrible?

CodePen of the glowing fire effect.

More by Chris Ward

Topics of interest

More Related Stories