views:

468

answers:

3

So I'm using CSS :hover to replace a submit button background. When I mouse over the button the old background image disappears (so it looks like nothing is there) for a moment and then reappears with the new background. I thought that perhaps the button image file size was too large but its only 1.4kb. Is there a way to prevent this, caching or pre-loading, or something along those lines?

+4  A: 

Is this only on the initial page display / hover?

This will be because the image file is only loaded on request - i.e. the hover action.

To avoid this, both button states should be stored in a single file. You then just need to adjust the background-position property to display the correct half of the image for it's current state.

Here's a rough example (note that button.png contains both image states and is 40 pixels high):

button {
background-image: url(button.png);
width: 60px;
height: 20px;
background-position: 0 0;
}

button:hover {
background-position: 0 -20px;
}
BrynJ
Take a look at this article: http://www.smashingmagazine.com/2009/04/27/the-mystery-of-css-sprites-techniques-tools-and-tutorials/
Perspx
Stored in a single file? Do you mean the CSS file? Both states are in the same CSS file.
Graham
I've edited my answer to clarify and also provided a basic example.
BrynJ
ooooo i see! thats clever great thanks Ill give that a shot
Graham
@Graham: Images for both states _in the same image file_ - then, as BrynJ's example shows, displaying a specific portion of that file as the image. This is a technique known as CSS spriting, and is often used to pull a bunch of icons, etc. down from the server (avoiding the request overhead on a ton of small files, and maximising the cache benefit).
Rob
@Perspx - nice link, it shows how far you can expand the concept.
BrynJ
great stuff guys thanks!
Graham
This is good, but not ideal. The problem is semantics and accessibility. You can't use the appropriate tag with this approach (input type="image"), which breaks semantics. And what happens when you turn images off? Then you have no button. My answer below addresses these issues.
Josh Stodola
@Josh. I used the button element as an example as its use was implied from the question - of course this approach can work equally with any number of elements. I'm not sure why styling a 'button type="submit"' breaks semantics? Whether you have no button without images enabled very much depends on if you have disabled the border, but also (and more importantly) if you have text defined for the button (e.g. <button>My Submit Button</button>).
BrynJ
A: 

It's because it takes time for the "hover" image to download before it displays. To prevent this, you can use a sprite image technique.

Example: Using Sprite Images with INPUT for a Hover Effect

Josh Stodola
A: 

You could, maybe, use a technique that's similar in intent, albeit not execution, to Bryn's answer, above.

.button {background-image: url(img/for/hover-state.png)
         background-position: top left;
         background-repeat: repeat-x;
         background-color: #fff;
         height: 1.5em;
         width: 5em;
}

.button span
        {background-image: url(img/for/non-hover-state.png);
         background-position: top left;
         background-repeat: repeat-x;
         background-color: #000;
         height: 1.5em;
         width: 5em;
}

.button:hover span
        {background-color: transparent;
         background-image: none;
}

The similarity I mentioned is to have both images present on the document in order to avoid the hover-flicker. On hover of the button the background-image of the span will disappear, and reveal the hover state, rather than having to load it on-demand.

The bonus is that, although I specified the height/width above this technique will work for dynamic re-sizing, not relying on fixed-width sizes of images (or it's as fluid as your design can allow it to be).

David Thomas
-1 for an additional HTTP request. Will not function properly for transparent images.
Josh Stodola
@Josh - true enough there's a second http request, but I find that the cost of an extra few kb is outweighed by the bonus of a more fluid design. And, so far as I can tell, it answered the asked-question. Each to their own though.
David Thomas
...the transparent image problem is presumably because the `span` as styled above has no `background-colour`. That's...not hard to resolve. Edited answer to accommodate.
David Thomas