Combining media queries and JavaScript

On Tuesday Jason Grigsby challenged the conventional view that media queries are all we need to make a website mobile-friendly. Although he’s right when he points out some serious problems, I do not think that media queries are the “fool’s gold,” as Jason says. The message seems to be more that media queries alone are not enough to make your sites mobile-friendly. An additional component is required.

To recap briefly, this is a media query:

.sidebar { float: right; width: 250px; } @media all and (max-device-width: 600px) { .complicatedFunctionality { display: none; } .sidebar { float: none; width: auto; } }

The media query asks whether the width of the device is 600px at maximum. If it is, the special styles are executed. This usually comes down to hiding advanced functionalities that do not make sense on mobile or take too much bandwidth, while it can also be used to change the site’s grid from horizontally oriented to vertically oriented; for instance by placing a sidebar not right of the main content, but below it.

Technically, the .complicatedFunctionality and .sidebar declarations are added to the style sheet only when the query returns true, i.e. the device is less than 600px wide.

Now this works. Better still, media queries are the ideal way of adapting your design to different screen resolutions. Still, they are not the be-all-end-all of making your website mobile-friendly.

Jason identifies two main problem areas:

It’s all very well to hide, say, an advanced mapping application on mobile, but if you use only media queries the browser will still download the scripts associated with the application.

Even though images might be hidden from mobile browsers, or low-source ones should be used, the browser still downloads the full-source variants.

In other words, media queries do not stop the browser from downloading assets that will not be used on a mobile phone. And with bandwidth at a premium, this is a serious problem.

He concludes:

CSS media queries are a tool, but they are not a silver bullet.

I mostly, but not entire agree. Media queries are silver bullets when it comes to pure CSS. Restricting the width of your site, moving sidebars and main navigations elsewhere, media queries can do all that and more.

The trick, however, is that a pure CSS approach is not enough. In addition we need a JavaScript that also reads out the media queries and uses the data to decide whether to download the complicated mapping script, whether to download the low-source or the full-source images, or possibly none.

As far as I know there is no direct access to media queries from JavaScript. You can’t read out whether the example media query above has fired or not.

JavaScript pairing

Fortunately, there is a pretty safe way of using JavaScript in conjunction with media queries. It turns out that all browsers I tested so far have paired the width and device-width media queries with the values of document.documentElement. clientWidth and screen.width , respectively.

This is a general rule. All mobile browsers that support media queries exhibit these pairings. It’s hard to believe, but I haven’t found any exceptions yet — and rest assured that I searched for them, because I could not believe that it would be this simple. And I will continue to keep an eye on this and report problems as soon as I find them.

One caveat, though: although the pairing exists in all browsers, some browsers report incorrect values for document.documentElement. clientWidth and screen.width . However, these browsers will also fire media queries based on these incorrect values, so the net result remains that both media query and script are executed, although at the wrong time. See the viewport compatiblity table for the gory details.

Therefore, if we want a JavaScript component that fires when the example media query above is triggered, we simply do:

if (screen.width < 600) { // don’t download complicated script // use low-source images instead of full-source ones }

I think it’s best to reverse the script logic:

if (screen.width >= 600) { // download complicated script // swap in full-source images for low-source ones }

If you want to use width instead, do this:

@media all and (max-width: 900px) { // styles } if (document.documentElement.clientWidth < 900) { // scripts }

Thus it is quite possible to pair a JavaScript routine with your media queries, and use it to decide which assets you should and should not download.

When these scripts are added to media queries, we’re a whole lot closer to making one website that reacts to a mobile (or rather, a narrow-screen) environment both in its CSS and in its asset management.

Comments are closed.