Changing image on hover with CSS/HTML

646,800

Solution 1

One solution is to use also the first image as a background image like this:

<div id="Library"></div>
#Library {
   background-image: url('LibraryTransparent.png');
   height: 70px;
   width: 120px;
}

#Library:hover {
   background-image: url('LibraryHoverTrans.png');
}

If your hover image has a different size, you've got to set them like so:

#Library:hover {
   background-image: url('LibraryHoverTrans.png');
   width: [IMAGE_WIDTH_IN_PIXELS]px;
   height: [IMAGE_HEIGHT_IN_PIXELS]px;
}

Solution 2

Another option is to use JS:

<img src='LibraryTransparent.png' onmouseover="this.src='LibraryHoverTrans.png';" onmouseout="this.src='LibraryTransparent.png';" />

Solution 3

What I usually do is that I create a double image with both states, acting like kind of a two-frame film which I then use with as background for the original element so that the element has width / height set in pixels, resulting in showing only one half of the image. Then what the hover state defines is basically "move the film to show the other frame".

For example, imagine that the image has to be a gray Tux, that we need to change to colorful Tux on hover. And the "hosting" element is a span with id "tuxie".

  1. I create 50 x 25 image with two Tuxes, one in color and other gray,
  2. then assign the image as a background for a 25 x 25 span,
  3. and finally set the hover to simply move the background 25px left.

The minimal code:

<style>
    #tuxie {
        width: 25px; height: 25px;
        background: url('images/tuxie.png') no-repeat left top;
    }
    #tuxie:hover { background-position: -25px 0px }
</style>

<div id="tuxie" />

and the image:

Two-frame Tuxie "film"

Advantages are:

  • By putting both frames in one file, it's ensured that they are loaded at once. This avoids the ugly glitch on slower connections when the other frame never loads immediately, so first hover never works properly.

  • It may be easier to manage your images this way since "paired" frames are never confused.

  • With smart use of Javascript or CSS selector, one can extend this and include even more frames in one file.

    In theory you could put even multiple buttons in single file and govern their display by coordinates, although such approach could get quickly out of hand.

Note that this is built with background CSS property, so if you really need to use with <img />s, you must not set the src property since that overlaps the background. (Come to think that clever use of transparency here could lead to interesting results, but probably very dependent on quality of image as well as of the engine.).

Solution 4

Use content:

#Library {
    height: 70px;
    width: 120px;
}

#Library:hover {
    content: url('http://www.furrytalk.com/wp-content/uploads/2010/05/2.jpg');
    height: 70px;
    width: 120px;
}

JSFiddle

Solution 5

.hover_image:hover {text-decoration: none} /* Optional (avoid undesired underscore if a is used as wrapper) */
.hide {display:none}
/* Do the shift: */
.hover_image:hover img:first-child{display:none}
.hover_image:hover img:last-child{display:inline-block}
<body> 
    <a class="hover_image" href="#">
        <!-- path/to/first/visible/image: -->
        <img src="http://farmacias.dariopm.com/cc2/_cc3/images/f1_silverstone_2016.jpg" />
        <!-- path/to/hover/visible/image: -->
        <img src="http://farmacias.dariopm.com/cc2/_cc3/images/f1_malasia_2016.jpg" class="hide" />
    </a>
</body>

To try to improve this Rashid's good answer I'm adding some comments:

The trick is done over the wrapper of the image to be swapped (an 'a' tag this time but maybe another) so the 'hover_image' class has been put there.

Advantages:

  • Keeping both images url together in the same place helps if they need to be changed.

  • Seems to work with old navigators too (CSS2 standard).

  • It's self explanatory.

  • The hover image is preloaded (no delay after hovering).

Share:
646,800

Related videos on Youtube

user2704743
Author by

user2704743

Updated on July 05, 2022

