matchMedia vs polyfill (v12)

Revision 12 of this benchmark created on


Description

window.matchMedia vs matchMedia.js polyfill & Media.match

This tests the performance of native window.matchMedia against matchMedia.js and Media.match.

matchMedia() polyfill

Test whether a CSS media type or media query applies. See http://github.com/paulirish/matchMedia.js

Media.match

Testing css media queries in Javascript. Not a polyfill and perhaps faster than native window.matchMedia. See http://github.com/weblinc/media-match

Setup

/* Media - Testing css media queries in Javascript. Authors & copyright (c) 2012: WebLinc, David Knight, Zac Owen. */
    
    (function(d){var p=d.document,c=p.getElementsByTagName("head")[0],f=d.getComputedStyle&&d.getComputedStyle(c,null)||c.currentStyle,c=screen.width,q=screen.height,r=screen.colorDepth,s=p.documentElement,u=/\(\s*(not)?\s*(min|max)?-?([^:\s]+)\s*:\s*([^\s]+)\s*\)/,v=/(not)?\s*(\w*)/,j=0,t=0;d.Media={supported:!1,type:"all",queries:[],features:{width:0,height:0,"aspect-ratio":0,color:r,"color-index":Math.pow(2,r),"device-aspect-ratio":(c/q).toFixed(2),"device-width":c,"device-height":q,orientation:"landscape",
    resolution:96},getAbsValue:function(a){var b;return(b=a.match(/([\d\.]+)(px|em|rem|%|in|cm|mm|ex|pt|pc)/))?"em"==b[2]?16*b[1]:"pt"==b[2]?this.features.resolution/72*b[1]:1*b[1]:(b=a.match(/(\d+)[\/:](\d+)/))?(b[1]/b[2]).toFixed(2):(b=a.match(/([\d]+)(dpi|dppx|dpcm)/))?"dpcm"==b[2]?0.3937*b[1]:"dppx"==b[2]?96*b[1]:1*b[1]:a},parseMatch:function(a,b){var n="string"===typeof a?a.split(", "):a,e=n.pop(),d=-1!==e.indexOf("not "),g="all",c=e.split(" and "),m=c.length-1,f=!d;do{var h=null,k=!0,l=null,l=!0;
    if(-1===c[m].indexOf("(")||(h=c[m].match(u))){if(h)var k=this.features[h[3]],j=this.getAbsValue(h[4]),k="min"===h[2]?k>=j:"max"===h[2]?k<=j:"undefined"!==h[4]?k===j:k;else l=c[m].match(v)||["","all"],g=l[2],l=g===this.type||"all"===g,b&&d&&"all"!==g&&(g="screen, print, speech, projection, handheld, tv, braille, embossed, tty".split(g).join(", ").replace(/(,\s){2}/,""));if(h&&!k||!h&&!l)return n.length?this.parseMatch(n,b):d}}while(m--);return b&&f&&{matches:f,type:g,media:e}||f},match:function(a){var b=
    j;a={matches:Media.parseMatch(a,!1),media:a,addListener:function(a){Media.queries[b].listeners||(Media.queries[b].listeners=[]);a&&Media.queries[b].listeners.push(a)},removeListener:function(a){var d=Media.queries[b];if(d)for(var c=0,g=d.listeners.length;c<g;c++)d.listeners[c]===a&&d.listeners.splice(c,1)}};j++;Media.queries.push({mql:a,listeners:null});return a},watch:function(a){clearTimeout(t);t=setTimeout(function(){var b=j;Media.setMutableFeatures();do{var c=Media.queries[b],e=!1;if("undefined"!==
    typeof c&&((e=Media.parseMatch(c.mql.media))&&!c.mql.matches||!e&&c.mql.matches))if(c.mql.matches=e,c.listeners)for(var e=0,f=c.listeners.length;e<f;e++)c.listeners[e]&&c.listeners[e].call(d,c.mql,a)}while(b--)},10)},setMutableFeatures:function(){var a=d.innerWidth||s.clientWidth,b=d.innerHeight||s.clientHeight;this.features.width=a;this.features.height=b;this.features["aspect-ratio"]=(a/b).toFixed(2);this.features.orientation=b>=a?"portrait":"landscape"},listen:function(a){d.addEventListener?(d.addEventListener("resize",
    a),d.addEventListener("orientationchange",a)):d.attachEvent&&(d.attachEvent("onresize",a),d.attachEvent("onorientationchange",a))},init:function(){var a=d.devicePixelRatio;this.supported=1===parseFloat(f.height);this.type="screen print speech projection handheld tv braille embossed tty".split(" ")[parseFloat(f.zIndex)-1]||"all";this.features.resolution=a&&96*a||screen.deviceXDPI||parseFloat(f.width);this.setMutableFeatures();this.listen(this.watch)}};Media.init()})(window);
    
                window.matchMediaPolyfill = (function( doc, undefined ) {
    
                  "use strict";
    
                  var bool,
                      docElem = doc.documentElement,
                      refNode = docElem.firstElementChild || docElem.firstChild,
                      // fakeBody required for <FF4 when executed in <head>
                      fakeBody = doc.createElement( "body" ),
                      div = doc.createElement( "div" );
    
                  div.id = "mq-test-1";
                  div.style.cssText = "position:absolute;top:-100em";
                  fakeBody.style.background = "none";
                  fakeBody.appendChild(div);
    
                  return function(q){
    
                    div.innerHTML = "&shy;<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>";
    
                    docElem.insertBefore( fakeBody, refNode );
                    bool = div.offsetWidth === 42;
                    docElem.removeChild( fakeBody );
    
                    return {
                      matches: bool,
                      media: q
                    };
    
                  };
    
                }( document ));
    
    var mql = window.matchMedia('screen and (min-width: 600px), screen and (min-height: 400px)');

Teardown


    Media.queries = [];
    
    if (window.removeEventListener) {
        window.removeEventListener('resize', Media.watch);
        window.removeEventListener('orientationchange', Media.watch);
    } else if (window.detachEvent) {
        window.detachEvent('onresize', Media.watch);
        window.detachEvent('onorientationchange', Media.watch);
    }
  

Test runner

Ready to run.

Testing in
TestOps/sec
native matchMedia
mql.matches;
ready
Media.match
Media.match('screen and (min-width: 600px), screen and (min-height: 400px)').matches;
ready
polyfill paulirish/scottjehl/matchMedia.js
window.matchMediaPolyfill('screen and (min-width: 600px), screen and (min-height: 400px)').matches;
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.