3

I have several animations on my site that I just realized do not even show up in Firefox or Internet Explorer. I have the background-image within the keyframes. I do this because I have different images in different percentages with the animation.

Why doesn't the background-image display within the keyframes in Firefox and Internet Explorer and is there a way to make this work?

Harry
  • 87,580
  • 25
  • 202
  • 214
Becky
  • 2,283
  • 2
  • 23
  • 50

1 Answers1

6

As per the specs, background-image is not an animatable or a transitionable property. But it does not seem to say anything about what or how the handling should be when it is used as part of transition or animation. Because of this, each browser seem to be handling it differently. While Chrome (Webkit) is displaying the background image, Firefox and IE seem to do nothing.

The below quote found in an article at oli.jp provides some interesting information:

While CSS Backgrounds and Borders Module Level 3 Editor’s Draft says “Animatable: no” for background-image at the time of writing, support for crossfading images in CSS appeared in Chrome 19 Canary. Until widespread support arrives this can be faked via image sprites and background-position or opacity. To animate gradients they must be the same type.

On the face of it, it looks like Firefox and IE are handling it correctly while Chrome is not. But, it is not so simple. Firefox seems to contradict itself when it comes to how it handles transition on background image as opposed to animation. While transitioning background-image, it shows up the second image immediately (hover the first div in the snippet) whereas while animating, the second image doesn't get displayed at all (hover the second div in the snippet).

So, conclusion is that it is better to not set background-image inside keyframes. Instead, we have to use background-position or opacity like specified @ oli.jp.

div {
  background-image: url(https://placehold.it/100x100);
  height: 100px;
  width: 100px;
  margin: 10px;
  border: 1px solid;
}
div:nth-of-type(1) {
  transition: background-image 1s ease;
}
div:nth-of-type(1):hover {
  background-image: url(https://placehold.it/100/123456/ffffff);
}
div:nth-of-type(2):hover {
  animation: show-img 1s ease forwards;
}
@keyframes show-img {
  to {
    background-image: url(https://placehold.it/100/123456/ffffff);
  }
}
<div></div>
<div></div>

If you have multiple images that should be shown at different percentages within the keyframe then it would be a better idea to add all those images on the element at start and animate their position like in the below snippet. This works the same way in Firefox, Chrome and IE.

div {
  background-image: url(https://placehold.it/100x100), url(https://placehold.it/100/123456/ffffff);
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: 0px 0px, 100px 0px;
  height: 100px;
  width: 100px;
  margin: 10px;
  border: 1px solid;
}
div:hover {
  animation: show-img 1s steps(1) forwards;
}
@keyframes show-img {
  to {
    background-position: -100px 0px, 0px 0px;
  }
}
<div></div>

Or, like in the below snippet. Basically each image is the same size as the container as background-size is set as 100% 100% but only one image is shown at any given time because of them being the same size as container. Between 0% to 50% the first image is shown because it is at 0px,0px (left-top) whereas the second image is at 100px,0px (outside the right border). At 50.1%, the first image is at -100px,0px (outside left border) and second image is at 0px,0px and so it is visible.

div {
  background-image: url(https://picsum.photos/id/0/367/267), url(https://picsum.photos/id/1/367/267);
  background-size: 100% 100%; /* each image will be 100px x 100px */
  background-repeat: no-repeat;
  background-position: 0px 0px, 100px 0px;
  height: 100px;
  width: 100px;
  margin: 10px;
  border: 1px solid;
  animation: show-img 5s ease forwards;
}
@keyframes show-img {
  0%, 50%{
    background-position: 0px 0px, 100px 0px; /* initially 1st image will be shown as it it as 0px 0px */
  }
  50.1%, 100% {
    background-position: -100px 0px, 0px 0px; /* at 50.1% 2nd image will be shown as it it as 0px 0px */
  }
}
<div></div>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Harry
  • 87,580
  • 25
  • 202
  • 214
  • Thanks for clarifying on this! I am a bit confused with how to make the multiple image scenario work, as I really don't see anything within your snippet that changes. Let's say, I have two different images, one shows from `0%, 50%` and the other `50.1%, 100%`...how would I make the image change? – Becky Mar 15 '16 at 15:55
  • @Becky: I've added a different example into the snippet (refer the last snippet). The original one would change images only on hover and so maybe that's why it wasn't clear for you :) – Harry Mar 15 '16 at 16:13
  • Would this still work for more than two images? Would I just put the `background-position` to: `background-position: 0px 0px, 100px 0px;` for every image I don't want seen and then pack to `background-position: 0px 0px, 0px 0px;` When I want them seen? – Becky Mar 15 '16 at 16:19
  • Yes it would still work. If there are 3 images you would do `0px 0px, 100px 0px, 200px 0px` till 33%, `-100px 0px, 0px 0px, 100px 0px` at 33.1% till 66% and `-200px 0px, -100px 0px, 0px 0px` from 66.7% till 100%. Just set the offsets depending on the no. of images. – Harry Mar 15 '16 at 16:22
  • 1
    Yes, it helped a lot! Thank you for your on-going contributions to help me. – Becky Mar 15 '16 at 19:31
  • Do you see why the white dot disappears as it should be transitioning into the stars? https://jsfiddle.net/zdg0L6ss/ – Becky Mar 19 '16 at 05:46
  • 1
    @Becky: There were a couple of unnecessary `background-image: none` inside the keyframes. [Here](https://jsfiddle.net/zdg0L6ss/1/) is the fixed fiddle. – Harry Mar 19 '16 at 06:23
  • IE11 is what I am using. – Becky Mar 19 '16 at 06:36
  • Just checked in IE11 and Edge using cross browser testing website and it works fine in both. – Harry Mar 19 '16 at 06:50
  • I just tried this with seven different images and it turned out horrible. Any ideas??? https://jsfiddle.net/346a6vok/ – Becky Apr 03 '16 at 06:30
  • 1
    @Becky: You should use the actual width of the images for the position calculation. I had used 100px because that was my image width. [Here](https://jsfiddle.net/346a6vok/1/) is a sample with an increased width. Adjust as appropriate. – Harry Apr 03 '16 at 07:05
  • I don't think this will work after all. I would need the image to appear as if it is one image. The way the css slides the image will never work. Thanks for letting me know how to do it though! – Becky Apr 03 '16 at 07:43
  • @Becky: If you don't need the slide effect then using animation timing function as steps like [here](https://jsfiddle.net/346a6vok/3/). Give all images the same width to be safe. – Harry Apr 03 '16 at 07:49