Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image moves on hover when changing filter in chrome

I have an image, when i blur it on hover, it slightly moves, it's like the image shakes in its position, problem only occurs in chrome ( tested with: chromium 63 linux-x86_64 ),

.item img{
  transition: 250ms all ease-in-out;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.item:hover img{
  filter: blur(2px)
}

I thaught it might be related to this issue, but none of the solutions worked.

image moves on hover

UPDATE :

As @Chase said, this is a chrome bug and the most stable solution is to wait for it to be fixed. but for now, the best solution for this issue is @kosh Very's answer

like image 234
Amin Avatar asked Dec 20 '17 21:12

Amin


2 Answers

This is a confirmed Chrome bug that popped up in a recent update, and should hopefully get resolved soon.

Here's a reduced test case: https://codepen.io/chasebank/pen/KZgYXK

Here's the Chromium issue marked for triage.

I think the best thing to do for now is nothing. Wait for a proper fix to be implemented. It's never a good idea to hack around an acknowledge browser bug.

We can take some comfort in the fact that the only other people seeing this are Chrome users who recently updated. My first try was asking a Slack channel full of skilled devs, and even they weren't seeing it.

$('#toggleBlur').click(function() {
  $('#content').toggleClass('blur')
})
body {
  padding: 5%;
}

div {
  filter: blur(0px);
}

.blur {
  filter: blur(.1px)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="toggleBlur">Toggle blur</button>

<div id="content">
  <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Accusantium eum nisi voluptate eaque! Sequi sit nemo iste. Earum accusantium rerum consectetur cumque sequi maiores maxime reiciendis, alias beatae accusamus labore.</p>
  <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Voluptate enim magnam nemo atque, ad placeat ab unde consequatur minima velit, ipsam tempora laudantium molestias sapiente perspiciatis quaerat modi ratione voluptatem?</p>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Deleniti commodi cum sed nemo fugiat non esse ex quos consectetur ipsam alias laboriosam, cumque eaque omnis quae accusamus, repellat dolore modi!</p>
</div>
like image 59
Chase Avatar answered Sep 17 '22 12:09

Chase


I have two solutions for you:

filter:blur(0.2px) hack (don't ask me how it works)

.item img
{
  transition: filter 250ms ease-in-out;
  filter: blur(0.2px); /* the lowest value I could get on my machine: 0.12805650383234025436px */
  image-rendering: -webkit-optimize-contrast; /* just in case quality degrades */
}

.item:hover img
{
  filter: blur(2px);
}

Jokes aside, this is probably caused by floating number optimizations done by the Processing Unit, so by setting blur to .2px I am not animating blur(0px), but instead start from another value and instead of calculating it like this (assume we have linear easing):

frame1: 0, frame2: .1, frame3: .2, frame4: .3, ...

it calculates it like that:

frame1: .2, frame2: .2666, frame3: .3332, ...

So the incremental value has changed and no longer causes that misposition. Of course there's no proper math here (this is especially tricky with easings), but you get the idea.

This also skips the first frame with jiggle as well.



Duplicate blurred image and toggle between them (also the most performant way)

<div class="item">
    <img class="blurred"  src="https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg" alt="">
    <img class="original" src="https://www.wikihow.com/images/thumb/2/25/Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg/aid8673811-v4-728px-Collect-Bodily-Fluid-Samples-from-a-Cat-Step-16.jpg" alt="">
</div>

.item
{
  position: relative;
}

.item img
{
  max-width: 300px;
  transition: opacity 250ms ease-in-out;
  will-change: opacity;
}

.item .original
{
  transition-delay: 0;
}

.item .blurred
{
  position: absolute;
  filter: blur(5px);
  opacity: 0;
  transition-delay: .1s;
}

.item:hover .original
{
  opacity: 0;
  transition-delay: .2s;
}
.item:hover .blurred
{
  opacity: 1;
  transition-delay: .1s;
}
like image 27
CyberAP Avatar answered Sep 18 '22 12:09

CyberAP