Larixk
Larixk

Reputation: 116

How to stop Chrome cutting off CSS blur filter when transitioning transform

I'm building a visual effect in CSS which applies a filter: blur to an element and animates children of this element. Some of these children are partially out of view, which causes rendering inconsistencies in Chrome while animating:

While a transition is active, the CSS filter is rendered differently than when the element is stationary. It seems to crop and then blur only the part of the element that is within the viewport while it is moving. This leads to an unwanted gradient where the element touches the edge of the window (example below).

I presume a new stacking context is created when animating a transform, similar to when applying a transform3d or will-change: transform. Applying such properties leads to the same effect, even when the element is static.

When nesting the element in another element and setting the transform on the parent and the blur on the child the problem goes away. But this is not a solution for me, because I will be animating multiple elements and then blurring the container to achieve the visual result I'm after.

I've created a codepen with a minimal test case: https://codepen.io/larixk/pen/jONRoXO Here there is a single element with a filter: blur which transitions on :hover.

.blurred {
  width: 50vmin;
  height: 50vmin;
  margin: 0 auto;
  border-radius: 50%;
  background: black;

  filter: blur(5vh);

  transform: translateY(-80%);
  transition: transform 1s;
}

.blurred:hover {
  transform: translateY(-20%);
}

Expected result while transitioning: Imgur

Actual result while transitioning: Actual

Seen in Chrome Version 77.0.3865.90 and Chrome Canary Version 79.0.3930.0.

Problem does not occur in Firefox (70.0b11) or Safari (13.0.1).

Is there something broken in Chrome, or am I missing something?

Upvotes: 4

Views: 1175

Answers (1)

a2343
a2343

Reputation: 21

.blurred {
    width: 50vmin;
    height: 50vmin;
    margin: 0 auto;
    border-radius: 50%;
    background: black;
    filter: blur(5vh);
    transition: 1s;
    position: relative;
    top: -140px;
}

.blurred:hover {
    top: 0px;
}

You could also use vw rather than px if you wanted it responsive.

Upvotes: 1

Related Questions