445

I have a few images and their rollover images. Using jQuery, I want to show/hide the rollover image when the onmousemove/onmouseout event happen. All my image names follow the same pattern, like this:

Original Image: Image.gif

Rollover Image: Imageover.gif

I want to insert and remove the "over" portion of image source in the onmouseover and onmouseout event, respectively.

How can I do it using jQuery?

Community
  • 1
  • 1
Sachin Gaur
  • 12,909
  • 9
  • 33
  • 38
  • 10
    Just what I'm looking for. Thanks for posting the Question! – Samuel Meddows Feb 18 '11 at 06:40
  • Change image on mouseover http://www.dotnetspeaks.com/DisplayArticle.aspx?ID=89 – Sumit Dec 07 '10 at 08:15
  • I have a problem like this([My Question](http://stackoverflow.com/q/10600678/381819)). The answer of this question is great but in IE9 every time that you goes over button, there is additional request for image and it is very bad. Is any body has better answer? – Iman May 16 '12 at 08:51
  • I wrote a small how-to with examples for beginners, *[Change image with JavaScript (or jQuery)](http://www.anyexample.com/webdev/javascript/jquery_change_image.xml)*. There's also an example without using jQuery. – gothy Aug 09 '10 at 20:44

14 Answers14

621

To set up on ready:

$(function() {
    $("img")
        .mouseover(function() { 
            var src = $(this).attr("src").match(/[^\.]+/) + "over.gif";
            $(this).attr("src", src);
        })
        .mouseout(function() {
            var src = $(this).attr("src").replace("over.gif", ".gif");
            $(this).attr("src", src);
        });
});

For those that use url image sources:

$(function() {
        $("img")
            .mouseover(function() {
               var src = $(this).attr("src");
               var regex = /_normal.svg/gi;
               src = this.src.replace(regex,'_rollover.svg');
               $(this).attr("src", src);

            })
            .mouseout(function() {
               var src = $(this).attr("src");
               var regex = /_rollover.svg/gi;
               src = this.src.replace(regex,'_normal.svg');
               $(this).attr("src", src);

            });
    });
jemmamariex3
  • 107
  • 2
  • 17
Jarrod Dixon
  • 15,727
  • 9
  • 60
  • 72
114

I know you're asking about using jQuery, but you can achieve the same effect in browsers that have JavaScript turned off using CSS:

#element {
    width: 100px; /* width of image */
    height: 200px; /* height of image */
    background-image: url(/path/to/image.jpg);
}

#element:hover {
    background-image: url(/path/to/other_image.jpg);
}

There's a longer description here

Even better, however, is to use sprites: simple-css-image-rollover

always-a-learner
  • 3,671
  • 10
  • 41
  • 81
Tyson
  • 6,214
  • 3
  • 32
  • 37
  • 1
    yeah, but is little harder to do this on IMAGE elements :) Besides that, CSS mean the separation of content from presentation. If you do this, you join those things ;) You can't have this for a large site, right? – Ionuț Staicu Feb 12 '09 at 07:56
  • I agree with you about the css, but it seems the question author wanted a generic solution that applies to multiple images all at once. – Jarrod Dixon Feb 12 '09 at 07:56
  • indeed, but i guess is not the same image repeated over and over again :) I'm a css guy, but this time... is not the best pick :) – Ionuț Staicu Feb 12 '09 at 08:03
  • 9
    This solution is the most preferable option, unless you are doing some effects. I was thinking the exact same thing +1 – Angel.King.47 May 22 '11 at 14:29
  • 6
    It is the best solution. To avoid waiting for the new image (network request) use a single image.jpg and play with background-position to show / hide the good one. – kheraud Sep 07 '11 at 10:46
  • 2
    @kheraud Moving a single image is a good solution, but whether it's the best or not depends on the image size. For example, on slow internet, downloading two 1920px wide images in one gigantic file would take unacceptably long. For icons and small images though it works fine. – DACrosby Apr 29 '12 at 05:50
63

If you have more than one image and you need something generic that doesn't depend on a naming convention.

HTML

<img data-other-src="big-zebra.jpg" src="small-cat.jpg">
<img data-other-src="huge-elephant.jpg" src="white-mouse.jpg">
<img data-other-src="friendly-bear.jpg" src="penguin.jpg">

