Responsive Web Design and Scrollbars: Is Chrome’s Implementation Better?
In my recent post, Is Your Responsive Web Design too Fragile?, I described an inconsistency between browsers when firing media query events:
- Chrome and Safari exclude the scrollbar dimensions.
- Firefox, Opera and IE include the scrollbar dimensions.
Assume we have a media query which detects a minimum width of 800px, e.g.
@media (min-width: 800px) { ... }
Chrome and Safari will include those styles when the body width is 800px or greater. However, if your OS shows vertical scrollbars with a width of 20px, other browsers would include the styles at 780px.
Let’s read the W3C media query specification for width:
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).
The Webkit engine is wrong. But is it better?
At first glance, Chrome’s implementation seems logical but it’s important to understand that ‘width’ refers to the viewport dimensions, i.e. the total area inside the browser window — not the page width. Using the assumptions above, Chrome’s viewport width is actually 820px (800px body + 20px scrollbar). In other browsers, the viewport width is 800px (780px body + 20px scrollbar).
Unfortunately, knowing the viewport width does not aid CSS development since you don’t know whether the scrollbar is visible or what its dimensions are. However, Chrome’s alternative is far worse since the introduction or removal of a scrollbar can trigger a media query. This is a little complex, so I’ll explain with an example:
- Assume you have a simple responsive site which shows a desktop layout at 800px or greater and a mobile site at 799px or less. Scrollbar widths are 20px.
- Currently, the user has their browser window sized to an 810px viewport width. The height is large enough to show the current page (in desktop layout) without scrollbars.
- You click through to another page. Here, the content is longer than the viewport height and a vertical scrollbar appears. This reduces the body width to 790px and Chrome instantly switches from the desktop to mobile layout. The user becomes confused and vows never to return to your site again.
The situation is exacerbated if you have dynamically generated content. If a page currently fits in the viewport and you display a status message which increases the height, the resulting vertical scrollbar will switch the user from desktop to mobile layout (which could show the message in a different location). Once the status message is removed, the page will return to the desktop layout.
Firefox, Opera and IE do not exhibit this behavior because the viewport dimensions never change unless the user resizes their browser window. However, Chrome and Safari users could experience different layouts just because your site has slightly more content on one page than another. Nasty.
Admittedly, this is an edge case:
- Mobile browsers do not normally display permanent scrollbars so the problem is never apparent on those devices.
- A desktop browser user would be unlucky to have window dimensions set at a point where layouts noticeably changed.
- You could prevent Chrome switching layouts by ensuring the vertical scrollbar is always visible, i.e.
body { overflow-y: scroll; }
.
That said, I consider it a valid reason for the Webkit and Blink teams to address the issue. I suspect media queries were implemented in Webkit before the syntax became a standard. However, we now have a W3C Recommendation; it makes sense to follow the finalized rules and provide a consistent experience for users and developers.