Malachi Willey
Malachi Willey

Reputation: 328

CSS transform animation causes visual glitch in subsequent blurred elements (Chrome only)

So this is a bit strange. I have a blurred element (filter: blur(..), just a black box for example here) that is scaled up slightly (transform: scale(2)) in order to hide the blurred edges. Now when a preceding element animates the transform property, the blurred element shows a visual glitch (perhaps losing its scale(2), but I'm not sure) for the duration of the animation.

I see this behavior in Chrome (on Linux), but not Firefox.

I have tried adding backface-visibility: hidden and translateZ(0) to the blurred element, but these actually cause the same visual glitch just described. I am not sure why this is.

Any workarounds or insight into this issue is appreciated! Here is a minimal reproduction:

https://jsfiddle.net/malwilley/tz4fwmu2/

button {
  width: 400px;
  height: 60px;
  transition: transform 500ms;
}

button:hover {
  transform: translateY(-4px);
}

.container {
  margin-top: 20px;
  overflow: hidden;
  height: 200px;
  width: 400px;
}

.blurred {
  height: 100%;
  width: 100%;
  overflow: hidden;
  background: black;
  filter: blur(10px);
  transform: scale(1.2);
}
<button>Hover me</button>

<div class="container">
  <div class="blurred" />
</div>

Upvotes: 2

Views: 1794

Answers (2)

yunzen
yunzen

Reputation: 33439

Sometimes these glitches in Chrome appear, when you have software rendering without support by the 3D graphics processor.

As far as I understand, you can trigger 3d support by using any Z coordinate transform. Thus appending translateZ(0) to your scaling transform in .blurred makes the glitch go away.

Old solution

button {
  width: 400px;
  height: 60px;
  transition: transform 500ms;
}

button:hover {
  transform: translateY(-4px);
}

.container {
  margin-top: 20px;
  overflow: hidden;
  height: 200px;
  width: 400px;
}
++ 
.blurred {
  height: 100%;
  width: 100%;
  overflow: hidden;
  background: black;
  filter: blur(10px);
  transform: scale(1.2) translateZ(0);
}
<button>Hover me</button>

<div class="container">
  <div class="blurred" />
</div>

New solution

I changed my style a little bit
It's now

.container {
    /* ... */
    transform: scale(1);
}
.blurred {
    transform: scale(1.2);
}

I took another trigger for 3D rendering and used it on the .container instead of the .blurred element

button {
  width: 400px;
  height: 60px;
  transition: transform 500ms;
}

button:hover {
  transform: translateY(-4px);
}

.container {
  margin-top: 20px;
  overflow: hidden;
  height: 200px;
  width: 400px;
  transform: scale(1);
}

.blurred {
  height: 100%;
  width: 100%;
  overflow: hidden;
  background: black;
  filter: blur(10px);
  transform: scale(1.2);
}
<button>Hover me</button>

<div class="container">
  <div class="blurred" />
</div>

Upvotes: 2

doğukan
doğukan

Reputation: 27531

If you use transform: translateY(20px) instead of margin-top: 20px the bug will be fixed.

button {
  width: 400px;
  height: 60px;
  transition: transform 500ms;
}

button:hover {
  transform: translateY(-4px);
}

.container {
  transform: translateY(20px);
  overflow: hidden; /* remove overflow: hidden to see blur */
  height: 200px;
  width: 400px;
}

.blurred {
  height: 100%;
  width: 100%;
  overflow: hidden;
  background: black;
  filter: blur(10px);
  transform: scale(1.2);
}
<button>Hover me</button>

<div class="container">
  <div class="blurred" />
</div>

Upvotes: 2

Related Questions