Media Query width and vertical scrollbars
Media queries are a great tool for changing a website’s layout depending on parameters like viewport width, but it can be very annoying when browsers do not do the same thing. An obvious example is whether or not a vertical scrollbar, should one exist, is included when the viewport’s width is calculated.
I made a note about this two years ago in Media queries, viewport width, scrollbars, and WebKit browsers. In that post I also pointed to the following statement in the Media Queries specification:
The ‘width’ media feature describes the width of the targeted display area of the output device. For continuous media, this is the width of the viewport (as described by CSS2, section 9.1.1 [CSS21]) including the size of a rendered scroll bar (if any).
So it’s pretty clear what browsers are supposed to do. But in reality this varies. It doesn’t just depend on the browser and operating system but also on user settings. To find out what current browsers do, I created a simple Media Query width test document with a number of breakpoints and opened it in a lot of browsers.
I saw three different behaviours.
Scrollbar included in media query width
Many desktop browsers do include the scrollbar in the viewport width. Firefox, Opera, and Internet Explorer all do.
Scrollbar not included in media query width
As noted in the older article I linked to, desktop versions of Chrome, Safari, and other WebKit-based browsers do not include the vertical scrollbar in media query widths. It’s a bit more complicated than that though, which I’ll get into next.
Scrollbar included in media query width but not affecting content width
On Mac OS X 10.7 and newer, there is a setting in the General pane in System Preferences to show scrollbars only when scrolling. With that option selected, WebKit browsers do include the scrollbar in the media query width but only display it during scrolling, and when they do they display it on top of the content instead of beside it. Because of this the content area of the viewport is still a scrollbar wider than in other browsers.
This is also what the mobile browsers I have tested in do (various iOS devices and versions, Opera Mobile, Android 2.3.3 and 4.1.2).
Is this going against the Media Queries specification? I’m not sure. The scrollbar is included in the width, after all, but I’m wondering if this is something the CSS Working Group thought of when producing the spec.
Mostly not a problem, but it can be
So how does this affect you as a web developer? As an example, let’s take a look at the excellent Responsive Design View in recent versions of Firefox. It includes the vertical scrollbar in the viewport width, but it displays the scrollbar as soon as the content doesn’t fit vertically, not just when you scroll. This means that if you use it to check how your design works in mobile-sized viewports you will not get exactly the same result around breakpoints as when checking on a real device or in a simulator or emulator.
The same thing happens if you use Safari or Chrome on your desktop computer (unless you’re using a Mac with OS X 10.7 or later and have configured scrollbars to only appear when scrolling).
Most of the time this difference is not really a big issue to web developers and may not even be noticeable, provided that you use flexible responsive design. But if you use fixed breakpoints with fixed layout widths and/or have content that has an intrinsic width and requires pixel-perfect breakpoints, you need to know about this difference. I can think of three ways to approach this:
- Somehow (likely by browser sniffing, hmm) detect if the browser includes the scrollbar in the media query width
- Make your fixed breakpoints trigger at wider widths to account for a vertical scrollbar to avoid a horizontal one in browsers that include the scrollbar width and always display it
- Make your layout and content widths flexible so the difference doesn’t matter (as much)
My preference here is definitely to go with option 3. However, I have been handed designs that really can’t handle flexibility very well, in which case option 2 is the way to go. Option 1 is out for me, unless there is a better way than using old-fashioned, error-prone browser sniffing.
And what would a better way be? Maybe if you could include a check for scrollbar behaviour in media queries, like this:
@media only screen and (max-width:768px) and (vertical-scrollbar:[inside|outside|on-top]) {
/* Rules here */
}
But then to make that useful you’d still need to know the width of the scrollbar (which may depend on the OS) when it isn’t rendered on top of the content area, so I’m not sure it would help all that much.
- Previous post: The mysterious WebKit placeholder overflow bug
- Next post: CSS background-position and percent