Autoscale, center an image with overlaid elements

The Problem

I recently had an interesting web layout problem.  I needed show a picture in the center of an area on the screen.  That’s normally pretty easy, but I also had a few extra requirements:

  1. The image should expand proportionately to cover as much of the stage as possible.
  2. The image should not scale any larger than a given size.
  3. I needed to overlay elements on top of the image (a hotspot in my case) that scales proportionately and retains the same relative location.

At first glance the answer would be to use some absolute or relative positioning and use a background-image with the background-size:cover (at least in modern browsers).  I did need to support IE7, which hurt that approach, but the requirement to overlay an element and scale it was also an issue.  When using background-size:cover, the element isn’t forced to stay proportional, just the image maintains proportions.  I needed to keep the actual element proportional too or I wouldn’t know where to put the overlaid element.

The Layout Approach

The answer does require some JavaScript, but CSS can get us halfway.  Here is the layout we need:

layout

HTML

So let’s set up the HTML (we won’t worry about the footer – just leave space for it:

<div id="stage"> <div id="imageHolder"> <img src="SomeImage.jpg" />

<div id="hotspot"></div> </div> </div>

CSS

The approach in CSS is to get the stage filling its area using absolute positioning. 

#stage { position:absolute; top:0px; bottom:38px; right:0px; left:0px; padding:0; background-color:Black; }

The imageHolder is also set to use absolute positioning and has its max-width and max-height set to the size/proportion we want, but the actual positioning will be done in JavaScript.

#imageHolder {
    position:absolute;
    max-height:720px;
    max-width:920px;     
}

And the image and placeholder are setup for absolute positioning.  The image is styled to fill the stage, and the hotspot is styled using percentages for position and size so that it will scale with the image:

#imageHolder img { position:absolute; top:0px; left:0px; min-height:100%; width:100%; height:auto; } #imageHolder #hotspot { position:absolute; cursor:pointer;

top:22.1%;

left:50.5%;

width:44%;height:42.3% }

JavaScript

We create a resize function that will recompute how big the imageHolder should be and where it should be placed.

function resize() {
    //Get stage size (less any desired padding)
    var stage = $('#stage');
    var div = $('#imageHolder');
    var newHeight = stage.height() - 10;
    var newWidth = stage.width() - 10;
    

    //Constrain to proportioon
    var proportion = parseInt(div.css('max-height')) / parseInt(div.css('max-width'));
    if (newWidth > newHeight / proportion) {
        newWidth = newHeight / proportion;
    }
    if (newHeight > newWidth * proportion) {
        newHeight = newWidth * proportion;
    }

    //Set the height and width -- the max-height/width will contrain this
    div.width(newWidth);
    div.height(newHeight);

    //Center it
    div.css({
        "left": (stage.width() - div.width()) / 2 + "px",
        "top": (stage.height() - div.height()) / 2 + "px"
    });
}

And then when we load the page we just need to call the resize function and setup the window’s resize event to call it as well.

$(document).ready(function () { $(window).resize(function () { resize(); });

 

resize(); });

See it in Action

You can see this in action on JSFiddle at http://jsfiddle.net/tYY87/  (I just made a few changes there for the smaller screen size.)