web design

jQuery image panning

Image panning with animation easing that works on mouse movement with some css and jquery.

The code

The css

body {margin:0; padding:0; background:#eee;}
#outer_container, #imagePan{height:400px; width:600px;}
#outer_container{margin:40px auto; padding:4px; border:8px solid #dadada;}
#imagePan{position:relative; overflow:hidden; cursor:crosshair;}
#imagePan .container{position:relative; left:0;}

The jQuery scripts and plugins inside head tag

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" type="text/javascript"></script>
<script src="jquery.easing.1.3.js" type="text/javascript"></script>

The full javascript code is inserted in the end of the document, just before the closing body tag

$(window).load(function() {
    $imagePan_panning=$("#imagePan .panning");
    $imagePan_container=$("#imagePan .container");
    function MouseMove(e){
        var mouseCoordsX=(e.pageX - $imagePan.offset().left);
        var mouseCoordsY=(e.pageY - $imagePan.offset().top);
        var mousePercentX=mouseCoordsX/containerWidth;
        var mousePercentY=mouseCoordsY/containerHeight;
        var destX=-(((totalContentW-(containerWidth))-containerWidth)*(mousePercentX));
        var destY=-(((totalContentH-(containerHeight))-containerHeight)*(mousePercentY));
        var thePosA=mouseCoordsX-destX;
        var thePosB=destX-mouseCoordsX;
        var thePosC=mouseCoordsY-destY;
        var thePosD=destY-mouseCoordsY;
        var marginL=$imagePan_panning.css("marginLeft").replace("px", "");
        var marginT=$imagePan_panning.css("marginTop").replace("px", "");
        var animSpeed=500; //ease amount
        var easeType="easeOutCirc";
        if(mouseCoordsX>destX || mouseCoordsY>destY){
            //$imagePan_container.css("left",-thePosA-marginL); $imagePan_container.css("top",-thePosC-marginT); //without easing
            $imagePan_container.stop().animate({left: -thePosA-marginL, top: -thePosC-marginT}, animSpeed,easeType); //with easing
        } else if(mouseCoordsX<destX || mouseCoordsY<destY){
            //$imagePan_container.css("left",thePosB-marginL); $imagePan_container.css("top",thePosD-marginT); //without easing
            $imagePan_container.stop().animate({left: thePosB-marginL, top: thePosD-marginT}, animSpeed,easeType); //with easing
        } else {
    $imagePan.bind("mousemove", function(event){
$(window).resize(function() {

The markup

<div id="outer_container">
    <div id="imagePan">
        <div class="container">
            <div><img src="a-big-image.jpg" class="panning"></div>

As with everything, you can change it, optimize it and pretty much use it anyway and anywhere you like. If you use it on a project of yours, it would be cool to let me know :)


Post a comment
  1. cibcg
    Posted on August 3, 2014 at 14:44 Permalink

    tanks alooooooooot admin

  2. cms
    Posted on February 25, 2014 at 12:19 Permalink

    I needed this code tanx a lot

  3. قیمت لاستیک خودرو
    Posted on November 19, 2013 at 00:47 Permalink

    Good site!
    Good lock

  4. mediahub
    Posted on August 26, 2013 at 08:59 Permalink

    Nice code, is it works or compatible with touch device like smartphone or tablets?

  5. newwebsitethemes
    Posted on August 26, 2013 at 08:56 Permalink

    Love this effects, now trying to make some different position, thanks for the great tips.

  6. rjgamer
    Posted on July 24, 2013 at 08:32 Permalink


    great code! Thanks dude!

    I’ve question: I want the mouse outside of the div for moving the image. I’ve changed this code:
    $imagePan.bind("mousemove", function(event){ MouseMove(event); });
    to this:
    $('body').bind("mousemove", function(event){ MouseMove(event); });

    But my change worked not correct. What have I to change?

    Thanks for helping.

  7. Alicia
    Posted on April 30, 2013 at 10:14 Permalink

    Hey, nice script

    I was wondering if it’s possible to change the code for viewing on smartphones & tablets so that the user can drag instead of hover?

  8. Alicia
    Posted on April 30, 2013 at 10:14 Permalink

    Hi there, great script!

    I was wondering if it’s possible to change the code for viewing on smartphones & tablets so that the user can drag instead of hover?

  9. Dean
    Posted on February 20, 2013 at 00:49 Permalink

    Thanks for a great script it is the perfect answer to what I was looking for.
    I have impleted your script on a page of a website of mine to allow users to move a map around. I hope to eventually use it on photographs of mine.

    I am trying to understand how I can get the script to work on a page that resizes depending on what size screen the viewer is using and even how to implement it on a page with a header and a footer and the usaual menu buttons.

    I take my hat off to people who understand HTML, Java and CSS as I have to rely on WordPress themes and Dreamweaver. Having said that I still can’t get Dreamweaver to do what I want hence the switch to WordPress, apart from the page with the map.

    Okay I’m off to the library to get a book on the subject!

  10. anija
    Posted on January 23, 2013 at 16:36 Permalink

    Hi! Thank you for this code :)
    i’m using it with outside container fixed at 100% width and 100% height (a fullscreen image zoom) but i’ve a problem on the left side: when mouse reach position 0, the image is shifted on the right of about 200px, instead vertical movements are fine, and i just can’t realize why…

  11. DongDongFace
    Posted on May 18, 2012 at 05:42 Permalink

    Fix ie6 display Bug:
    find line :
    var easeType="easeOutCirc";

    replace to:

    var easeType="easeOutCirc"; if ($.browser.msie && $.browser.version.substr(0,1)<7) {$imagePan_panning.css("margin-left","0px").css("margin-top","0px");}// fix ie6

  12. Alan
    Posted on May 2, 2012 at 22:35 Permalink

    Hi. Thanks for this great script. I have used it on the Berndt Museum site for a virtual exhibition, using Lasso to build the clickable links by pulling information from the filemaker database. Check it out at http://berndt.uwa.edu.au/panorama.lasso?panID=1. Thanks a million!

    • malihu
      Posted on May 2, 2012 at 23:53 Permalink

      Awesome! Thank you for using the script and for your comments Alan :)

  13. phonecluster
    Posted on April 27, 2012 at 13:05 Permalink

    Yes, I’m looking for this wonderful effect, thank you so much, great job.

  14. Dary
    Posted on April 5, 2012 at 04:14 Permalink

    Hi there,

    this looks great but do you have any idea how i can get it work for indexhibit by any chance?

  15. Kasimir
    Posted on March 27, 2012 at 13:23 Permalink

    For those looking for an image panning script that supports multiple images, here’s some code. It works a bit different than Malihu’s, in that it only requires you to have images with a ‘pan’ class. The javascript will wrap divs around them and event listeners for mouse movement.
    Style the divs like above, only note that I’ve used different div class names and these are class names instead of id’s, because you’re using multiple images. Thus: #outer_container = .wrap_pan-image, #imagePan = .pan-image and .container = .img-container

    So, html:

    And javascript:

    $(window).load(function () { $('img.pan').wrap('').wrap('').wrap(''); $.each($('.wrap_pan-image'), function () { var img = $(this).find('img'), imgW = $(img).width(), imgH = $(img).height(); $(img).css('margin-top', ($(this).find('.pan-image').height() - imgH) / 2 + 'px'); $(this).find('.pan-image .img-container').css('width', imgW).css('height', imgH); $(img).css('margin-left', ($(this).find('.pan-image').width() - imgW) / 2).css('margin-top', ($(this).find('.pan-image').height() - imgH) / 2); $(this).find('.pan-image').bind('mousemove', function(event){ MouseMove(event, $(this).parent(), imgW, imgH); }); }); }); function MouseMove(e, el, imgW, imgH){ var containerWidth = $(el).find('.pan-image').width(); var containerHeight = $(el).find('.pan-image').height(); var mouseCoordsX = (e.pageX - $(el).find('.pan-image').offset().left); var mouseCoordsY = (e.pageY - $(el).find('.pan-image').offset().top); var mousePercentX = mouseCoordsX / containerWidth; var mousePercentY = mouseCoordsY / containerHeight; var destX = -(((imgW - (containerWidth)) - containerWidth) * (mousePercentX)); var destY = -(((imgH - (containerHeight)) - containerHeight) * (mousePercentY)); var posA = mouseCoordsX - destX; var posB = destX - mouseCoordsX; var posC = mouseCoordsY - destY; var posD = destY - mouseCoordsY; var marginL = $(el).find('img').css('marginLeft').replace('px', ''); var marginT = $(el).find('img').css('marginTop').replace('px', ''); var animSpeed = 500; var easeType = 'easeOutCirc'; if (mouseCoordsX > destX || mouseCoordsY > destY) { $(el).find('.pan-image .img-container').stop().animate({left: -posA - marginL, top: -posC - marginT}, animSpeed, easeType); } else if (mouseCoordsX < destX || mouseCoordsY < destY){ $(el).find(&#039;.pan-image .img-container&#039;).stop().animate({left: posB - marginL, top: posD - marginT}, animSpeed, easeType); } else { $(el).find(&#039;.pan-image .img-container&#039;).stop(); } }

    • Kasimir
      Posted on March 27, 2012 at 13:29 Permalink

      Seems the html is cut out of the code blocks. It should read (replace percentage symbols with opening and closing brackets):

      So HTML:

      So HTML: %img src="bla.jpg" class="pan" /%



      should be:

      $('img.pan').wrap('%div class="wrap_pan-image" /%').wrap('%div class="pan-image" /%').wrap('%div class="img-container" /%');

      • Petipain
        Posted on July 13, 2012 at 10:38 Permalink

        Hi Kasimir, thanks for your version of this script, it helped me a lot :)

        Still I have a strange problem, which seems to come from the “pan-image” div position.
        Cool effect, but not really on purpose : clik here to see

        Any idea how I can fix this ?

        • Petipain
          Posted on July 13, 2012 at 11:07 Permalink

          Ok, found my mistake : I didn’t get that the javascript function wrap () replaced the previous html structure. I left the whole set of imbricated divs in my html document, which made me have a double imbricated set…

          Thanks again for the script :)

    • ressia
      Posted on February 19, 2014 at 07:36 Permalink


      I’ve tried using this for multiple images but I failed.
      I get error message.

      Should I just copy the code?

      Thank you

  16. Nacho
    Posted on February 3, 2012 at 13:58 Permalink

    Thank you so much, i’ve been googling for ages something like this. Many similar things, but this is exactly what i was looking for :)

  17. ArleyM
    Posted on January 6, 2012 at 19:06 Permalink

    Is it possible to mouseover Image A and have Image B do the panning (like a mouse over for detail view functionality)?

    • Chumtarou
      Posted on January 6, 2012 at 21:17 Permalink

      Hi ArleyM, this panning code by Manos is excellent for what it currently does. Perhaps you are looking for something like this instead

  18. Chumtarou
    Posted on January 3, 2012 at 01:45 Permalink

    Sorry, please ignore my comment. I have placed the overlaying text div within the “imagepan” div giving the panning function for the entire image area. ‘Coffee’ is on me :-)

  19. Chumtarou
    Posted on January 2, 2012 at 21:32 Permalink

    Wonderful script – thank you and looking forward to donating soon. I’m testing it out to see if it works well for my project and have one question: would it be possible to control the panning from a smaller div than the image full container? For example, suppose the image is 1000×1000, the container is 600×400 but a smaller div for example 60×40 inside controls the panning. The reason is I’d like to overlay text above the image but be able to control the full image from a smaller area since the overlaying text stops the panning function. Sorry for the long comment – hope this question makes sense :-) Thank you in advance

  20. hardy
    Posted on December 20, 2011 at 21:18 Permalink

    thanx for that gorgeous script. make use of it @ http://www.leitbilder.net. was not to easy to figure out how to manage different images ($(window).load();). anyway still mysterious behavior with safari 5.0.x and 5.1. x (ff, chrome, opera etc work fine) . 3 of 4 times the new image will not placed properly. offline everything is fine just online it’s tricky. any idea? thanx again and thank you for any tips regarding safari ( sure its my fault, not safaris). btw any idea to have the video fluid?


    • hardy
      Posted on December 21, 2011 at 12:51 Permalink

      did it. safari is to fast (or to slow). have to wait for some millisec to preform that window.load thing. anyway thank you again

  21. ahmad balavipour
    Posted on October 31, 2011 at 12:37 Permalink

    Thanks alot, very good tutorial

  22. Frantisek
    Posted on October 29, 2011 at 18:41 Permalink

    Hi, your script is pretty cool, but I’m wondering if its possible somehow edit it to work with multiple images on one page? I dont want you to do it, I just need an advice, because Im JQuery newbie :)


  23. Dimitris
    Posted on September 22, 2011 at 15:05 Permalink


    πολύ καλή δουλεία…
    μήπως υπάρχει καποια ιδέα τί να κάνω στην περίπτωση που έχω περισσότερες απο μια εικόνες..? βάζοντας ένα next κ ένα back …?

    • malihu
      Posted on September 22, 2011 at 15:57 Permalink

      Γεια σου Δημήτρη,
      Είναι διαφορετική διαδικασία και αρκετά πιο περίπλοκη η δημιουργία ενός mini-gallery. Μπορείς αν θες να δεις ένα gallery script όπως αυτό: http://manos.malihu.gr/simple-jquery-fullscreen-image-gallery και να ενώσεις τα 2 script, αλλά οπωσδήποτε χρειάζεται γνώσεις σε css και jquery.

  24. Rob
    Posted on August 21, 2011 at 08:22 Permalink

    Hi! Do you have a modified version of the script for IE 8 and 7? Cause the script doesn’t work on these versions of IE. Great great script by the way! :D Love it!

  25. Rob
    Posted on August 8, 2011 at 11:02 Permalink

    Really great script mate!! Really really useful!

  26. Justin
    Posted on June 20, 2011 at 00:58 Permalink

    Hi Malihu,

    You’ve got a really awesome site here, spent a while just browsing it checking out scripts.

    I have a bit of a problem, I’ve a plugin(http://jquery.malsup.com/cycle/) to do a simple cycle through some images, but each of them needs to pan which is where your script comes in.
    It works fine on the first image, then when I go to the click next it works for a second then the whole images starts moving, interestingly if I hit the previous button and go back to the first image the first image still works.

    Any ideas?
    Also I’m using jquery 1.6.1 which seems to make the panning a bit jerky in ie8

    I’m still working on this site so it’s not online yet, but I can put it up somewhere if it helps.

    Any assistance would be highly appreciated :)

    • Dave
      Posted on June 19, 2011 at 04:34 Permalink

      Sorry, made a mess of last post, with link and not putting in mark up.
      Anyway, mark up

      div id=”outer_container”
      div id=”imagePan”
      div class=”container”
      div class=”sun”>

    • Vanessa
      Posted on September 14, 2012 at 16:53 Permalink

      Hi Dave,
      May you help me with your code? it’s working very well but I would like the image to be resized as long as the browser window is resized… is it possible? mantaining the width and height 100% of browser window.
      I dont know if I was clear about this….

  27. Mary
    Posted on June 3, 2011 at 21:52 Permalink

    Love this — it’s working great for me! I just need to tweak the speed of the panning. How would I go about making the image pan slower in relation to the mouse? Thanks!

    • Mary
      Posted on June 3, 2011 at 23:22 Permalink

      Never mind, I think I figured it out! I was changing the animSpeed but was making it smaller when I should I have been making it bigger. Great plugin malihu!

  28. michelle
    Posted on June 1, 2011 at 08:20 Permalink

    This is great love it… but was wondering is it possible to have another image at the background that can pan with different speed like in http://kalendiar.lenm.cz/ ?

    • malihu
      Posted on June 1, 2011 at 13:41 Permalink

      @2046 @michelle
      Not as it is. I need to update the script a bit to add these features. If you have time though, you can use the plugin at http://manos.malihu.gr/jquery-thumbnail-scroller with some additional css rules to pan an image. I’ll try to find some time to do it and I’ll post it here ;)

  29. 2046
    Posted on April 27, 2011 at 17:57 Permalink

    Is there way how to have multiple images on one page, where only one image that has mouse over moves?


  30. Dan
    Posted on April 20, 2011 at 13:44 Permalink

    malihu, can you please show me how to implementing image maps w/ links?
    can you give me a hint?

    thank you

  31. Dan
    Posted on April 13, 2011 at 12:59 Permalink

    it is possible to implement image map/hot spots with hyperlinks?

    • malihu
      Posted on April 13, 2011 at 13:29 Permalink

      Yes, there shouldn’t be any problems implementing image maps w/ links :)

  32. David Luiz
    Posted on April 13, 2011 at 08:49 Permalink

    no, i want the pixel pattern to stay on top…don’t pan.. but overlps the panning image.. ive an exmaple here click on image and see panning..


    Pleas ehelp.. thanks.

    • malihu
      Posted on April 13, 2011 at 09:22 Permalink

      You would need to add the overlay div below .container div (inside #imagePan) and give it an absolute position. You’d probably need to change .container position to absolute as well or/and give your overlay div a greater z-index.

  33. David Luiz
    Posted on April 11, 2011 at 06:19 Permalink

    Hi, really nice stuff… but i want to ask something… i want to add an overly like we see on full screen galleries. i mean the pixel overlay…i tried to add div after outer container and add pixel pattern as image bg with repeat.. but somehow the images dosent pan.. i think it’s messing with JS..
    Can you help please..

    • malihu
      Posted on April 13, 2011 at 08:06 Permalink

      You need an extra image on top of the one that pans? Will that extra image also pan?

  34. phil
    Posted on March 30, 2011 at 15:59 Permalink

    Hi is there a way to set the image to start of on the top right, instead of bottom right. im using a large image as the image and it starts off on bottom right, how can i set it to strat top right

    • malihu
      Posted on April 13, 2011 at 08:15 Permalink

      The image’s initial position is and should be centered (horizontal and vertical).
      To change it, find “$imagePan_panning.css(…” inside the script and remove/comment it. On window resize, image position is also reset ($imagePan_container.css(“top”,0).css(“left”,0);), so you may wanna change this as well if you need it bottom/right.

      • ramakant
        Posted on February 11, 2013 at 15:27 Permalink


        I’ve the same query as above.
        I’m not a script writer.
        Could you please clearly explain it?

        Thank you very much.

  35. Jes
    Posted on February 10, 2011 at 17:19 Permalink

    This is just what I needed, thanks! I’ll show you where I’m using it once I get the greenlight :)

  36. g.G
    Posted on February 8, 2011 at 14:01 Permalink

    would be possible to apply the panning effect to the div’s background image, so that i can have some text on top of it?
    thank you
    great job, with all of your scripts!

    • malihu
      Posted on February 8, 2011 at 14:52 Permalink

      You could add another absolutely positioned div inside #outer_container with greater z-index and 100% width/height and add your text inside it. This way the text containing div would be on top of the panning image.

      • g.G
        Posted on February 8, 2011 at 15:08 Permalink

        great! thanks for the quick reply! keep up the great work here :)

  37. ibuku
    Posted on February 7, 2011 at 23:18 Permalink


    i do love your work. I understand that most people dont care about IE anymore but with clients, it is always a concern. the panning effect does some wierd things in ie6. Do you have a possible fix for this?


    • malihu
      Posted on February 8, 2011 at 13:07 Permalink

      Ah, sorry but I never check any of the things I do in IE6, so I have absolutely no idea what could be the problem. I understand that a client might request it but it’s a conscious decision of mine not to develop or support old browsers like IE6.

  38. Brett Widmann
    Posted on January 1, 2011 at 03:23 Permalink

    This was really helpful! Everything works great.

  39. reed
    Posted on November 27, 2010 at 00:13 Permalink

    Hello malihu – superb clean code, with a responsive feel!

    Have you considered turning this elegant snippet into a simple image gallery? I’ve looked without success for a jQuery gallery with panning functionality – it would be a wonderful tool for novice coders like myself –

    thanks again for your reliably crisp code!

    • malihu
      Posted on December 12, 2010 at 16:02 Permalink

      Hello and thanks for your comments :)
      I might try making one when I get some time. Do you have any specific idea of its functionality?

  40. reneechung
    Posted on November 24, 2010 at 09:41 Permalink

    Is it possible to have panning the fading effect together? By the way, love it!

    • malihu
      Posted on November 24, 2010 at 09:55 Permalink

      Thanks! How do you mean?

      • reneechung
        Posted on December 8, 2010 at 09:41 Permalink

        Hi there,

        I want to have more than one image in the container and have them fade in and out while at the same time when a particular image is being displayed, the panning effect will be applied to it. I hope you can understand what I mean. Thanks.

  41. Michael
    Posted on September 3, 2010 at 00:07 Permalink

    Very nice one. Thank you for sharing all those beautiful code :)

  42. rojes
    Posted on September 2, 2010 at 06:25 Permalink

    help me please how to embed it at web page?

    • malihu
      Posted on September 2, 2010 at 10:18 Permalink

      Download the script. Inside the .zip file there’s the html file that you can open with a text editor and see the code.


Post a comment

Your e-mail is never published nor shared. Required fields are marked *

You may use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
You can write or copy/paste code directly in your comment using the <code> tag:
<code>code here...</code>