Using matchMedia to add the Responsible to Responsive Web Design

Over the past year I have become a fan of Responsive Web Design because it provides an affordable way to have a single code base that targets a broad range of client devices. Generally you use media queries in CSS to define custom rules to adjust the way your layout renders. There are however concerns over performance that many, and I was one of them, are concerned with. Do you want to render the same content for a small screen (phone) as you do for a large monitor? Often the answer is no.

Efforts to deal with the content management side of responsive web design have led to a term some are calling responsible web design. My understanding of the practice is a mixture of CSS media queries and JavaScript to create a more optimal DOM and rendering based on the browser criteria (typical size). While it is generally accepted, for now, that you cannot determine all device characteristics, at least the browser ViewPort dimensions give you a good place to start.

But how do you properly use JavaScript to monitor ViewPort dimensions? The first effort most are likely to take is to bind an event handler to the Window's resize event, it certainly was for me. This can lead to some performance issues as the event continually fires as the user manually resizes the window. Recently I discovered there was a better way, the matchMedia method.

The matchMedia method returns a new MediaQueryList object. This object has a pair of members; addListener and removeListener. Basically these  two methods bind and unbind a callback method that gets executed when the browser's ViewPort crosses a boundary set by a media query. The media query (often abbreviated as mql in documentation) is the same syntax used in CSS. The following example script creates a MediaQueryList that executes a callback when the browser ViewPort crosses 400 pixels width, either greater than or less than.

window.matchMedia("(min-width: 400px)").addListener(function (e) {
      "the view port is at least 400 pixels wide");
      "the view port is not at least 400 pixels wide");

The addListener callback accepts a single variable, I used 'e' in the example. This variable has a pair of properties; matches and media. The matches property is a boolean and is either true or false, indicating if the media query criteria have been met. For the example above when the width is less than 400 pixels it is false, when it is 400 pixels or greater it is true. The media property is a list of the media queries used to create the MediaQueryListener. In this example it returns "(min-width: 400px)".

There are two primary advantages matchMedia has over monitoring the resize event. First it only fires when the media query criteria matches property changes, not every single resize event. It also allows your JavaScript to utilize that same media queries and syntax you are using in your CSS. This should make it much easier to keep content changes in sync with the CSS rules used to style the content.

matchMedia and the MediaQueryList object is supported in all current browsers, so this is something you can feel confident in utilizing. For obsolete browsers there are some polyfils available, but as usual the performance is not going to compete with the modern browser. For more details visit the MSDN and Mozilla Developer Network pages.

MSDN matchMedia

Mozzila Developer Network matchMedia