Fleegix.org

Getting the scrollbar width in pixels

2006-05-30 22:42:00

Update: The code in this post is licensed under the terms of the Apache License, version 2.

Working on the new fluid layout code for Scooby, I had a seemingly intractable problem -- I needed to do percent-based side-to-side alignment of elements inside two div elements, one positioned directly above the other. The catch was that the lower div scrolled, and the upper one did not.

I tried two or three different things, but couldn't get around it -- ultimately I needed to set a horizontal offset on the top div that would be the same precise width as the scrollbar in the div below.

Interestingly, the irritatating IE bug of calculating the 100% width before adding scrollbars to a scrolling div makes this unnecessary -- all you have to do is set the same arbitrary offset for both div elements (as long as it's wider than any Windows scrollbar might be so you don't end up with content under the scroller).

For the well-behaved browsers, though, I just decided to do some hacking, and came up with something that reliably gives you the actual pixel width of the scroller. There is likely a better way to do it, but here's what I ended up with:

function getScrollerWidth() {
    var scr = null;
    var inn = null;
    var wNoScroll = 0;
    var wScroll = 0;

    // Outer scrolling div
    scr = document.createElement('div');
    scr.style.position = 'absolute';
    scr.style.top = '-1000px';
    scr.style.left = '-1000px';
    scr.style.width = '100px';
    scr.style.height = '50px';
    // Start with no scrollbar
    scr.style.overflow = 'hidden';

    // Inner content div
    inn = document.createElement('div');
    inn.style.width = '100%';
    inn.style.height = '200px';

    // Put the inner div in the scrolling div
    scr.appendChild(inn);
    // Append the scrolling div to the doc
    document.body.appendChild(scr);

    // Width of the inner div sans scrollbar
    wNoScroll = inn.offsetWidth;
    // Add the scrollbar
    scr.style.overflow = 'auto';
    // Width of the inner div width scrollbar
    wScroll = inn.offsetWidth;

    // Remove the scrolling div from the doc
    document.body.removeChild(
        document.body.lastChild);

    // Pixel width of the scroller
    return (wNoScroll - wScroll);
}

Okay, so it's fairly obvious and a bit brute-force.

All it does is add a couple of div elements to the document and actually measure widths with and without the scroller. But I was pretty excited to be able to grab that value correctly and reliably for Safari, as well as for Firefox on Linux and on Windows -- with both the XP "Hasbro" look and the old-skool Soviet-bloc style.

And of course, as you might guess, it's different everywhere. Yes, it is.


Comments

Scott (2006-06-19)
Thanks so much for providing the script. I was having exactly the same problem as you were: two div elements, one above the other, and the lower one scrolled. After a bit of searching, I came across this and my problem was solved. Thanks again! Scott


mde (2006-06-15)
Cool. I'm really glad this was able to help someone else out. It make me mind those browser differences a bit less when I can get an accurate picture of what they are.


Cathy (2006-06-12)
Thanks for sharing this script Matthew. It's solved a problem I was having with a liquid layout containing a pixel sized flash movie. I had to calculate the size of the flash parent element and use that value to work out how wide the flash movie should be displayed. In firefox using clientWidth was making the flash too wide - I just needed to minus the width of the scrollbar.


handan (2008-08-19)

This function has been modified by the OpenLayers from the original version, written by Matthew Eernisse and released under the Apache 2 license here:

http://www.fleegix.org- /articles- /2006- /05- /30- /getting-the-scrollbar-width-in-pixels

It has been modified simply to cache its value, since it is physically impossible that this code could ever run in more than one browser at once.


About

This is the blog for Matthew Eernisse. I currently work at Yammer as a developer, working mostly with JavaScript. All opinions expressed here are my own, not my employer's.

Related

Previous posts

All previous posts ยป

This blog is a GeddyJS application.