JavaScript

$('img').bind('mouseenter mouseleave', function() {
    $(this).attr({
        src: $(this).attr('data-other-src') 
        , 'data-other-src': $(this).attr('src') 
    })
});
Richard Ayotte
  • 5,021
  • 1
  • 36
  • 34
  • 1
    This was the one for me. Just remember to put the javascript inside a function to execute it ie when DOM ready "$(function(){ });" – Mischa Sep 27 '12 at 04:05
  • Actually it triggers when the page is still loading, and when your mouse cursor is actually over the selector it replaces the url so then the effect is inverted – Mike Aug 31 '16 at 10:38
57
    /* Teaser image swap function */
    $('img.swap').hover(function () {
        this.src = '/images/signup_big_hover.png';
    }, function () {
        this.src = '/images/signup_big.png';
    });
Jonas Lejon
  • 3,189
  • 3
  • 28
  • 26
  • 4
    Keep in mind that going this way will mean that the user will see a pause on first hover while the browser fetches the image. – Tyson Jun 26 '12 at 03:51
  • 1
    @Tyson Hate to hop onto the train late, but you can preload the images by either via [Javascript](http://stackoverflow.com/questions/3646036/javascript-preloading-images) or [CSS](http://css-tricks.com/snippets/css/css-only-image-preloading/) – cbr Feb 12 '14 at 16:45
  • Doesn't work on Chrome 37 neither. $(this).attr("src", src) works fine. – Le Droid Jan 27 '16 at 22:17
26

A generic solution that doesn't limit you to "this image" and "that image" only may be to add the 'onmouseover' and 'onmouseout' tags to the HTML code itself.

HTML

<img src="img1.jpg" onmouseover="swap('img2.jpg')" onmouseout="swap('img1.jpg')" />

JavaScript

function swap(newImg){
  this.src = newImg;
}

Depending on your setup, maybe something like this would work better (and requires less HTML modification).

HTML

<img src="img1.jpg" id="ref1" />
<img src="img3.jpg" id="ref2" />
<img src="img5.jpg" id="ref3" />

JavaScript / jQuery

// Declare Arrays
  imgList = new Array();
  imgList["ref1"] = new Array();
  imgList["ref2"] = new Array();
  imgList["ref3"] = new Array();

//Set values for each mouse state
  imgList["ref1"]["out"] = "img1.jpg";
  imgList["ref1"]["over"] = "img2.jpg";
  imgList["ref2"]["out"] = "img3.jpg";
  imgList["ref2"]["over"] = "img4.jpg";
  imgList["ref3"]["out"] = "img5.jpg";
  imgList["ref3"]["over"] = "img6.jpg";

//Add the swapping functions
  $("img").mouseover(function(){
    $(this).attr("src", imgList[ $(this).attr("id") ]["over"]);
  }

  $("img").mouseout(function(){
    $(this).attr("src", imgList[ $(this).attr("id") ]["out"]);
  }
DACrosby
  • 11,116
  • 3
  • 39
  • 51
21
$('img.over').each(function(){
    var t=$(this);
    var src1= t.attr('src'); // initial src
    var newSrc = src1.substring(0, src1.lastIndexOf('.'));; // let's get file name without extension
    t.hover(function(){
        $(this).attr('src', newSrc+ '-over.' + /[^.]+$/.exec(src1)); //last part is for extension   
    }, function(){
        $(this).attr('src', newSrc + '.' + /[^.]+$/.exec(src1)); //removing '-over' from the name
    });
});

You may want to change the class of images from first line. If you need more image classes (or different path) you may use

$('img.over, #container img, img.anotherOver').each(function(){

and so on.

It should work, I didn't test it :)

Ionuț Staicu
  • 21,360
  • 11
  • 51
  • 58
  • 2
    +1 Doh, forgot about the hover event helper! And nice suggestion about adding a class to the images - truly is a best practice :) – Jarrod Dixon Feb 12 '09 at 08:05
  • 1
    That's far better solution because it caches the old image source. – trante Jun 29 '12 at 20:23
  • The negative part is, if the image is in the bottom of the page and there is 10-20 images then layout becomes weird. – trante Jun 29 '12 at 20:24
13

I was hoping for an über one liner like:

$("img.screenshot").attr("src", $(this).replace("foo", "bar"));
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
chovy
  • 72,281
  • 52
  • 227
  • 295
6

If the solution you are looking for is for an animated button, then the best you can do to improve in performance is the combination of sprites and CSS. A sprite is a huge image that contains all the images from your site (header, logo, buttons, and all decorations you have). Each image you have uses an HTTP request, and the more HTTP requests the more time it will take to load.

.buttonClass {
    width: 25px;
    height: 25px;
    background: url(Sprite.gif) -40px -500px;
}
.buttonClass:hover {
    width: 25px;
    height: 25px;
    background: url(Sprite.gif) -40px -525px;
}

The 0px 0px coordinates will be the left upper corner from your sprites.

But if you are developing some photo album with Ajax or something like that, then JavaScript (or any framework) is the best.

Have fun!

Kevin Ji
  • 10,479
  • 4
  • 40
  • 63
matt
  • 638
  • 2
  • 10
  • 22
4

Whilst looking for a solution some time back, I found a similar script to the below, which after some tweaking I got working for me.

It handles two images, that almost always default to "off", where the mouse is off the image (image-example_off.jpg), and the occasional "on", where for the times the mouse is hovered, the required alternative image (image-example_on.jpg) is displayed.

<script type="text/javascript">        
    $(document).ready(function() {        
        $("img", this).hover(swapImageIn, swapImageOut);

        function swapImageIn(e) {
            this.src = this.src.replace("_off", "_on");
        }
        function swapImageOut (e) {
            this.src = this.src.replace("_on", "_off");
        }
    });
</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • I realise that the above function would execute for all images within the DOM as it is currently coded. Supplying further context would make it focus the effect to specific img elements. – Kristopher Rout Sep 05 '12 at 22:50
4
$('img').mouseover(function(){
  var newSrc = $(this).attr("src").replace("image.gif", "imageover.gif");
  $(this).attr("src", newSrc); 
});
$('img').mouseout(function(){
  var newSrc = $(this).attr("src").replace("imageover.gif", "image.gif");
  $(this).attr("src", newSrc); 
});
iamrasec
  • 49
  • 1
3
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>JQuery</title>
<script src="jquery.js" type="text/javascript"> </script>
<style type="text/css">
    #box{
        width: 68px;
        height: 27px;
        background: url(images/home1.gif);
        cursor: pointer;
    }
</style>

<script type="text/javascript">

$(function(){

    $('#box').hover( function(){
        $('#box').css('background', 'url(images/home2.gif)');

    });
    $('#box').mouseout( function(){
        $('#box').css('background', 'url(images/home1.gif)');

    });

});
</script>
</head>

<body>
<div id="box" onclick="location.href='index.php';"></div>
</body>
</html>
Imran
  • 87,203
  • 23
  • 98
  • 131
2

I've made something like the following code :)

It works only, when you have a second file named with _hover, for example, facebook.png and facebook_hover.png

$('#social').find('a').hover(function() {
    var target = $(this).find('img').attr('src');
    //console.log(target);
    var newTarg = target.replace('.png', '_hover.png');
    $(this).find('img').attr("src", newTarg);
}, function() {
    var target = $(this).find('img').attr('src');
    var newTarg = target.replace('_hover.png', '.png');
    $(this).find('img').attr("src", newTarg);
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Grzegorz
  • 21
  • 1
1
<img src="img1.jpg" data-swap="img2.jpg"/>



img = {

 init: function() {
  $('img').on('mouseover', img.swap);
  $('img').on('mouseover', img.swap);
 }, 

 swap: function() {
  var tmp = $(this).data('swap');
  $(this).attr('data-swap', $(this).attr('src'));
  $(this).attr('str', tmp);
 }
}

img.init();
Gustav Westling
  • 633
  • 3
  • 9
1

Adapted from Richard Ayotte's code - To target an img in a ul/li list (found via wrapper div class here), something like this:

$('div.navlist li').bind('mouseenter mouseleave', function() {    
    $(this).find('img').attr({ src: $(this).find('img').attr('data-alt-src'), 
    'data-alt-src':$(this).find('img').attr('src') }
); 
anoldermark
  • 366
  • 3
  • 8