7

I am trying to do a simple image fade on rollover - works fine and smooth in Chrome, but Firefox is a bit jumpy. I've tried doing the backface-visibility trick on the container, but still no luck.

Anyone have any ideas?

JSFiddle

HTML

<div class="link-box large">
    <div class="image">

        <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRStwH3maKRqLU8lLOo1XbO6uZIKHRyf2PGv66H6ol5mB0kS_0r" alt="">
    </div>
</div>

CSS

.link-box .image img { transition: all .2s ease-out; width:200px; }
.link-box.large { position: relative;}
.link-box.large:hover .image img { opacity: .65; }
apaul
  • 16,092
  • 8
  • 47
  • 82
wickywills
  • 4,024
  • 2
  • 38
  • 54

2 Answers2

6

My best guess is that setting the width of the image to 200px and leaving the height unspecified is causing the browser to calculate the height of the image. If the height calculates to a nice whole number it isn't an issue. If the height calculates to a decimal it may be the cause of the problem.

In this case the natural dimensions of the image are 275px by 183px.

By changing the width of the image to 200px you are shrinking the image to 72.727272...% of its natural size.

275/200 = 0.727272... Or if you prefer fractions: 275(8/11) = 200

Now running the same equation on the height yields:

183(8/11) = 133.090909...

It looks like, under the normal run of things, the partial pixels are cropped, but during the transition the partial pixels aren't being cropped, and the image is warped slightly to show the partial pixels within the same height.

Cropped down to 133px:
enter image description here
Not cropped and slightly warped:
enter image description here


Now that we have a good hypothesis on what's causing the problem, on to the solutions:

You can hard code the height of the image:

Working Example

.link-box .image img {
    transition: all .2s ease-out;
    width:200px;
    height: 133px; /* manually set the height */
}

Or if you would rather not hard code the height, you can also fix the issue with an anti-alias hack, just add a box-shadow.

Working Example

.link-box.large:hover .image img {
    opacity: .65;
    box-shadow: 0 0 0 #000; /* add a non-visible box-shadow */
}

Or if you're concerned about the cross-browser compatibility of using a box-shadow, you can also use a transparent border:

Working Example

.link-box .image img {
    transition: all .2s ease-out;
    width:200px;
    border: 1px solid transparent; /* add transparent border */
}
Community
  • 1
  • 1
apaul
  • 16,092
  • 8
  • 47
  • 82
  • sometimes setting explicit `height` is not a way we want, so I think this find of fix is not ***generally*** good. Anyway we have to admit that it's hard to fix a bug in a sucking browser like FireFox, just let it be so, remember that only a small amount of users (who use FireFox) have to suffer from the issue (which is also not really serious). I think the fix by setting `201` px for `width` instead is better. – King King Jun 19 '14 at 15:27
  • @KingKing I realize hard coding the height isn't ideal, but once you know the cause of an issue its a lot easier to find a solution you can live with. – apaul Jun 19 '14 at 15:31
  • looks like your guess seems to be close, but it's better to find some reference talking about this. I don't think changing the opacity has something to do with calculating the `height` and the `width`, it's some kind of internal bug inside FireFox. – King King Jun 19 '14 at 15:33
  • +1 for now - though unfortunantely my site is responsive and I can't explicitly set heights/widths on elements. I may resort to doing the fade with jQuery if it begins to bother me! – wickywills Jun 19 '14 at 15:37
  • @wickywills looks like you're a fan of FireFox, just because of having to support FireFox, you have to get rid of using the simple CSS to use a script solution instead. I would never do so, it's not worth doing so unless the issue is serious and at least 2 browsers (or more) have the issue. – King King Jun 19 '14 at 15:43
  • @KingKing Well I actually get the same issue in Chrome as well on the site I'm working on :(. Basically, I have 3 columns set to 33.3333% width, and the first image is jerky on firefox with the second one smooth. But on Chrome it's the first image that's smooth but the second one is jerky! – wickywills Jun 19 '14 at 15:46
  • @KingKing I think I figured it out, when the opacity is changed the stacking context is changed as well, causing the height to recalculate. – apaul Jun 19 '14 at 16:43
  • @apaul34208 I can understand about the stacking context change but not sure why the height (and maybe width) should be recalculated, anyway it's a bug in FireFox. The interesting thing is when you hover the image, it's just being jerked a little and ***turns back*** right to the correct height (while the opacity at that time is `.65`). I don't think it's simple to explain this. However the fix you found about the `box-shadow` is really interesting. Not sure why it could fix it. It can even be shorter by just `box-shadow:0 0`, +1 for that fix. – King King Jun 19 '14 at 16:51
  • @wickywills the answer was updated with a nice trick with `box-shadow`, it seems to fix the issue. You mentioned about the same issue on Chrome, I hope that issue is caused by something else because changing the opacity has never been able to cause an issue in Chrome (as well as in many other browers). I'm also surprised that FireFox has this issue, maybe it's because I've rarely tried my demos on FireFox. – King King Jun 19 '14 at 17:03
  • @KingKing Yep, the `box-shadow` one worked. Will test it in Chrome when I get back to work, but I'm fairly sure that it would work for that also. Thanks again guys! – wickywills Jun 19 '14 at 22:08
  • @KingKing After further investigation I think I've come to a better understanding of what's causing the problem. See edit. – apaul Jun 20 '14 at 17:34
  • @apaul34208 it's still unclear to me on the fact that when hovering over the image, it's jerked a little and turns back right to the normal height, I even tried removing all transitions, it's still jerked. If the height is just shrunk a little and does ***not*** turn back to the normal state, it would be easier to understand. If it's some kind of anti-aliasing related problem in FireFox, there is another well-known fix by using `outline` (instead of `border`). This kind of bug is very well-known in FireFox, however looks like it's hard to be fixed in next updates of FF. – King King Jun 20 '14 at 18:22
3

Works good on my Firefox.

Anyway you can try to add some special attributes that will prepare the browser for the transition and actually render the element with possible transformation in mind.

Such an attribute is transform: translate3d(0,0,0);

Like this :

.link-box .image img { 
    transition: all .2s ease-out; 
    width:200px; 
    transform: translate3d(0,0,0); 
}
.link-box.large { position: relative;}
.link-box.large:hover .image img { opacity: .65; }
drinchev
  • 19,201
  • 4
  • 67
  • 93
  • I was getting a slight movement in FF but this has fixed it. +1 – John Halsey Jun 19 '14 at 15:01
  • I'm using Firefox version 30 by the way – wickywills Jun 19 '14 at 15:07
  • @wickywills I've tested it on FF29 and looks like it's fixed, trying testing on FF30 after updating. – King King Jun 19 '14 at 15:11
  • I tested again on FF30 and `translate3d` seems to fix it. Also keep in mind that you don't need anymore prefixes to `transform`. http://caniuse.com/transforms2d – drinchev Jun 19 '14 at 15:16
  • well, it's strange, just updated FF from 29 to 30, now it seems that the issue is not fixed in FF30 (although I had tested before with FF29, which did fix the issue). – King King Jun 19 '14 at 15:21