Getting the scrollbar width in pixels

Posted by mde [ Wed, 31 May 2006 03:42:00 GMT ]

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.