Member Avatar for Member #453901

I found a website that has a really cool effect for their links. The link is an image, and when you hover over it, it plays an animation, and after looking into it more, it seems that they use a single image with all of the different frames for the animation lined up, and they use this image as a background image and position it at one end. When you hover over it, they have the background image move from the position where the first frame is visible, to a position when the last frame is visible. Now, that only part I don't understand, is how they got it to actually go through the whole image to allow you to see all of the frames, rather than just jumping to the last frame.

I'm sorry if that makes very little sense, I can provide a link to the site if needed. I've looked all over and cannot find anything about this. I did find a lot about moving an image on hover, to show a different image, but nothing about slowing the process down.

Any help would be great.
Thanks!

Dani AI

Generated

Short answer: that site is using a sprite sheet (one image with all frames) and stepping the background across it so you see each frame in sequence rather than jumping straight to the last frame. As explained, sprites cut requests; a modern, simple way to play the frames on hover is CSS keyframes combined with the steps() timing function so the background advances in discrete frames instead of a smooth linear slide. (developer.mozilla.org)

Practical CSS (one-file, no JS): set the element size to one frame, use the sprite as background, then trigger an animation on hover that moves background-position across the sheet with steps(frameCount).

.sprite {
  width: 100px; height: 100px;
  background: url(sprite.png) 0 0 no-repeat;
}
.sprite:hover {
  animation: play .8s steps(8) 1 forwards;
}
@keyframes play {
  100% { background-position: -800px 0; } /* total shift = frameWidth * frames */
}

If you need programmatic control (variable speed, reverse, or older browser fallbacks) use a JS loop driven by requestAnimationFrame() and compute the current frame from elapsed time. Example pattern:

function playFrames(el, frames, frameW, duration) {
  let start = null;
  function tick(ts) {
    if (!start) start = ts;
    const t = Math.min((ts - start) / duration, 1);
    const frame = Math.floor(t * frames);
    el.style.backgroundPosition = -(frame * frameW) + 'px 0';
    if (t < 1) requestAnimationFrame(tick);
  }
  requestAnimationFrame(tick);
}

Prefer requestAnimationFrame() over setTimeout for smoother frames and correct syncing with display refresh. (developer.mozilla.org)

Troubleshooting & tips: make the frame width/height exact integers so offsets snap cleanly; set background-size if you scale the sprite; match steps(n) to the actual number of frames; use will-change sparingly; respect prefers-reduced-motion. Be aware background-position animations can force repaints and be more costly than transform/opacity, so test on real devices and keep hover animations short or use CSS-only where possible. (developer.mozilla.org)

(Notes: pointed out JS/HTML5 options and suggested transitions — the CSS steps() + keyframes approach above is usually the cleanest for sprite-frame playback, with JS fallbacks when you need extra control.)

Recommended Answers

All 3 Replies

the image with a bunch of included icons is a sprite and it works just as you describe
its a page minimisation strategy, only 1 image is downloaded, instead of a larger number of images each with the delay negotiating the transfer, for small images 100 bytes of image and 220 bytes of http is not efficient

the google search would be "how to enable css sprites animation",
the slowdown is a series of small movements, better described in the search links than i can do

hello t4gal,
check this..

You also could do it with html5:

or

It really all depends on what you want to do.. :)

You might be able to do it with a simple webkit transition, not sure if it will look right

#div{
background-image: url(myimage.jpg);
background-position:0px 0px;
-webkit-transition: background-position 5s linear;
-moz-transition: background-position 5s linear;
-o-transition: background-position 5s linear;
-ms-transition: background-position 5s linear;
transition: background-position 5s linear;
}
#div:hover{
background-position: 2000px 0px;
}

otherwise you will need to use javascript to make 'frames' to display along the way eg.

function slideImage(eid,direction,frames,frameWidth,timePerFrame,curFrame){
	//direction true || false (true is forward)
	var ele = document.getElementById(eid);
	var totalWidth = frameWidth*frames;
	var totalTime = frames*timePerFrame;
	if(curFrame >= 1){
	}else{
		curFrame = 1;
	}
	
	if(direction){
		ele.style.backgroundPosition = ((frameWidth*curFrame)-frameWidth)+'px 0px';
	}else{
		ele.style.backgroundPosition = (totalWidth - ((frameWidth*curFrame)-frameWidth))+'px 0px';
	}
	if(curFrame <= frames){
		curFrame++;
		setTimeout("slideImage('"+eid+"',"+direction+","+frames+","+frameWidth+","+timePerFrame+","+curFrame+")",timePerFrame);
	}
}

i tested it working ok with ->

<div id='testDiv' style='background-color:#337733;width:100px;height:80px;' onmouseover="slideImage('testDiv',true,10,100,1000);" onmouseout="slideImage('testDiv',false,10,100,1000);">hi</div>

the 5th var timeperframe should be lowered much more to give much smoother animation, 50(0.05 seconds) would be 20 fps but of course requires a much bigger picture

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.