News    Current Issue    Archive    Forums    About    Links
Home    Home    Home

The Viewport

The area of your window where the contents are shown is called the viewport. When positioning a popup menu or something relative to the mouse cursor, it is very useful to know how big the viewport is without its scrollbars. With that information, you can make sure your positioned elements are completely visible.

I’ve tried to keep the code in the examples short and without any crossbrowser workarounds. So, to view the examples you will need a browser that supports a little of DOM level 1, and iframes.

width and height

Let’s start with an example that shows what might happen when you position an element without checking how large the viewport is.

Example 1: shows a div element when mousing over a link. The div is always positioned in the same place. If this example works the way I intended it, only part of the div is visible, the rest is cut off by the viewport’s edge.

The code for getting the viewport size is different across browsers. Here are the most commonly used properties:

document.documentElement.clientWidth
document.body.clientWidth
window.innerWidth - 18

document.documentElement.clientHeight
document.body.clientHeight
window.innerHeight - 18

Example 2: is a testcase where you can check how your browser handles these properties. (does not automatically open in a new window)

The document.documentElement.clientWidth/Height is used by IE6 in strict mode, otherwise it uses document.body.clientWidth/Height. Mozilla also uses document.body.clientWidth/Height and supports the Netscape 4 properties window.innerWidth/Height as well. Opera also supports window.innerWidth/Height, though it’s a little buggy there.

Note that window.innerWidth/Height does not exactly get the viewport size the way we want it, because these properties add the space for the scrollbar if it is visible. As far as I know, there is no reliable way to test if scrollbars are visible. Also, the size of scrollbars varies over different platforms and user settings, therefore we’ll take a safe bet and guess it at 18 pixels, and subtract that.

Now that we know what to look for, it’s easy to write a simple script that tries each property until it finds one that exists and has a non-zero value. Note that instead of browser sniffing, this code uses object detection:

getViewportWidth = function() {
  var width = 0;
  if( document.documentElement && 
  document.documentElement.clientWidth ) {
    width = document.documentElement.clientWidth;
  }
  else if( document.body && 
  document.body.clientWidth ) {
    width = document.body.clientWidth;
  }
  else if( window.innerWidth ) {
    width = window.innerWidth - 18;
  }
  return width;
};

getViewportHeight = function() {
  var height = 0;
  if( document.documentElement && 
  document.documentElement.clientHeight ) {
    height = document.documentElement.clientHeight;
  }
  else if( document.body && 
  document.body.clientHeight ) {
    height = document.body.clientHeight;
  }
  else if( window.innerHeight ) {
    height = window.innerHeight - 18;
  }
  return height;
};

Example 3: uses these two functions. It shows a div element when mousing over a link, and when the div is positioned there is a check to make sure it is placed inside the viewport.

Remember that these functions must be called after the page has finished loading. Because getViewportWidth() and getViewportHeight() access the body element, the body must have completed loading, otherwise the width and height readings may be wrong.

Example 4: shows how to center the div horizontally and vertically. By running the positioning function onresize, the div remains centered when you change the size of the window.

scrollX and scrollY

Knowing the size of the viewport is only half of the deal. What happens when the document is scrolled?

Example 5: shows a div bouncing between the left edge of the viewport and the right. When the document is scrolled, the div is no longer positioned where it was intended.

So what’s the problem? Well, the div was positioned relative to the top left corner of the document. When the document was scrolled, the top left corner moved as well. So to position the div element relative to the viewport, the amount of pixels scrolled must be added when setting the left and top of the div.

These are the different properties that give the scrolled distance of the document:

document.documentElement.scrollLeft
document.body.scrollLeft
window.pageXOffset
window.scrollX

document.documentElement.scrollTop
document.body.scrollTop
window.pageYOffset
window.scrollY

Example 6: is a test case where you can check how your browser handles these properties. (does not automatically open in a new window)