Comments

  • user2704743
    user2704743 almost 2 years

    I have this problem where I have set an image to display another image when the mouse hovers over, however the first image still appears and the new one doesn't change height and width and overlaps the other one. I'm still pretty new to HTML/CSS so I may have missed something simple. Here is the code:

    <img src="LibraryTransparent.png" id="Library">
    
    #Library {
        height: 70px;
        width: 120px;
    }
    
    #Library:hover {
        background-image: url('LibraryHoverTrans.png');
        height: 70px;
        width: 120px;
    }
    
  • user2704743
    user2704743 over 10 years
    Thanks, what do I need to change to fix this problem?
  • user2704743
    user2704743 over 10 years
    thanks, will this also change the height and width of the new image on hover?
  • Aurelio De Rosa
    Aurelio De Rosa over 10 years
    If your hover image has a different size, you have to write them.
  • user2704743
    user2704743 over 10 years
    your solution worked with the hover but the size of the images hasn't changed?
  • Tomzan
    Tomzan over 10 years
    Do you want it to change? if yes just add to :hover class the right size.
  • user2704743
    user2704743 over 10 years
    I tried your solution exactly as shown, for some reason though the sizes aren't changing, the hover works though
  • user2704743
    user2704743 over 10 years
    yes I read the update, so i changed my img tag to div, then copied down what you have here. it fixed the hover but neither the first image or hover image are changing sizes i'm not sure why?
  • Aurelio De Rosa
    Aurelio De Rosa over 10 years
    No, I meant the "If your over image has a different size, you've to set them like so:" part...
  • user2704743
    user2704743 over 10 years
    my image is within a link tag does this have an effect on anything?
  • user2704743
    user2704743 over 10 years
    hi I've been trying this solution, it fixes the hover issue but doesn't fix the sizes they stay the same what can I do?
  • Daniel Schwarz
    Daniel Schwarz over 10 years
    Seems to be working for for me. Can we see your code? Here's mine: jsfiddle.net/kHBzh
  • m02ph3u5
    m02ph3u5 over 8 years
    This requires javascript; didn't OP ask for a css/html solution?
  • Lombas
    Lombas almost 8 years
    I think this is the best solution. It's simpler, uses the proper <img> tag, and doesn't have to worry with background-repeat and stuff like that.
  • piyushj
    piyushj almost 8 years
    add some description/comments to it, simply posting code wont help
  • the digitalmouse
    the digitalmouse almost 8 years
    And while this is resurrecting an old solution, it is really a bad practice to embed styles with the HTML. All style info should be included at the top of the HTML file inside style tags, or linked from an external stylesheet.
  • jagb
    jagb about 7 years
    +1 for using "sprites", Sprites are making pages load faster, a good online tool that can help creating sprites for an existing website is SpriteMe, it's very useful to create sprites faster as it will create the new CSS and images for you.
  • Chaz
    Chaz over 6 years
    I found this to be browser dependent. Works in Chrome, but not Firefox or IE11.
  • Vucko
    Vucko over 6 years
    @Chaz check the Browser compatibility.
  • Chaz
    Chaz over 6 years
    @Vucko, I believe the compatibility issue is with regard to using the content attribute on something that is not :before or :after. From the Browser Compatibility link: The content CSS property is used with the ::before and ::after pseudo-elements to generate content in an element. Try the JSFiddle above in Firefox or IE; it does not work.
  • CliffVandyck
    CliffVandyck over 6 years
    Is there a way to smoothly transition the img?
  • kurdtpage
    kurdtpage over 6 years
    @thedigitalmouse good point, I have updated my answer and removed CSS
  • kurdtpage
    kurdtpage over 6 years
    @CliffVandyck you could possibly use jQuery animation to do that
  • Nishanth Shaan
    Nishanth Shaan over 4 years
    Someone has downvoted my answer. please explain why you downoted for me to unerstand and improve the answer.
  • 1.21 gigawatts
    1.21 gigawatts almost 4 years
    It's odd that there isn't a CSS src or srcset property yet. Setting the background image is not the same as setting the source. Maybe a candidate for review.
  • Akhilesh Mishra
    Akhilesh Mishra almost 4 years
    You should add some more details about your answer
  • Hsinhsin Hung
    Hsinhsin Hung about 3 years
    It's the best answer. Thank you very much.
  • WinEunuuchs2Unix
    WinEunuuchs2Unix about 2 years
    This is really cool. Would you answer a new question on click image instead of hover with ability to get current state of on/off? (Top half/bottom half of image currently displayed)? Or would that be a duplicate question?