Using Media Queries in JavaScript

by Krasimir Tsonev on March 24, 2014

The modern web is always changing, and this article is more than two years old.

By Krasimir Tsonev

If you practice responsive design then you use a lot of media queries. Media Queries are a CSS feature that gives designers the power to add something like if statements. By this I mean that it allows you to apply rules only if the current page meets certain conditions. In this article I’ll show you how I use media queries in JavaScript.

The Basics

Many of you probably already know the basics of using media queries in CSS. First you create the media query and then every rule defined within it is applied to the page only if the conditions of the media query are valid.

@media all and (max-width: 700px) {
    body {
        background: #FF0;

This is pretty cool and it acts as the basis of the responsive design whereby designers need to change the look of the site based upon the specific dimensions of the screen.

However, the same is true for the developers. We all want to make our applications adaptive. We want to write the code once and support various devices. This is now possible using the window.matchMedia function. It is well supported and if you don’t need to support IE8 or lower you may use it without worry.

var mq = window.matchMedia([email protected] all and (max-width: 700px)');
if(mq.matches) {
    // the width of browser is more then 700px
} else {
    // the width of browser is less then 700px

Not only that, we can add an event listener and wait for changes.

mq.addListener(function(changed) {
    if(changed.matches) {
        // the width of browser is more then 700px
    } else {
        // the width of browser is less then 700px

Advanced Media Queries

During the last few weeks I’ve been working on the client-side components of AbsurdJS. I’m filling the library with small but useful built-in modules. Being able to use media queries in JavaScript brings a lot of benefits and I wanted to have this ready-to-use within the library. Yes, we could get the current width or height of the screen with plain JavaScript. While this can be a little bit tricky because the different browsers provide different properties, media queries are capable of more than just testing screen dimensions.

@media all and (orientation: portrait) { ... }
@media screen and (min-resolution: 2dppx) { ... }
@media tv and (scan: progressive) { ... }

As you can see we are able to write styles that target a device with specific characteristics. It’s really simple and it doesn’t require tons of code.

Tackling Browser Support

Media queries in CSS are supported in almost every browser. though in Internet Explorer it only works in version 9 and up. Support for window.matchMedia is also pretty good, though it only works in IE 10+. So what can you do when it is not supported.

var mq = function(query, callback, usePolyfill) {
    var host = {};
    var isMatchMediaSupported = !!(window && window.matchMedia) && !usePolyfill;
    if(isMatchMediaSupported) {
        var res = window.matchMedia(query);
        callback.apply(host, [res.matches,]);
        res.addListener(function(changed) {
            callback.apply(host, [changed.matches,]);
    } else {
        // ... polyfill

The usePolyfill variable was added because I wanted to test the polyfill in browsers which support window.matchMedia. The other part of the code is trivial. Calling the specified callback within a specific context and passing the result as parameters. Here is how this function could be used:

mq('all and (min-width: 300px)', function(match) {
    // match = true or false

And now it gets interesting. In general we are mostly interested in the changes of the screen’s width and height. Most of the solutions which I found are based on the resize event dispatched by the window object. They listen for that event, get the new dimensions and check if the passed query works. This is of course not enough, because sometimes we need to know that our app is running on a TV or a screen that has a lower dpi.

Because I’m writing this function for AbsurdJS, I decided to use the features of the library to help solve the problem. The idea is simple. I’ll add a span element to the body tag. I’ll monitor its display property which will be controlled by the media query used by the developer. You need to know a little bit more about AbsurdJS’s client-side components to fully understand the code below, but basically they are JavaScript classes that compile to CSS and HTML at runtime.

Before to start with the implementation of the component let’s first define its CSS and HTML.

var id = ".match-media-" + absurd.components.numOfComponents;
var css = {}, html = {};
css[id] = { display: 'block' };
css[id][[email protected] ' + query] = { display: 'none' };
html['span' + id] = '';

We need an unique id because we may have more then one usage of the mq function on the page. The rest is just the usual JavaScript object definition. absurd.components.numOfComponents is a number which is incremented during the components’ definition.

absurd.component(id + '-component', {
    css: css,
    html: html,
    intervaliTime: 30,
    status: '',
    loop: function(dom) {
        var self = this;
        if(this.el) {
            var d = this.getStyle('display');
            if(this.status != d) {
                this.status = d;
                callback.apply(host, [d === 'none'])
        setTimeout(function() { self.loop(); }, this.intervaliTime);
    constructor: ['dom', function(dom) {
        var self = this;
        this.set('parent', dom('body').el).populate();
        setTimeout(function() { self.loop(); }, this.intervaliTime);

This is what the finished component looks like. The constructor method is called immediately. It has the dom module injected, which we need in order to get a reference to the body tag. You may read more about it here, but, essentially the same effect could be achieved by using document.querySelector.

Next, we set the parent DOM element of the component and call the populate method. That’s the place where AbsurdJS compiles the css and html properties. What is important to understand here is that the library appends the generated CSS as a style tag in the head of the current document and the generated DOM element to the parent. At the end of the constructor we are calling the loop method which will be fired again and again in order to catch the changes in the span’s display property. There is a status variable which stores the latest value.

Thankfully for AbsurdJS, the polyfill for window.matchMedia is just 22 lines of code. And it still works with complex media queries, because it actually uses CSS.

An Example

If you want to see this in action check the example below. Just move the panel dividers to make the output panel greater than 300 pixels.

JS Bin

Notice that the example uses the polyfill directly (i.e. there is a true parameter at the end of the mq call). If you inspect the right part of the output iframe source, you will notice that the following CSS is added to the head:

<style id=".match-media-1-component-css" type="text/css">
    .match-media-1 {
      display: block;
    @media all and (min-width: 300px) {
      .match-media-1 {
        display: none;

And the following span tag is attached to the body.

<span class="match-media-1"></span>

The code written in this article is tested under Chrome, Firefox, Safari, Opera and IE9. If the example works properly or doesn’t work inside your browser please comment below. There are also Jasmine tests of the media query module in AbsurdJS which are available here.