63

I have an image that is a link. I want to show a different image when the user hovers over the link.

Currently I'm using this code:

<a href="http://twitter.com/me" title="Twitter link">
<div id="twitterbird" class="sidebar-poster"></div></a>

div.sidebar-poster {
margin-bottom: 10px;
background-position: center top;
background-repeat: no-repeat;
width: 160px;
}
#twitterbird {
background-image: url('twitterbird.png');
}
#twitterbird:hover {
background-image: url('twitterbird_hover.png');
}

But I'm having loads of problems: the div isn't picking up the CSS rules (the element just isn't showing the related CSS rules when I view it in Firebug).

Perhaps this is because (as I know) this is invalid HTML: you can't put an <a> around a <div>. However, if I switch to <span> then it seems I get bigger problems, because you can't set a height and width on a span reliably.

Help! How can I do this better?

Community
  • 1
  • 1
AP257
  • 89,519
  • 86
  • 202
  • 261

8 Answers8

123
 <a href="http://twitter.com/me" class="twitterbird" title="Twitter link"></a>

use a class for the link itself and forget the div

.twitterbird {
 margin-bottom: 10px;
 width: 160px;
 height:160px;
 display:block;
 background:transparent url('twitterbird.png') center top no-repeat;
}

.twitterbird:hover {
   background-image: url('twitterbird_hover.png');
}
Caspar Kleijne
  • 21,552
  • 13
  • 72
  • 102
  • 3
    As the image is downloaded on demand, the first time somebody visits the page, there will be a split second where no image exists after hovering. Just wanted to point this out as it may be undesirable for some. – Chris Smith Jul 15 '17 at 22:05
41

If you have just a few places where you wish to create this effect, you can use the following html code that requires no css. Just insert it.

<a href="TARGET URL GOES HERE"><img src="URL OF FIRST IMAGE GOES HERE" 
onmouseover="this.src='URL OF IMAGE ON HOVER GOES HERE'"
onmouseout="this.src='URL OF FIRST IMAGE GOES HERE AGAIN'" /></A>

Be sure to write the quote marks exactly as they are here, or it will not work.

Dave Loomis
  • 427
  • 4
  • 2
  • I have tried this and it is assume. I understand that this is JavaScript... Could you kindly let me know how this can be done with CSS. If possible I need the actual code as an example. – MBC870 May 07 '13 at 20:57
10

The problem with changing it via JavaScript or CSS is that if you have a slower connection, the image will take a second to change to the hovered version. This will cause an undesirable flash as one disappears while the other downloads.

What I've done before is have two images. Then hide and show each depending on the hover state. This will allow for a clean switch between the two images.

<a href="/settings">
    <img class="default" src="settings-default.svg"/>
    <img class="hover" src="settings-hover.svg"/>
    <span>Settings</span>
</a>

a img.hover {
    display: none;
}
a img.default {
    display: inherit;
}
a:hover img.hover {
    display: inherit;
}
a:hover img.default {
    display: none;
}
Chris Smith
  • 2,928
  • 4
  • 27
  • 59
6

That could be done with <a> only:

#twitterbird {
 display: block; /* 'convert' <a> to <div> */
 margin-bottom: 10px;
 background-position: center top;
 background-repeat: no-repeat;
 width: 160px;
 height: 160px;
 background-image: url('twitterbird.png');
}
#twitterbird:hover {
 background-image: url('twitterbird_hover.png');
}
Floern
  • 33,559
  • 24
  • 104
  • 119
  • You mean with something like ``? Unfortunately, that renders with width and height of 0 (even with the CSS classes you suggest) in Chrome. – AP257 Jan 17 '11 at 20:25
  • okay, if I try a test page with just your suggestion it displays... so why have I got a height and width of 0 on my 'real' page? I've tried setting `height: 160px ! important` but it doesn't help... – AP257 Jan 17 '11 at 20:29
  • ...to explain: in Chrome Developer Tools, all the styles above show up under 'Matched Rules', but then in the 'Computed Style' section, the height and width are zero! For no apparent reason. Why? – AP257 Jan 17 '11 at 20:31
  • I've created a new question for this: http://stackoverflow.com/questions/4717673/css-mystery-width-being-set-to-0px-without-any-css-rules – AP257 Jan 17 '11 at 20:41
4

It can be better if you set the a element in this way

display:block;

and then by css sprites set your over background

Edit: check this example out http://jsfiddle.net/steweb/dTwtk/

stecb
  • 14,478
  • 2
  • 50
  • 68
3

You could do the following, without needing CSS...

<a href="ENTER_DESTINATION_URL"><img src="URL_OF_FIRST_IMAGE_SOURCE" onmouseover="this.src='URL_OF_SECOND_IMAGE_SOURCE'" onmouseout="this.src='URL_OF_FIRST_IMAGE_SOURCE_AGAIN'" /></a>

Example: https://jsfiddle.net/jord8on/k1zsfqyk/

This solution was PERFECT for my needs! I found this solution here.

Disclaimer: Having a solution that is possible without CSS is important to me because I design content on the Jive-x cloud community platform which does not give us access to global CSS.

jord8on
  • 166
  • 1
  • 3
  • 18
0
<!DOCTYPE html>
<html lang="en">
<head>
<title>Change Image on Hover in CSS</title>
<style type="text/css">
    .card {
        width: 130px;
        height: 195px;
        background: url("../images/pic.jpg") no-repeat;
        margin: 50px;
    }
    .card:hover {
        background: url("../images/anotherpic.jpg") no-repeat;
    }
</style>
</head>
<body>
    <div class="card"></div>
</body>
</html>       
0

If you give generally give a span the property display:block, it'll then behave like a div, i.e you can set width and height.

You can also skip the div or span and just set the a the to display: block and apply the backgound style to it.

<a href="" class="myImage"><!----></a>


    <style>
      .myImage {display: block; width: 160px; height: 20px; margin:0 0 10px 0; background: url(image.png) center top no-repeat;}
.myImage:hover{background-image(image_hover.png);}
    </style>
wosis
  • 1,209
  • 10
  • 14