Switching a DIV background image with jQuery

Viewed 834532

I am making an expand/collapse call rates table for the company I work for. I currently have a table with a button under it to expand it, the button says "Expand". It is functional except I need the button to change to "Collapse" when it is clicked and then of course back to "Expand" when it is clicked again. The writing on the button is a background image.

So basically all I need is to change the background image of a div when it is clicked, except sort of like a toggle.

14 Answers
$('#divID').css("background-image", "url(/myimage.jpg)");  

Should do the trick, just hook it up in a click event on the element

$('#divID').click(function()
{
  // do my image switching logic here.
});

There are two different ways to change a background image CSS with jQuery.

  1. $('selector').css('backgroundImage','url(images/example.jpg)');
  2. $('selector').css({'background-image':'url(images/example.jpg)'});

Look carefully to note the differences. In the second, you can use conventional CSS and string multiple CSS properties together.

If you use a CSS sprite for the background images, you could bump the background offset +/- n pixels depending on whether you were expanding or collapsing. Not a toggle, but closer to it than having to switch background image URLs.

One way to do this is to put both images in the HTML, inside a SPAN or DIV, you can hide the default either with CSS, or with JS on page load. Then you can toggle on click. Here is a similar example I am using to put left/down icons on a list:

$(document).ready(function(){
    $(".button").click(function () {
        $(this).children(".arrow").toggle();
            return false;
    });
});

<a href="#" class="button">
    <span class="arrow">
        <img src="/images/icons/left.png" alt="+" />
    </span>
    <span class="arrow" style="display: none;">
        <img src="/images/down.png" alt="-" />
    </span>
</a>

This works on all current browsers on WinXP. Basically just checking what the current backgrond image is. If it's image1, show image2, otherwise show image1.

The jsapi stuff just loads jQuery from the Google CDN (easier for testing a misc file on the desktop).

The replace is for cross-browser compatibility (opera and ie add quotes to the url and firefox, chrome and safari remove quotes).

<html>
    <head>
        <script src="http://www.google.com/jsapi"></script>
        <script>
          google.load("jquery", "1.2.6");
          google.setOnLoadCallback(function() {
            var original_image = 'url(http://stackoverflow.com/Content/img/wmd/link.png)';
            var second_image = 'url(http://stackoverflow.com/Content/img/wmd/code.png)';

            $('.mydiv').click(function() {
                if ($(this).css('background-image').replace(/"/g, '') == original_image) {
                    $(this).css('background-image', second_image);
                } else {
                    $(this).css('background-image', original_image);
                }

                return false;
            });
          });
        </script>

        <style>
            .mydiv {
                background-image: url('http://stackoverflow.com/Content/img/wmd/link.png');
                width: 100px;
                height: 100px;
            }
        </style>
    </head>
    <body>
        <div class="mydiv">&nbsp;</div>
    </body>
</html>

I always use a timestamp as well to prevent browsers from caching the image. For example, if the user is rotating their avatar, it will often get cached and appear to not change.

var d = new Date();
var t = d.getTime();

$('#avatar').css("background-image", "url(" + iPath + "?" + t + ")");

CSS Sprites work best. I tried switching classes and manipulating the 'background-image' property with jQuery, none worked. I think it's because the browsers (at least the latest stable Chrome) can't "reload" an image already loaded.

Bonus : CSS Sprites are faster to download and faster to display. Less HTTP requests means faster page load. Reducing the number of HTTP is the best way to improve front end performance, so I recommend going this route all the time.

Related