The magic of CSS filter

There is no issue in telling the responsibility of the majority of CSS properties. The margin sets the margin. The color sets the color. But what does the filter do?

Well, it's a bit more complicated because unlike most of the properties, filter does all sorts of things. "Applying graphical effects on an image" is as far as you can narrow it down. But that's what makes it so exciting to describe.

In today's blog post, we will go ballistic on an image of your choosing, covering some fun use-cases for the usage of CSS filter. Before we start though, make sure you actually can use it on production. If you are not one of those poor souls that have to support IE11, you are good. But if you are, I remind you the group therapy was rescheduled to Monday. See you there!

1. Syntax

In order to use CSS filter property, we must supply it with a value in the format of a filter function. There is quite a lot to choose from:

  • blur(...)
  • brightness(...)
  • contrast(...)
  • drop-shadow(...)
  • grayscale(...)
  • hue-rotate(...)
  • invert(...)
  • opacity(...)
  • saturate(...)
  • sepia(...)
  • revert(...)
  • url(...)

Each function accepts a different parameter: you will see pixels, percentages, and degrees. What is worth noting is that you can combine functions in a single string.

2. Sandbox

I think the reason why some of the more abstract CSS properties don't necessarily stick with me is that they are rarely being presented in a relatable context. This is why I created a bunch of CodeSandboxes I will use to showcase the power of filter, using the example of basic Cards with images in them.

Each Card follows this structure:

<div class="card">
    alt="Random photo"
  <div class="card__content">
    <span class="card__caption">Subtitle</span>

3. Black & White and Sepia

One of the instant classics of filter use-cases is turning the photo either b&w or sepia. What we will do is:

  • make all of the photos in the Cards b&w / sepia
  • colorize & scale up the hovered one

We go with filter: grayscale() or filter: saturate() - either will turn the photo black&white, both also accept percentage as an argument. The only difference is the values: they are inverted. For grayscale, 100% means black&white, while for saturate it's 0%.

.filter-bnw > .card {
  filter: grayscale(100%);
  /* filter: saturate(0%); */

.filter-bnw > .card:hover {
  filter: grayscale(0%);
  /* filter: saturate(100%); */

Although black&white is definitely the most common color effect, it's not the only one. You may also want to achieve sepia which is no harder with CSS filter:

.filter-bnw > .card {
  filter: sepia(100%);

Throw in a slight increase of the card's size on hover and you are good to go:

.card:hover {
  transition-duration: 0.15s;
  transform: scale(1.1);

4. Blur

Perhaps you want to focus the user's attention on a particular area through a different mean. The perfect case for that is blur, which - as most of the other CSS filter functions - does exactly what it says: it blurres out the item. This time, we will go with a different, but quite usual use-case: a modal.

What you see quite a lot with modals is blurring out the background while opening the modal. CSS filter is not the only way to achieve that effect but it suits it quite nicely.

.blur {
  filter: blur(5px);

And when clicked, add that class to the classList of a background element:

const openModal = () => {
  modal.setAttribute("open", true);

You can easily imagine something more sophisticated, though. blur may come in handy in a variety of loading scenarios. If you are familiar with Next.js Image component, you may be tempted to implement a feature similar to their placeholder="blur" whose result looks like this.