2

I want to know if there's a way to make a GIF have this exact behavior:

  • Start paused in the page;
  • Play only while hovering;
  • Pause at the exact frame it was when dragging the mouse out of the image.

Is it possible to do this? Preferably without JavaScript, but I can use it if necessary.

1 Answers1

2

There is. Basically you will need to create the gif yourself using individual frames. Essentially, you create X number of frames, then use keyframes to cycle through them as background-image properties of an absolutely positioned div. The "gif" starts with the property animation-play-state:paused and changes to running on hover. It is possible to switch these properties obviously. Consider the following:

Your markup:

<div class="gif"></div>

And your CSS:

.gif {
    position: absolute;
    margin: auto;
    background-image: url(/path/to/starting.frame);
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-position: center;
    animation: play 0.5s infinite steps(1);
    animation-play-state: paused;
}
.gif:hover {
    animation-play-state:running;
}

@keyframes play {
    0%   { background-image: url('/path/to/0.frame'); } 
    15%  { background-image: url('/path/to/1.frame'); }
    30%  { background-image: url('/path/to/2.frame'); }
    45%  { background-image: url('/path/to/3.frame'); }
    60%  { background-image: url('/path/to/4.frame'); }
    75%  { background-image: url('/path/to/5.frame'); }
    90%  { background-image: url('/path/to/6.frame'); }
    100% { background-image: url('/path/to/7.frame'); }
}

Here is an example I was able to find and alter.

Claire
  • 3,146
  • 6
  • 22
  • 37
  • Thank you. I was messing with the code while waiting for an answer and discovered this method, but in the first loop of the GIF, it blinks every frame. Why is this happening? – Prinzherbert Aug 14 '19 at 00:42
  • @Prinzherbert because each frame is loading into the DOM during the keyframe rotation. You could solve this by preloading the images. – Claire Aug 14 '19 at 00:46
  • Oh, I see. I actually want to make 11 of these, so is there a way to make it more compact? – Prinzherbert Aug 14 '19 at 00:55
  • @Prinzherbert yes you can make as many or as few as you'd like. Just do the math on 100 divided by your final number off frames, then make your percentages that far apart. For example, if you have 21 frames, you go 100/20 = 5 (because the first frame is 0%), and your keyframe percentages would be 0, 5, 10, 15, 20, 25, etc, each with the corresponding image for that frame. – Claire Aug 14 '19 at 00:58
  • I didn't mean that. I made 20 frames for my GIF, but I want 11 of these 20-frame GIFs. Considering the preload lines, that's like 440 lines, so I wanted to know if there is any way to reach the same effect in a more compact way. – Prinzherbert Aug 14 '19 at 01:06
  • Ah. Well the first step would be to make sure the frames are as lightweight as possible. Then I'd use JS to preload each one as it comes into view in the window or something, rather than all on page load. Alternatively, you could just preload them using jQuery at `document.ready();`, that way it doesn't affect your page load times. – Claire Aug 14 '19 at 01:09
  • Basically you just want them in the DOM before the animation runs. Doesn't matter exactly when that happens. – Claire Aug 14 '19 at 01:09
  • And if you name them with incremental file names you can just write one function to preload them all. – Claire Aug 14 '19 at 01:10
  • That's exactly what I need. How do I preload every frame using incremental file names? – Prinzherbert Aug 14 '19 at 01:27
  • you can check out [this link](https://forums.adobe.com/thread/1943008) and [this link](https://stackoverflow.com/questions/10765511/preloading-100s-of-images-in-wordpress-with-only-one-http-request) for more info on how and why to use certain methods. I'd actually suggest creating a sprite for each set of images and loading them that way. Use PHP to grab the sprites and jQuery to preload them. There are options. – Claire Aug 14 '19 at 01:38