CodyHouse Framework + Components are featured on Product Hunt! Join the discussion →

How to create clipped, blurred background images in CSS

In this tutorial, we'll take a look at how to apply blur effects to images using CSS filters, and how to confine these effects to specific image areas.

A few days ago, we published the team component. It comes with a --blurred-img variation, where the area behind the team name is blurred. I thought it would be interesting to share the process of creating such an effect.

Let's do this! #

I've put together a video tutorial that explains in details how to create the blur effect.

The component we build in this tutorial is based on the CodyHouse framework.

👋 First time you hear about the CodyHouse Framework?

The idea behind the effect is the following: we need to duplicate the image of the team member, then we have to apply the CSS blur filter to this copy and a mask so that only part of the image is visible.

We create a copy of the image in CSS using the ::before pseudo-element of the .team__caption element:

.team--blurred-img {
  .team__caption {
    overflow: hidden;

    &::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-image: url('../../assets/img/img-01.jpg');
      background-repeat: no-repeat;
      background-position: center bottom;
      background-size: 100% auto;
      filter: blur(8px);
      transform: scale(1.1);
    }
  }

  .team__name {
    background: alpha(var(--color-black), 0.6);
    padding: var(--space-sm);
    z-index: 1;
  }
}

By setting background-position: center bottom; and background-size: 100% auto;, we make sure the copy of the image overlaps perfectly the original team member image.

By targeting each team member card using their IDs, we can set a different image for each member.

.team--blurred-img {
  // ...

  #james {
    .team__caption::before {
      background-image: url('../../assets/img/img-01.jpg');
    }
  }
  #emily {
    .team__caption::before {
      background-image: url('../../assets/img/img-02.jpg');
    }
  }
  #mathew {
    .team__caption::before {
      background-image: url('../../assets/img/img-03.jpg');
    }
  }
  #olivia {
    .team__caption::before {
      background-image: url('../../assets/img/img-04.jpg');
    }
  }
}

Because we're targeting the .team__caption, the duplicated image is confined to that area, and we don't need additional tricks to clip the image. Also, we've applied overflow: hidden to this element, to cut out the children elements in case they exceed the size of their parent.

When you apply the blur filter, you'll notice the edges are semitransparent. We can fix this issue by creating an additional copy of the image using the ::after pseudo-element, and by increasing the size of the ::before element with the scale transformation:

.team--blurred-img {
  .team__caption {
    overflow: hidden;

    &::before, &::after {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-repeat: no-repeat;
      background-position: center bottom;
      background-size: 100% auto;
      filter: blur(8px);
    }

    &::before {
      transform: scale(1.1);
    }
  }

  #james {
    .team__caption::before,
    .team__caption::after {
      background-image: url('../../assets/img/img-01.jpg');
    }
  }
  #emily {
    .team__caption::before,
    .team__caption::after {
      background-image: url('../../assets/img/img-02.jpg');
    }
  }
  #mathew {
    .team__caption::before,
    .team__caption::after {
      background-image: url('../../assets/img/img-03.jpg');
    }
  }
  #olivia {
    .team__caption::before,
    .team__caption::after {
      background-image: url('../../assets/img/img-04.jpg');
    }
  }

  .team__name {
    background: alpha(var(--color-black), 0.6);
    padding: var(--space-sm);
    z-index: 1;
  }
}

Optionally, you can target browsers that support the backdrop-filter property, and use this alternative technique to create the same effect with just one line of code. Unfortunately, support is not great at the moment, so we decided to include both methods.

@supports (backdrop-filter: blur(10px)) {
  .team--blurred-img .team__caption {
    backdrop-filter: blur(10px);

    &::before, &::after {
      display: none;
    }
  }
}

Done! Now go out there and blur things!

Feedbacks/suggestions? Get in touch on Twitter.

Project duplicated.