Photo detail zoomer with jQuery

Magnify screenshot

One of the frustrating things about Web images is that they are often too small. There are several ways to deal with this - lightbox, for example, which displays a larger image on top of the page.

In this article I'm going to discuss a way to enable zooming in on just part of an image. For me, there's something fascinating about being able to zoom in on the faces in a group photo or getting in close enough in a painting to see the brush strokes.

In this demo, which I named "Magnify," there is a small rectangular area that can be dragged around over the image on the left. The area inside it is enlarged and displayed in the area to the right, as shown above.

You can check out a working* demo here. (*Right now it's not working in IE - surprise, surprise! I will be trouble-shooting this later.)

Complete source code: HTML, CSS, and JavaScript.

This is accomplished with a surprisingly small amount of code. In the HTML document head, we call our stylesheet and load jquery.js, jquery-ui-1.8.1.custom.min.js (which contains the draggable plug-in), and our custom script, myscript.js, thus:


<link rel="stylesheet" href="style.css" type="text/css" media="all" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery-ui-1.8.1.custom.min.js"></script>
<script type="text/javascript" src="myscript.js"></script>

Then in the body of the HTML, we have the divs that hold our images. For each image, there are two versions: the small image (400 px wide) that we see in the box on the left, and the large image (1600 px wide) for the box on the right. (The large image is 4 time bigger than the small image, which gives us a 4x magnification.)


<div id="box1" class="box">
  <div id="magnifier"></div>
  <img src="images/renoirmoulinsmall.jpg" alt="Les Moulin by Renoir" class="small">
</div>
<div id="box2" class="box">
  <img src="images/renoirmoulin.jpg" alt="Les Moulin by Renoir" class="big">
</div>

We style these divs with this CSS, floating them so they line up next to each other. Two things to note:
1) Overflow is hidden - this causes only the part of the large image that is inside box2 to show.
2) Position is set to relative - it seems like this wouldn't be necessary since "relative" is the default position, but it's one of those quirky things in CSS. For the absolutely positioned magnifier div to be positioned correctly, its parent div (i.e. box1) must have its position explicitly declared.

The same quirk applies to #box1 img and #box2 img. It doesn't seem like the position attribute would be necessary, but if it is left out the viewer doesn't work.


div.box {
  width: 400px;
  height: 300px;
  float: left;
  border: 1px solid #333;
  padding: 0;
  margin: 24px 12px;
  overflow: hidden;
  position: relative;
}
div#box1  img {
  width: 400px;
  height: 300px;
  position: relative;
  top: 0;
  left: 0
}
div#box2 img {
  position: relative;
  top: 0;
  left: 0
}
div#magnifier {
  z-index: 99;
  margin: 0;
  padding: 0;
  display: block;
  position: absolute;
  top: 2px;
  left: 2px;
  width: 99px;
  height: 76px;
  min-width: 99px;
  min-height: 76px;
  border: 1px solid #f00;
  outline: 1px solid #ff0;
  background: none; /* the fallback if no rgba */
  background: rgba(200, 200, 200, 0.3);
}

I set the z-index of the magnifier div to ensure that it is always on top. I gave it a bright red border and a bright yellow outline so it will be visible on top of any picture. I set both width and min-width and height and min-height so it wouldn't collapse, as empty divs usually do.

OK. Now, on to the jQuery. It came from http://jqueryui.com/demos/draggable/.


  $('#magnifier').draggable({
    containment: 'parent',
    drag: function(event, ui) { 
      var xtop = (ui.position.top);
      var xleft = (ui.position.left);
      $('#box2 img').css('left', ((xleft * -4) + 'px'));
      $('#box2 img').css('top', ((xtop * -4) + 'px'));
    }
  });

In line one, we select the element with the id of "magnifier" and apply to it the jQuery ui function "draggable." Line two specifies that the magnifier stays contained within its parent, box1. In the drag function, we get the top and left positions of the ui parameter and multiply them by -4. (We use 4 since our magnification is 4x, and it's negative so the large image will move left as the magnifier is moved right.) In the last two lines, the position of the image in the div with the id of box2 is set by modifying the css properties top and left.

The astute reader will notice that there is more to the page, namely the photo chooser/switcher. But that will have to be covered in another article. It's on my to do list.