The above test shows that in compatibility mode, Explorer 6 has the scrolling information sitting on the body element while the values on the documentElement are 0. In strict mode, the situation is reversed: the scrolled values are found on the documentElement and the values on the body are 0.

All the other browsers that support a bit of DHTML also support at least one of the properties mentioned above, and they all give correct values for as far as I could check. Even Netscape 4 and Explorer 4 support these, so this is not just something for 5th generation browsers. It’s easy to write a simple script that tries each of these properties until it finds one that exists and is not 0:

getViewportScrollX = function() {
  var scrollX = 0;
  if( document.documentElement && 
  document.documentElement.scrollLeft ) {
    scrollX = document.documentElement.scrollLeft;
  }
  else if( document.body && 
  document.body.scrollLeft ) {
    scrollX = document.body.scrollLeft;
  }
  else if( window.pageXOffset ) {
    scrollX = window.pageXOffset;
  }
  else if( window.scrollX ) {
    scrollX = window.scrollX;
  }
  return scrollX;
};

getViewportScrollY = function() {
  var scrollY = 0;
  if( document.documentElement && 
  document.documentElement.scrollTop ) {
    scrollY = document.documentElement.scrollTop;
  }
  else if( document.body && 
  document.body.scrollTop ) {
    scrollY = document.body.scrollTop;
  }
  else if( window.pageYOffset ) {
    scrollY = window.pageYOffset;
  }
  else if( window.scrollY ) {
    scrollY = window.scrollY;
  }
  return scrollY;
};

Example 7: shows a div element bouncing between the left edge of the viewport and the right. Every time the position of the div is updated, there is a check to see if the document has been scrolled and an adjustment is made if necessary.

standardisation

As you may have noticed, the code shown in this tutorial cannot be found in any of the currently available W3C specifications. In fact, these techniques have not been standardised by the people of the W3C, and maybe they should not be expected to do that in the immediate future. The W3C is more concerned with XML, CSS and other technologies for accessibility and document structure, and a good deal more beside that. Measuring the size of the viewport of a window seems outside their area of interest, they are more concerned with the document in the viewport.

conclusion & credits

I’ve shown that it’s pretty easy to get the viewport width and height, but that some browsers give different readings because they handle scrollbars in another way. Regardless of the differences, these readings are still very useful. Getting the position of the scrolled content has solid support in many browsers.

The four example functions shown in the article were written so they would fit in the text. For the 13th API (the new library we’re working on) I’ve put all the functionality in one function with longer and fewer lines, because I find that easier to work with.

Finally, if you spot any errors in this article, or still have questions after reading it, please contact us in the forums. All feedback is much appreciated.

I would like to thank Garrett Smith (dhtmlkitchen) for the great help he has given to tweak this article for the Macintosh.

references

These are links to the official documentation from Microsoft and Mozilla.

CSS enhancements in Internet Explorer 6 documents how the Doctype declaration affects Explorer 6. This goes deeper into the differences between Strict and Compatibility mode.

There is also documentation in different places regarding the clientWidth, scrollLeft, innerWidth and pageXOffset properties.

examples

Here’s a list of all the examples used in this tutorial:

Example 1: shows a div element when mousing over a link. The div is always positioned in the same place.

Example 2: is a testcase where you can check how your browser handles the properties for getting the viewport size. (does not automatically open in a new window)

Example 3: shows a div element when mousing over a link. When the div is positioned, there is a check to make sure it is placed inside the viewport.

Example 4: shows how to center the div horizontally and vertically. By running the positioning function onresize, the div remains centered when you change the size of the window.

Example 5: shows a div bouncing between the left edge of the viewport and the right. When the document is scrolled, the div is no longer positioned where it was intended.

Example 6: is a test case where you can check how your browser handles the properties for getting the scrolled position of the content. (does not automatically open in a new window)

Example 7: shows a div element bouncing between the left edge of the viewport and the right. Every time the position of the div is updated, there is a check to see if the document has been scrolled and an adjustment is made if necessary.