Last Updated: February 25, 2016
· javier_toledo

Creating a zoomable website with em units

Recently we've updated our company website (http://theagilemonkeys.com). When we were at the design table, a thing we wanted was that the experience of the site were the same regardless the size of the screen of our users. Not in the "responsive" way of media queries, but preserving the relative sizes of things whatever the actual size was.

So we had some time thinking on how to achieve that goal, and the idea that came to us was to set a "default" font-size for the body element and use font-size relative units like em to set every size or position, just in following way:

body {
  font-size: 10pt; // Any value here will be Ok, (spoiler alert: even none as it'll be set later by JS)

.example {
  position: relative;
  top: 10em;
  left: 1.89em; // Using floats allows extra-precision positioning
  width: 20em;
  height: 10em;

Once we finish our website using font-size relative units we can test how it works opening the website with our browser's inspector and manually changing the font-size of the body element. Bigger values will act as a zoom-in and lesser ones like a zoom-out, so everything is ready, we just have to make it live.

You can take the screen size of the machine used to develop the website as reference for the 1:1 scale, for example, the viewport size of a chrome window in Mac OS X is 1440x779px. Knowing this we can make a simple JavaScript function to calculate the scale for the current window size:

function zoom() {
  var $window = $(this),
      relX = ($window.width() / 1440), //We use our screen size as scale reference
      relY = ($window.height() / 779),
  if (relX < relY) { //Always select the scale from the most shrinked axis
    rel = relX;
  } else {
    rel = relY;
  $("body").css("font-size", "" + (10.0 * rel) + "pt"); // Here you use the default size you chosen for the body

  $(window).resize(zoom); // Set a listener to call zoom whenever the window is resized
  zoom(); // Call zoom after page is loaded

And that's all! Simple, DRY, effective and unobstrusive. While you don't resize the screen nothing will be executed and when you do most of scale work will be automagically made by CSS. The first time I saw it working it was like, "hey we've created a flash website with HTML, cool!".

Please leave us your comments, we'll love to hear your ideas to achieve the same goal in better ways :-)

Update: As @avetisk and then @jessewilliamson noticed, using this technique over the body tag can disable the native zoom of the browser, which can be considered an accesibility issue. As soon as I can, I'll try to improve this code to address that problem and update this post with the fix.

6 Responses
Add your response


Nice technique Javier, thanks for sharing. :)

over 1 year ago ·

you're welcome :-)

over 1 year ago ·

Actually, that's a very bad idea.

For instance, on your website (http://theagilemonkeys.com/) if someone wants to change the font size (native zooming), they'll come to the very disappointing evidence that it is impossible.

Such minimal accessibility features of the browser should always be kept as they are.

over 1 year ago ·

Hi @avetisk, thanks for your comment, the website is a work in progress and this issue and many others will be addressed in a near future. Anyway I wouldn't call it a "very bad idea", it's just an idea that could be useful in some use cases :-)

over 1 year ago ·

From a usability and accessibility perspective I'm with @avetisk. Resizing the browser window on the site makes certain bits of text unreadable. That being said, I think it's a cool idea, and it looks nice when you see it working.

over 1 year ago ·

Yes, I'm with you both on this to be an issue, I had no time yet to figure out a fix, but I'll do it eventually and then update this post accordingly ;-)

over 1 year ago ·