Return to Firewoiks

Extensions, resources & tutorials for Fireworks, Dreamweaver & HTML5 / CSS3 by UI developer, .

Your Media Queries are Wrong. Fix them with Viewport Genie and mqGenie

Posted: January 29 2013

Alarmist? Perhaps. Truthful? Yeah.

A few weeks ago I realised that WebKit browsers are the only ones that don't include scrollbar widths in the viewport size for media queries. While this is technically incorrect, it makes more sense to me since scrollbar widths vary across platforms and in the case of “mobile” don't exist. Roger Johansson also noted this a year ago and, interestingly, just recently posted a follow up: Media Query Width and Vertical Scrollbars.

Now, if you build “responsively” and fluidly, this isn't generally a big deal. However, in my most recent project, the media queries I'd written while developing in Firefox were occuring too early (by 17px) on mobile and Chrome/Safari - causing layout issues. Similarly, any media queries written while developing in WebKit browsers fire too late on every other desktop browser.

So, I've written two platform-agnostic, vanilla JavaScript “plugins” to help combat this issue: Viewport Genie and mqGenie.

Viewport Genie

Viewport Genie is available as a bookmarklet or JavaScript plugin and adds the “real” (without scrollbars) viewport size (in both px and em) as a fixed element at the top of the page to help with obtaining values for responsive breakpoints. You can select the content to copy in to your stylesheets and the ems are based on the actual font-size of the html element, not fixed at a 16px base.

Remember, if you use em-based media queries, you should never reset/change the font-size on <html>, otherwise they'll fire at unexpected sizes; em-based media queries only respond to the browser's default font size, which is generally 16px unless changed by the user.

When using the bookmarklet, running it again will remove Viewport Genie from your page. If using the plugin, you activate it by adding a querystring parameter of ?genie=true to the url. At around only 800 bytes minified and gzipped, it's safe to include in your projects without worry.

I recommend combining Viewport Genie with your other main JavaScripts, before the closing </body> to reduce http requests.

Now, the “real” viewport size is meaningless in most desktop browsers, unless you use my next plugin…

mqGenie

In non-WebKit browsers, mqGenie adjusts the media queries found in CSS by the width of the scrollbar so they fire at the intended size. If not already set, mqGenie first forces overflow-y: scroll on <html> to produce a vertial scrollbar (if appropriate). If you're not already doing this anyway, you should, so that short pages in your site don't shift position when browsing between them. mqGenie also adjusts em-based media queries using the actual font-size of the html element, not fixed at a 16px base.

It returns a JavaScript object called mqGenie, which contains the following properties:

A second function, mqAdjust, is made available, which uses the mqGenie object to allow you to re-calculate media queries that are written in JavaScript. Simply pass mqAdjust the media query string and it will return one that's adjusted appropriately.

Consider mqGenie as a progressive enhancement. If it's not used then it shouldn't matter too much, but with it, your media queries will fire consistently across all browsers and devices. Again, it's only around the 800 bytes mark when minified and gzipped.

I recommend combining mqGenie with your other small, “utility” scripts, such as Modernizr, in the <head>.

What now?

Ok, so that's a lot to take in. The best thing to do is view some demos to see it in action:

In the two demos above, the #content element and the console will update accordingly showing which media queries are being matched. The console will also show the media queries after being mqAdjusted.

A good test browser is Firefox as it has a Responsive Design View and does not respond to Mountain Lion's scrollbar preferences. You'll notice that in the first demo, the breakpoints will trigger at what Viewport Genie determines as the “real” viewport width, not what Responsive Design View reports.

Convinced? Get the code!

Like the good community citizen I am, both plugins are freely available on GitHub. The GitHub repos also have instructions.

Honourable mention

I can't write this post and these plugins without mentioning, Nicky Williams. On my “eureka day” I tweeted, asking: “Is it possible with JavaScript to get a list of all the media queries applied to a page/in a stylesheet & change them?”. Nicky, of enquire.js fame, amazingly wrote part of the function for me, while I went to the pub (and then slept). That saved me a lot of work! Nicky is a great member of the web community and always willing to offer help and assistance to those who need it. So, for that, *hats off* :D