Creative Use of CSS Filters

Adir SL
4 min readFeb 18, 2019

--

The filter property in CSS is a lot more powerful than people think, not only does it allow us to change the color or the tone of an image but it also allows us to change those properties on regular HTML/CSS shapes.

In this article you will see how I built this Lava Lamp in CSS using various filters, you can also click on it (in the Codepen) to cycle through different colors:

CSS Lava Lamp

Codepen: https://codepen.io/Adir-SL/pen/LqBpVR

Here’s a quick example of this filter behavior on a shape, you can see that the filter: blur(); is applied on the circle as you would expect it to work on an image, just blurring everything in this circle class.

.circle{
position: absolute;
width: 20vw;
height: 20vw;
top: 50%;
left: 50%;
margin-left: -10vw;
margin-top: -10vw;
background-color: darkred;
border-radius: 100%;
filter: blur(1vw);
}

Codepen: https://codepen.io/Adir-SL/pen/yZGxBq

We can combine the effect with overflow: hidden; in order to make the effect contained, that way we can better control what gets blurred and what is not, you can see how I added a <div> to make the effect contained.

.circle{
position: absolute;
width: 20vw;
height: 20vw;
top: 50%;
left: 50%;
margin-left: -10vw;
margin-top: -10vw;
background-color: darkred;
border-radius: 100%;
overflow: hidden;
}
.circle div{
position: absolute;
width: 50%;
height: 50%;
top: 50%;
left: 50%;
background-color: white;
filter: blur(2vw);
}

Codepen: https://codepen.io/Adir-SL/pen/exbLJx

Another interesting feature of CSS is that we can stack multiple filter on top of each other, kind of like we can in Photoshop or After Effects (confession time: I used to work as a full time Motion Designer working every day on After Effects).

I know you’re probably thinking “but how can I achieve the blobs connecting like in the lava lamp ?”, so here we go with that.

This is the way I used to do it in After Effects:

Lava Lamp effect in After Effects

You can see it’s just a matter of blurring everything and then bringing the Alpha Channel back to reality with Levels, here’s another example of the same approach but done in Photoshop with Threshold:

Lava Lamp effect in Photoshop

Now that we know what we’re looking for, we can turn to our code again and make some adjustments, first we need to add another <div> so we can see how they connect, and instead of levels we can achieve our goal with contrast() and brightness().

.circle{
position: absolute;
width: 20vw;
height: 20vw;
top: 50%;
left: 50%;
margin-left: -10vw;
margin-top: -10vw;
background-color: darkred;
border-radius: 100%;
overflow: hidden;
filter: blur(.2vw) contrast(500%) brightness(1500%) hue-rotate(30deg);
}
.circle div{
position: absolute;
width: 30%;
height: 30%;
top: 50%;
left: 50%;
background-color: white;
filter: blur(2vw) contrast(50000%) brightness(100%);
}
.circle div:nth-of-type(2){
top: 22%;
left: 22%;
}

Codepen: https://codepen.io/Adir-SL/pen/OdroZv

In order to make the effect work as two tone without seeing the effect of the blur()which may cause our colors to blend together in a weird gradient, we need to crank the contrast and brightness way up on both the parent <div> and the actual blobs, notice that I add another filter of hue-rotate() on the parent <div> just so we can maintain the dark red color of the parent, maintaining exact color combination here is difficult due to all the filters being applied.

The exact values of the contrast() and brightness() are dependent on your shapes structure and size, you might want to vary those values if everything disappear on your project or may be just work with larger shapes as smaller shapes might not even render after all those filters.

Now that we got what we wanted we can add some animation to make it work as we did in After Effects, and that’s it, we can make another wrapper <div> to make sure that the edges of the blur() disappear if we want and make it more pretty but that’s basically it.

.circle{
position: absolute;
width: 20vw;
height: 20vw;
top: 50%;
left: 50%;
margin-left: -10vw;
margin-top: -10vw;
background-color: darkred;
border-radius: 100%;
overflow: hidden;
filter: blur(.2vw) contrast(500%) brightness(1500%) hue-rotate(30deg);
}
.circle div{
position: absolute;
width: 30%;
height: 30%;
top: 50%;
left: 50%;
background-color: lightpink;
filter: blur(2vw) contrast(50000%) brightness(100%);
}
.circle div:nth-of-type(2){
top: 22%;
left: 22%;
margin-left: 20vw;
animation-name: blobAnim;
animation-duration: 5000ms;
animation-timing-function: ease-in-out;
animation-play-state: running;
animation-iteration-count: infinite;
}
@keyframes blobAnim{
0%{margin-left: -20vw};
100%{margin-left: 20vw};
}

Codepen: https://codepen.io/Adir-SL/pen/OdroBZ

The result of our Code

I hope you enjoyed reading it and learned something new, for more interesting uses of CSS Animations and Interactions and the occasional JavaScript you can follow me here:
Codepen: https://codepen.io/Adir-SL
Instagram: https://www.instagram.com/adir.sl

--

--