├── .gitignore
├── Gruntfile.js
├── LICENSE-MIT
├── README.md
├── bower.json
├── cross-domain
├── example-base.html
├── example.html
├── respond-proxy.html
├── respond.proxy.gif
└── respond.proxy.js
├── dest
├── respond.matchmedia.addListener.min.js
├── respond.matchmedia.addListener.src.js
├── respond.min.js
└── respond.src.js
├── package.json
├── src
├── matchmedia.addListener.js
├── matchmedia.polyfill.js
└── respond.js
└── test
├── test.css
├── test.html
├── test2.css
└── unit
├── index.html
├── qunit
├── qunit.css
└── qunit.js
├── test-with-comment.css
├── test-with-dpr.css
├── test-with-keyframe.css
├── test.css
├── test2.css
├── test3.css
└── tests.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .vimdir
3 | node_modules
4 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | "use strict";
3 |
4 | // Project configuration.
5 | grunt.initConfig({
6 | pkg: grunt.file.readJSON('package.json'),
7 | banner:
8 | '/*! Respond.js v<%= pkg.version %>: <%= pkg.description %>\n' +
9 | ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>\n' +
10 | ' * Licensed under <%= _.pluck(pkg.licenses, "type").join(", ") %>\n' +
11 | ' * <%= pkg.homepageShortened %>' +
12 | ' */\n\n',
13 | uglify: {
14 | nonMinMatchMedia: {
15 | options: {
16 | banner: '<%= banner %>',
17 | mangle: false,
18 | compress: false,
19 | preserveComments: 'some',
20 | beautify: {
21 | beautify: true,
22 | indent_level: 2
23 | }
24 | },
25 | files: {
26 | 'dest/respond.src.js': ['src/matchmedia.polyfill.js', 'src/respond.js']
27 | }
28 | },
29 | minMatchMedia: {
30 | options: {
31 | banner: '<%= banner %>'
32 | },
33 | files: {
34 | 'dest/respond.min.js': ['src/matchmedia.polyfill.js', 'src/respond.js']
35 | }
36 | },
37 | nonMinMatchMediaListener: {
38 | options: {
39 | banner: '<%= banner %>',
40 | mangle: false,
41 | compress: false,
42 | preserveComments: 'some',
43 | beautify: {
44 | beautify: true,
45 | indent_level: 2
46 | }
47 | },
48 | files: {
49 | 'dest/respond.matchmedia.addListener.src.js': ['src/matchmedia.polyfill.js', 'src/matchmedia.addListener.js', 'src/respond.js']
50 | }
51 | },
52 | minMatchMediaListener: {
53 | options: {
54 | banner: '<%= banner %>'
55 | },
56 | files: {
57 | 'dest/respond.matchmedia.addListener.min.js': ['src/matchmedia.polyfill.js', 'src/matchmedia.addListener.js', 'src/respond.js']
58 | }
59 | }
60 | },
61 | jshint: {
62 | files: ['src/respond.js', 'src/matchmedia.polyfill.js'],
63 | options: {
64 | curly: true,
65 | eqeqeq: true,
66 | immed: true,
67 | latedef: false,
68 | newcap: true,
69 | noarg: true,
70 | sub: true,
71 | undef: true,
72 | boss: true,
73 | eqnull: true,
74 | smarttabs: true,
75 | node: true,
76 | es5: true,
77 | strict: false
78 | },
79 | globals: {
80 | Image: true,
81 | window: true
82 | }
83 | }
84 | });
85 |
86 | grunt.loadNpmTasks( 'grunt-contrib-jshint' );
87 | grunt.loadNpmTasks( 'grunt-contrib-uglify' );
88 |
89 | // Default task.
90 | grunt.registerTask('default', ['jshint', 'uglify']);
91 |
92 | };
93 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Scott Jehl
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Respond.js
2 | ### A fast & lightweight polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more)
3 |
4 | - Copyright 2011: Scott Jehl, scottjehl.com
5 |
6 | - Licensed under the MIT license.
7 |
8 | The goal of this script is to provide a fast and lightweight (3kb minified / 1kb gzipped) script to enable [responsive web designs](http://www.alistapart.com/articles/responsive-web-design/) in browsers that don't support CSS3 Media Queries - in particular, Internet Explorer 8 and under. It's written in such a way that it will probably patch support for other non-supporting browsers as well (more information on that soon).
9 |
10 | If you're unfamiliar with the concepts surrounding Responsive Web Design, you can read up [here](http://www.alistapart.com/articles/responsive-web-design/) and also [here](https://scottjehl.github.io/picturefill/)
11 |
12 | [Demo page](https://scottjehl.github.io/Respond/test/test.html) (the colors change to show media queries working)
13 |
14 |
15 | Usage Instructions
16 | ======
17 |
18 | 1. Craft your CSS with min/max-width media queries to adapt your layout from mobile (first) all the way up to desktop
19 | ```css
20 | @media screen and (min-width: 480px){
21 | /** ...styles for 480px and up go here **/
22 | }
23 | ```
24 |
25 | 2. Reference the respond.min.js script (1kb min/gzipped) after all of your CSS (the earlier it runs, the greater chance IE users will not see a flash of un-media'd content)
26 |
27 | 3. Crack open Internet Explorer and pump fists in delight
28 |
29 |
30 | CDN/X-Domain Setup
31 | ======
32 |
33 | Respond.js works by requesting a pristine copy of your CSS via AJAX, so if you host your stylesheets on a CDN (or a subdomain), you'll need to set up a local proxy to request the CSS for old IE browsers. Prior versions recommended a deprecated x-domain approach, but a local proxy is preferable (for performance and security reasons) to attempting to work around the cross-domain limitations.
34 |
35 |
36 | Support & Caveats
37 | ======
38 |
39 | Some notes to keep in mind:
40 |
41 | - This script's focus is purposely very narrow: only min-width and max-width media queries and all media types (screen, print, etc) are translated to non-supporting browsers. I wanted to keep things simple for filesize, maintenance, and performance, so I've intentionally limited support to queries that are essential to building a (mobile-first) responsive design. In the future, I may rework things a bit to include a hook for patching-in additional media query features - stay tuned!
42 |
43 | - Browsers that natively support CSS3 Media Queries are opted-out of running this script as quickly as possible. In testing for support, all other browsers are subjected to a quick test to determine whether they support media queries or not before proceeding to run the script. This test is now included separately at the top, and uses the window.matchMedia polyfill found here: https://github.com/paulirish/matchMedia.js . If you are already including this polyfill via Modernizr or otherwise, feel free to remove that part.
44 |
45 | - This script relies on no other scripts or frameworks (aside from the included matchMedia polyfill), and is optimized for mobile delivery (~1kb total filesize min/gzip)
46 |
47 | - As you might guess, this implementation is quite dumb in regards to CSS parsing rules. This is a good thing, because that allows it to run really fast, but its looseness may also cause unexpected behavior. For example: if you enclose a whole media query in a comment intending to disable its rules, you'll probably find that those rules will end up enabled in non-media-query-supporting browsers.
48 |
49 | - Respond.js doesn't parse CSS referenced via @import, nor does it work with media queries within style elements, as those styles can't be re-requested for parsing.
50 |
51 | - Due to security restrictions, some browsers may not allow this script to work on file:// urls (because it uses xmlHttpRequest). Run it on a web server.
52 |
53 | - If the request for the CSS file that includes MQ-specific styling is
54 | behind a redirect, Respond.js will fail silently. CSS files should
55 | respond with a 200 status.
56 |
57 | - Currently, media attributes on link elements are supported, but only if the linked stylesheet contains no media queries. If it does contain queries, the media attribute will be ignored and the internal queries will be parsed normally. In other words, @media statements in the CSS take priority.
58 |
59 | - Reportedly, if CSS files are encoded in UTF-8 with Byte-Order-Mark (BOM), they will not work with Respond.js in IE7 or IE8. Noted in issue #97
60 |
61 | - WARNING: Including @font-face rules inside a media query will cause IE7 and IE8 to hang during load. To work around this, place @font-face rules in the wide open, as a sibling to other media queries.
62 |
63 | - If you have more than 32 stylesheets referenced, IE will throw an error, `Invalid procedure call or argument`. Concatenate your CSS and the issue should go away.
64 |
65 | - Sass/SCSS source maps are not supported; `@media -sass-debug-info` will break respond.js. Noted in issue [#148](https://github.com/scottjehl/Respond/issues/148)
66 |
67 | - Internet Explorer 9 supports css3 media queries, but not within frames when the CSS containing the media query is in an external file (this appears to be a bug in IE9 — see https://stackoverflow.com/questions/10316247/media-queries-fail-inside-ie9-iframe). See this commit for a fix if you're having this problem. https://github.com/NewSignature/Respond/commit/1c86c66075f0a2099451eb426702fc3540d2e603
68 |
69 | - Nested Media Queries are not supported
70 |
71 |
72 | How's it work?
73 | ======
74 | Basically, the script loops through the CSS referenced in the page and runs a regular expression or two on their contents to find media queries and their associated blocks of CSS. In Internet Explorer, the content of the stylesheet is impossible to retrieve in its pre-parsed state (which in IE 8-, means its media queries are removed from the text), so Respond.js re-requests the CSS files using Ajax and parses the text response from there. Be sure to configure your CSS files' caching properly so that this re-request doesn't actually go to the server, hitting your browser cache instead.
75 |
76 | From there, each media query block is appended to the head in order via style elements, and those style elements are enabled and disabled (read: appended and removed from the DOM) depending on how their min/max width compares with the browser width. The media attribute on the style elements will match that of the query in the CSS, so it could be "screen", "projector", or whatever you want. Any relative paths contained in the CSS will be prefixed by their stylesheet's href, so image paths will direct to their proper destination
77 |
78 | API Options?
79 | ======
80 | Sure, a couple:
81 |
82 | - respond.update() : rerun the parser (helpful if you added a stylesheet to the page and it needs to be translated)
83 | - respond.mediaQueriesSupported: set to true if the browser natively supports media queries.
84 | - respond.getEmValue() : returns the pixel value of one em
85 |
86 |
87 | Alternatives to this script
88 | ======
89 | This isn't the only CSS3 Media Query polyfill script out there; but it damn well may be the fastest.
90 |
91 | If you're looking for more robust CSS3 Media Query support, you might check out https://code.google.com/p/css3-mediaqueries-js/. In testing, I've found that script to be noticeably slow when rendering complex responsive designs (both in filesize and performance), but it really does support a lot more media query features than this script. Big hat tip to the authors! :)
92 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "respond",
3 | "version": "1.4.2",
4 | "main": "dest/respond.src.js",
5 | "description": "Fast and lightweight polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more)",
6 | "ignore": [
7 | "**/.*",
8 | "test"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/cross-domain/example-base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is a visual test file for cross-domain proxy and custom base tag. NB: For this test to work properly, you need to set the href attribute of the base tag to the fully-qualified path to cross-domain on your system, terminated with a slash (earlier versions of IE don't play nicely otherwise).
19 |
20 |
The media queries in the included CSS file simply change the body's background color depending on the browser width. If you see any colors aside from black, then the media queries are working in your browser. You can resize your browser window to see it change on the fly.
21 |
22 |
23 |
Media-attributes are working too! This should be visible above 600px.
This is a visual test file for cross-domain proxy.
17 |
18 |
The media queries in the included CSS file simply change the body's background color depending on the browser width. If you see any colors aside from black, then the media queries are working in your browser. You can resize your browser window to see it change on the fly.
19 |
20 |
21 |
Media-attributes are working too! This should be visible above 600px.
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/cross-domain/respond-proxy.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Respond JS Proxy
7 |
8 |
9 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/cross-domain/respond.proxy.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scottjehl/Respond/9d91fd47eb59c11a80d570d4ea0beaa59cfc71bf/cross-domain/respond.proxy.gif
--------------------------------------------------------------------------------
/cross-domain/respond.proxy.js:
--------------------------------------------------------------------------------
1 | /*! Respond.js: min/max-width media query polyfill. Remote proxy (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
2 | (function(win, doc, undefined){
3 | var docElem = doc.documentElement,
4 | proxyURL = doc.getElementById("respond-proxy").href,
5 | redirectURL = (doc.getElementById("respond-redirect") || location).href,
6 | baseElem = doc.getElementsByTagName("base")[0],
7 | urls = [],
8 | refNode;
9 |
10 | function encode(url){
11 | return win.encodeURIComponent(url);
12 | }
13 |
14 | function fakejax( url, callback ){
15 |
16 | var iframe,
17 | AXO;
18 |
19 | // All hail Google https://j.mp/iKMI19
20 | // Behold, an iframe proxy without annoying clicky noises.
21 | if ( "ActiveXObject" in win ) {
22 | AXO = new ActiveXObject( "htmlfile" );
23 | AXO.open();
24 | AXO.write( '' );
25 | AXO.close();
26 | iframe = AXO.getElementById( "x" );
27 | } else {
28 | iframe = doc.createElement( "iframe" );
29 | iframe.style.cssText = "position:absolute;top:-99em";
30 | docElem.insertBefore(iframe, docElem.firstElementChild || docElem.firstChild );
31 | }
32 |
33 | iframe.src = checkBaseURL(proxyURL) + "?url=" + encode(redirectURL) + "&css=" + encode(checkBaseURL(url));
34 |
35 | function checkFrameName() {
36 | var cssText;
37 |
38 | try {
39 | cssText = iframe.contentWindow.name;
40 | }
41 | catch (e) { }
42 |
43 | if (cssText) {
44 | // We've got what we need. Stop the iframe from loading further content.
45 | iframe.src = "about:blank";
46 | iframe.parentNode.removeChild(iframe);
47 | iframe = null;
48 |
49 |
50 | // Per https://j.mp/kn9EPh, not taking any chances. Flushing the ActiveXObject
51 | if (AXO) {
52 | AXO = null;
53 |
54 | if (win.CollectGarbage) {
55 | win.CollectGarbage();
56 | }
57 | }
58 |
59 | callback(cssText);
60 | }
61 | else{
62 | win.setTimeout(checkFrameName, 100);
63 | }
64 | }
65 |
66 | win.setTimeout(checkFrameName, 500);
67 | }
68 |
69 | // https://stackoverflow.com/a/472729
70 | function checkBaseURL(href) {
71 | var el = document.createElement('div'),
72 | escapedURL = href.split('&').join('&').
73 | split('<').join('<').
74 | split('"').join('"');
75 |
76 | el.innerHTML = 'x';
77 | return el.firstChild.href;
78 | }
79 |
80 | function checkRedirectURL() {
81 | // IE6 & IE7 don't build out absolute urls in attributes.
82 | // So respond.proxy.gif remains relative instead of https://example.com/respond.proxy.gif.
83 | // This trickery resolves that issue.
84 | if (~ !redirectURL.indexOf(location.host)) {
85 |
86 | var fakeLink = doc.createElement("div");
87 |
88 | fakeLink.innerHTML = '';
89 | docElem.insertBefore(fakeLink, docElem.firstElementChild || docElem.firstChild );
90 |
91 | // Grab the parsed URL from that dummy object
92 | redirectURL = fakeLink.firstChild.href;
93 |
94 | // Clean up
95 | fakeLink.parentNode.removeChild(fakeLink);
96 | fakeLink = null;
97 | }
98 | }
99 |
100 | function buildUrls(){
101 | var links = doc.getElementsByTagName( "link" );
102 |
103 | for( var i = 0, linkl = links.length; i < linkl; i++ ){
104 |
105 | var thislink = links[i],
106 | href = links[i].href,
107 | extreg = (/^([a-zA-Z:]*\/\/(www\.)?)/).test( href ),
108 | ext = (baseElem && !extreg) || extreg;
109 |
110 | //make sure it's an external stylesheet
111 | if( thislink.rel.indexOf( "stylesheet" ) >= 0 && ext ){
112 | (function( link ){
113 | fakejax( href, function( css ){
114 | link.styleSheet.rawCssText = css;
115 | respond.update();
116 | } );
117 | })( thislink );
118 | }
119 | }
120 |
121 |
122 | }
123 |
124 | if( !respond.mediaQueriesSupported ){
125 | checkRedirectURL();
126 | buildUrls();
127 | }
128 |
129 | })( window, document );
130 |
--------------------------------------------------------------------------------
/dest/respond.matchmedia.addListener.min.js:
--------------------------------------------------------------------------------
1 | /*! Respond.js v1.4.2: min/max-width media query polyfill
2 | * Copyright 2014 Scott Jehl
3 | * Licensed under MIT
4 | * https://j.mp/respondjs */
5 |
6 | !function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";if(a.matchMedia&&a.matchMedia("all").addListener)return!1;var b=a.matchMedia,c=b("only all").matches,d=!1,e=0,f=[],g=function(){a.clearTimeout(e),e=a.setTimeout(function(){for(var c=0,d=f.length;d>c;c++){var e=f[c].mql,g=f[c].listeners||[],h=b(e.media).matches;if(h!==e.matches){e.matches=h;for(var i=0,j=g.length;j>i;i++)g[i].call(a,e)}}},30)};a.matchMedia=function(e){var h=b(e),i=[],j=0;return h.addListener=function(b){c&&(d||(d=!0,a.addEventListener("resize",g,!0)),0===j&&(j=f.push({mql:h,listeners:i})),i.push(b))},h.removeListener=function(a){for(var b=0,c=i.length;c>b;b++)i[b]===a&&i.splice(b,1)},h}}(this),function(a){"use strict";function b(){v(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},g=function(a){return a.replace(c.regex.minmaxwh,"").match(c.regex.other)};if(c.ajax=f,c.queue=d,c.unsupportedmq=g,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,comments:/\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,maxw:/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,minmaxwh:/\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,other:/\([^\)]*\)/g},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var h,i,j,k=a.document,l=k.documentElement,m=[],n=[],o=[],p={},q=30,r=k.getElementsByTagName("head")[0]||l,s=k.getElementsByTagName("base")[0],t=r.getElementsByTagName("link"),u=function(){var a,b=k.createElement("div"),c=k.body,d=l.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=k.createElement("body"),c.style.background="none"),l.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&l.insertBefore(c,l.firstChild),a=b.offsetWidth,f?l.removeChild(c):c.removeChild(b),l.style.fontSize=d,e&&(c.style.fontSize=e),a=j=parseFloat(a)},v=function(b){var c="clientWidth",d=l[c],e="CSS1Compat"===k.compatMode&&d||k.body[c]||d,f={},g=t[t.length-1],p=(new Date).getTime();if(b&&h&&q>p-h)return a.clearTimeout(i),i=a.setTimeout(v,q),void 0;h=p;for(var s in m)if(m.hasOwnProperty(s)){var w=m[s],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?j||u():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?j||u():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(n[w.rules]))}for(var C in o)o.hasOwnProperty(C)&&o[C]&&o[C].parentNode===r&&r.removeChild(o[C]);o.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=k.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,r.insertBefore(E,g.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(k.createTextNode(F)),o.push(E)}},w=function(a,b,d){var e=a.replace(c.regex.comments,"").replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},i=!f&&d;b.length&&(b+="/"),i&&(f=1);for(var j=0;f>j;j++){var k,l,o,p;i?(k=d,n.push(h(a))):(k=e[j].match(c.regex.findStyles)&&RegExp.$1,n.push(RegExp.$2&&h(RegExp.$2))),o=k.split(","),p=o.length;for(var q=0;p>q;q++)l=o[q],g(l)||m.push({media:l.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:n.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}v()},x=function(){if(d.length){var b=d.shift();f(b.href,function(c){w(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){x()},0)})}},y=function(){for(var b=0;b #mq-test-1 { width: 42px; }';
18 | docElem.insertBefore(fakeBody, refNode);
19 | bool = div.offsetWidth === 42;
20 | docElem.removeChild(fakeBody);
21 | return {
22 | matches: bool,
23 | media: q
24 | };
25 | };
26 | }(w.document);
27 | })(this);
28 |
29 | /*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license */
30 | (function(w) {
31 | "use strict";
32 | if (w.matchMedia && w.matchMedia("all").addListener) {
33 | return false;
34 | }
35 | var localMatchMedia = w.matchMedia, hasMediaQueries = localMatchMedia("only all").matches, isListening = false, timeoutID = 0, queries = [], handleChange = function(evt) {
36 | w.clearTimeout(timeoutID);
37 | timeoutID = w.setTimeout(function() {
38 | for (var i = 0, il = queries.length; i < il; i++) {
39 | var mql = queries[i].mql, listeners = queries[i].listeners || [], matches = localMatchMedia(mql.media).matches;
40 | if (matches !== mql.matches) {
41 | mql.matches = matches;
42 | for (var j = 0, jl = listeners.length; j < jl; j++) {
43 | listeners[j].call(w, mql);
44 | }
45 | }
46 | }
47 | }, 30);
48 | };
49 | w.matchMedia = function(media) {
50 | var mql = localMatchMedia(media), listeners = [], index = 0;
51 | mql.addListener = function(listener) {
52 | if (!hasMediaQueries) {
53 | return;
54 | }
55 | if (!isListening) {
56 | isListening = true;
57 | w.addEventListener("resize", handleChange, true);
58 | }
59 | if (index === 0) {
60 | index = queries.push({
61 | mql: mql,
62 | listeners: listeners
63 | });
64 | }
65 | listeners.push(listener);
66 | };
67 | mql.removeListener = function(listener) {
68 | for (var i = 0, il = listeners.length; i < il; i++) {
69 | if (listeners[i] === listener) {
70 | listeners.splice(i, 1);
71 | }
72 | }
73 | };
74 | return mql;
75 | };
76 | })(this);
77 |
78 | (function(w) {
79 | "use strict";
80 | var respond = {};
81 | w.respond = respond;
82 | respond.update = function() {};
83 | var requestQueue = [], xmlHttp = function() {
84 | var xmlhttpmethod = false;
85 | try {
86 | xmlhttpmethod = new w.XMLHttpRequest();
87 | } catch (e) {
88 | xmlhttpmethod = new w.ActiveXObject("Microsoft.XMLHTTP");
89 | }
90 | return function() {
91 | return xmlhttpmethod;
92 | };
93 | }(), ajax = function(url, callback) {
94 | var req = xmlHttp();
95 | if (!req) {
96 | return;
97 | }
98 | req.open("GET", url, true);
99 | req.onreadystatechange = function() {
100 | if (req.readyState !== 4 || req.status !== 200 && req.status !== 304) {
101 | return;
102 | }
103 | callback(req.responseText);
104 | };
105 | if (req.readyState === 4) {
106 | return;
107 | }
108 | req.send(null);
109 | }, isUnsupportedMediaQuery = function(query) {
110 | return query.replace(respond.regex.minmaxwh, "").match(respond.regex.other);
111 | };
112 | respond.ajax = ajax;
113 | respond.queue = requestQueue;
114 | respond.unsupportedmq = isUnsupportedMediaQuery;
115 | respond.regex = {
116 | media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,
117 | keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,
118 | comments: /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,
119 | urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,
120 | findStyles: /@media *([^\{]+)\{([\S\s]+?)$/,
121 | only: /(only\s+)?([a-zA-Z]+)\s?/,
122 | minw: /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
123 | maxw: /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
124 | minmaxwh: /\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,
125 | other: /\([^\)]*\)/g
126 | };
127 | respond.mediaQueriesSupported = w.matchMedia && w.matchMedia("only all") !== null && w.matchMedia("only all").matches;
128 | if (respond.mediaQueriesSupported) {
129 | return;
130 | }
131 | var doc = w.document, docElem = doc.documentElement, mediastyles = [], rules = [], appendedEls = [], parsedSheets = {}, resizeThrottle = 30, head = doc.getElementsByTagName("head")[0] || docElem, base = doc.getElementsByTagName("base")[0], links = head.getElementsByTagName("link"), lastCall, resizeDefer, eminpx, getEmValue = function() {
132 | var ret, div = doc.createElement("div"), body = doc.body, originalHTMLFontSize = docElem.style.fontSize, originalBodyFontSize = body && body.style.fontSize, fakeUsed = false;
133 | div.style.cssText = "position:absolute;font-size:1em;width:1em";
134 | if (!body) {
135 | body = fakeUsed = doc.createElement("body");
136 | body.style.background = "none";
137 | }
138 | docElem.style.fontSize = "100%";
139 | body.style.fontSize = "100%";
140 | body.appendChild(div);
141 | if (fakeUsed) {
142 | docElem.insertBefore(body, docElem.firstChild);
143 | }
144 | ret = div.offsetWidth;
145 | if (fakeUsed) {
146 | docElem.removeChild(body);
147 | } else {
148 | body.removeChild(div);
149 | }
150 | docElem.style.fontSize = originalHTMLFontSize;
151 | if (originalBodyFontSize) {
152 | body.style.fontSize = originalBodyFontSize;
153 | }
154 | ret = eminpx = parseFloat(ret);
155 | return ret;
156 | }, applyMedia = function(fromResize) {
157 | var name = "clientWidth", docElemProp = docElem[name], currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime();
158 | if (fromResize && lastCall && now - lastCall < resizeThrottle) {
159 | w.clearTimeout(resizeDefer);
160 | resizeDefer = w.setTimeout(applyMedia, resizeThrottle);
161 | return;
162 | } else {
163 | lastCall = now;
164 | }
165 | for (var i in mediastyles) {
166 | if (mediastyles.hasOwnProperty(i)) {
167 | var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = "em";
168 | if (!!min) {
169 | min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
170 | }
171 | if (!!max) {
172 | max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
173 | }
174 | if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) {
175 | if (!styleBlocks[thisstyle.media]) {
176 | styleBlocks[thisstyle.media] = [];
177 | }
178 | styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
179 | }
180 | }
181 | }
182 | for (var j in appendedEls) {
183 | if (appendedEls.hasOwnProperty(j)) {
184 | if (appendedEls[j] && appendedEls[j].parentNode === head) {
185 | head.removeChild(appendedEls[j]);
186 | }
187 | }
188 | }
189 | appendedEls.length = 0;
190 | for (var k in styleBlocks) {
191 | if (styleBlocks.hasOwnProperty(k)) {
192 | var ss = doc.createElement("style"), css = styleBlocks[k].join("\n");
193 | ss.type = "text/css";
194 | ss.media = k;
195 | head.insertBefore(ss, lastLink.nextSibling);
196 | if (ss.styleSheet) {
197 | ss.styleSheet.cssText = css;
198 | } else {
199 | ss.appendChild(doc.createTextNode(css));
200 | }
201 | appendedEls.push(ss);
202 | }
203 | }
204 | }, translate = function(styles, href, media) {
205 | var qs = styles.replace(respond.regex.comments, "").replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0;
206 | href = href.substring(0, href.lastIndexOf("/"));
207 | var repUrls = function(css) {
208 | return css.replace(respond.regex.urls, "$1" + href + "$2$3");
209 | }, useMedia = !ql && media;
210 | if (href.length) {
211 | href += "/";
212 | }
213 | if (useMedia) {
214 | ql = 1;
215 | }
216 | for (var i = 0; i < ql; i++) {
217 | var fullq, thisq, eachq, eql;
218 | if (useMedia) {
219 | fullq = media;
220 | rules.push(repUrls(styles));
221 | } else {
222 | fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1;
223 | rules.push(RegExp.$2 && repUrls(RegExp.$2));
224 | }
225 | eachq = fullq.split(",");
226 | eql = eachq.length;
227 | for (var j = 0; j < eql; j++) {
228 | thisq = eachq[j];
229 | if (isUnsupportedMediaQuery(thisq)) {
230 | continue;
231 | }
232 | mediastyles.push({
233 | media: thisq.split("(")[0].match(respond.regex.only) && RegExp.$2 || "all",
234 | rules: rules.length - 1,
235 | hasquery: thisq.indexOf("(") > -1,
236 | minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || ""),
237 | maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || "")
238 | });
239 | }
240 | }
241 | applyMedia();
242 | }, makeRequests = function() {
243 | if (requestQueue.length) {
244 | var thisRequest = requestQueue.shift();
245 | ajax(thisRequest.href, function(styles) {
246 | translate(styles, thisRequest.href, thisRequest.media);
247 | parsedSheets[thisRequest.href] = true;
248 | w.setTimeout(function() {
249 | makeRequests();
250 | }, 0);
251 | });
252 | }
253 | }, ripCSS = function() {
254 | for (var i = 0; i < links.length; i++) {
255 | var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
256 | if (!!href && isCSS && !parsedSheets[href]) {
257 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
258 | translate(sheet.styleSheet.rawCssText, href, media);
259 | parsedSheets[href] = true;
260 | } else {
261 | if (!/^([a-zA-Z:]*\/\/)/.test(href) && !base || href.replace(RegExp.$1, "").split("/")[0] === w.location.host) {
262 | if (href.substring(0, 2) === "//") {
263 | href = w.location.protocol + href;
264 | }
265 | requestQueue.push({
266 | href: href,
267 | media: media
268 | });
269 | }
270 | }
271 | }
272 | }
273 | makeRequests();
274 | };
275 | ripCSS();
276 | respond.update = ripCSS;
277 | respond.getEmValue = getEmValue;
278 | function callMedia() {
279 | applyMedia(true);
280 | }
281 | if (w.addEventListener) {
282 | w.addEventListener("resize", callMedia, false);
283 | } else if (w.attachEvent) {
284 | w.attachEvent("onresize", callMedia);
285 | }
286 | })(this);
287 |
--------------------------------------------------------------------------------
/dest/respond.min.js:
--------------------------------------------------------------------------------
1 | /*! Respond.js v1.4.2: min/max-width media query polyfill
2 | * Copyright 2014 Scott Jehl
3 | * Licensed under MIT
4 | * https://j.mp/respondjs */
5 |
6 | !function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){v(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},g=function(a){return a.replace(c.regex.minmaxwh,"").match(c.regex.other)};if(c.ajax=f,c.queue=d,c.unsupportedmq=g,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,comments:/\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,maxw:/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,minmaxwh:/\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,other:/\([^\)]*\)/g},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var h,i,j,k=a.document,l=k.documentElement,m=[],n=[],o=[],p={},q=30,r=k.getElementsByTagName("head")[0]||l,s=k.getElementsByTagName("base")[0],t=r.getElementsByTagName("link"),u=function(){var a,b=k.createElement("div"),c=k.body,d=l.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=k.createElement("body"),c.style.background="none"),l.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&l.insertBefore(c,l.firstChild),a=b.offsetWidth,f?l.removeChild(c):c.removeChild(b),l.style.fontSize=d,e&&(c.style.fontSize=e),a=j=parseFloat(a)},v=function(b){var c="clientWidth",d=l[c],e="CSS1Compat"===k.compatMode&&d||k.body[c]||d,f={},g=t[t.length-1],p=(new Date).getTime();if(b&&h&&q>p-h)return a.clearTimeout(i),i=a.setTimeout(v,q),void 0;h=p;for(var s in m)if(m.hasOwnProperty(s)){var w=m[s],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?j||u():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?j||u():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(n[w.rules]))}for(var C in o)o.hasOwnProperty(C)&&o[C]&&o[C].parentNode===r&&r.removeChild(o[C]);o.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=k.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,r.insertBefore(E,g.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(k.createTextNode(F)),o.push(E)}},w=function(a,b,d){var e=a.replace(c.regex.comments,"").replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},i=!f&&d;b.length&&(b+="/"),i&&(f=1);for(var j=0;f>j;j++){var k,l,o,p;i?(k=d,n.push(h(a))):(k=e[j].match(c.regex.findStyles)&&RegExp.$1,n.push(RegExp.$2&&h(RegExp.$2))),o=k.split(","),p=o.length;for(var q=0;p>q;q++)l=o[q],g(l)||m.push({media:l.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:n.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}v()},x=function(){if(d.length){var b=d.shift();f(b.href,function(c){w(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){x()},0)})}},y=function(){for(var b=0;b #mq-test-1 { width: 42px; }';
18 | docElem.insertBefore(fakeBody, refNode);
19 | bool = div.offsetWidth === 42;
20 | docElem.removeChild(fakeBody);
21 | return {
22 | matches: bool,
23 | media: q
24 | };
25 | };
26 | }(w.document);
27 | })(this);
28 |
29 | (function(w) {
30 | "use strict";
31 | var respond = {};
32 | w.respond = respond;
33 | respond.update = function() {};
34 | var requestQueue = [], xmlHttp = function() {
35 | var xmlhttpmethod = false;
36 | try {
37 | xmlhttpmethod = new w.XMLHttpRequest();
38 | } catch (e) {
39 | xmlhttpmethod = new w.ActiveXObject("Microsoft.XMLHTTP");
40 | }
41 | return function() {
42 | return xmlhttpmethod;
43 | };
44 | }(), ajax = function(url, callback) {
45 | var req = xmlHttp();
46 | if (!req) {
47 | return;
48 | }
49 | req.open("GET", url, true);
50 | req.onreadystatechange = function() {
51 | if (req.readyState !== 4 || req.status !== 200 && req.status !== 304) {
52 | return;
53 | }
54 | callback(req.responseText);
55 | };
56 | if (req.readyState === 4) {
57 | return;
58 | }
59 | req.send(null);
60 | }, isUnsupportedMediaQuery = function(query) {
61 | return query.replace(respond.regex.minmaxwh, "").match(respond.regex.other);
62 | };
63 | respond.ajax = ajax;
64 | respond.queue = requestQueue;
65 | respond.unsupportedmq = isUnsupportedMediaQuery;
66 | respond.regex = {
67 | media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,
68 | keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,
69 | comments: /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,
70 | urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,
71 | findStyles: /@media *([^\{]+)\{([\S\s]+?)$/,
72 | only: /(only\s+)?([a-zA-Z]+)\s?/,
73 | minw: /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
74 | maxw: /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
75 | minmaxwh: /\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,
76 | other: /\([^\)]*\)/g
77 | };
78 | respond.mediaQueriesSupported = w.matchMedia && w.matchMedia("only all") !== null && w.matchMedia("only all").matches;
79 | if (respond.mediaQueriesSupported) {
80 | return;
81 | }
82 | var doc = w.document, docElem = doc.documentElement, mediastyles = [], rules = [], appendedEls = [], parsedSheets = {}, resizeThrottle = 30, head = doc.getElementsByTagName("head")[0] || docElem, base = doc.getElementsByTagName("base")[0], links = head.getElementsByTagName("link"), lastCall, resizeDefer, eminpx, getEmValue = function() {
83 | var ret, div = doc.createElement("div"), body = doc.body, originalHTMLFontSize = docElem.style.fontSize, originalBodyFontSize = body && body.style.fontSize, fakeUsed = false;
84 | div.style.cssText = "position:absolute;font-size:1em;width:1em";
85 | if (!body) {
86 | body = fakeUsed = doc.createElement("body");
87 | body.style.background = "none";
88 | }
89 | docElem.style.fontSize = "100%";
90 | body.style.fontSize = "100%";
91 | body.appendChild(div);
92 | if (fakeUsed) {
93 | docElem.insertBefore(body, docElem.firstChild);
94 | }
95 | ret = div.offsetWidth;
96 | if (fakeUsed) {
97 | docElem.removeChild(body);
98 | } else {
99 | body.removeChild(div);
100 | }
101 | docElem.style.fontSize = originalHTMLFontSize;
102 | if (originalBodyFontSize) {
103 | body.style.fontSize = originalBodyFontSize;
104 | }
105 | ret = eminpx = parseFloat(ret);
106 | return ret;
107 | }, applyMedia = function(fromResize) {
108 | var name = "clientWidth", docElemProp = docElem[name], currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime();
109 | if (fromResize && lastCall && now - lastCall < resizeThrottle) {
110 | w.clearTimeout(resizeDefer);
111 | resizeDefer = w.setTimeout(applyMedia, resizeThrottle);
112 | return;
113 | } else {
114 | lastCall = now;
115 | }
116 | for (var i in mediastyles) {
117 | if (mediastyles.hasOwnProperty(i)) {
118 | var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = "em";
119 | if (!!min) {
120 | min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
121 | }
122 | if (!!max) {
123 | max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
124 | }
125 | if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) {
126 | if (!styleBlocks[thisstyle.media]) {
127 | styleBlocks[thisstyle.media] = [];
128 | }
129 | styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
130 | }
131 | }
132 | }
133 | for (var j in appendedEls) {
134 | if (appendedEls.hasOwnProperty(j)) {
135 | if (appendedEls[j] && appendedEls[j].parentNode === head) {
136 | head.removeChild(appendedEls[j]);
137 | }
138 | }
139 | }
140 | appendedEls.length = 0;
141 | for (var k in styleBlocks) {
142 | if (styleBlocks.hasOwnProperty(k)) {
143 | var ss = doc.createElement("style"), css = styleBlocks[k].join("\n");
144 | ss.type = "text/css";
145 | ss.media = k;
146 | head.insertBefore(ss, lastLink.nextSibling);
147 | if (ss.styleSheet) {
148 | ss.styleSheet.cssText = css;
149 | } else {
150 | ss.appendChild(doc.createTextNode(css));
151 | }
152 | appendedEls.push(ss);
153 | }
154 | }
155 | }, translate = function(styles, href, media) {
156 | var qs = styles.replace(respond.regex.comments, "").replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0;
157 | href = href.substring(0, href.lastIndexOf("/"));
158 | var repUrls = function(css) {
159 | return css.replace(respond.regex.urls, "$1" + href + "$2$3");
160 | }, useMedia = !ql && media;
161 | if (href.length) {
162 | href += "/";
163 | }
164 | if (useMedia) {
165 | ql = 1;
166 | }
167 | for (var i = 0; i < ql; i++) {
168 | var fullq, thisq, eachq, eql;
169 | if (useMedia) {
170 | fullq = media;
171 | rules.push(repUrls(styles));
172 | } else {
173 | fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1;
174 | rules.push(RegExp.$2 && repUrls(RegExp.$2));
175 | }
176 | eachq = fullq.split(",");
177 | eql = eachq.length;
178 | for (var j = 0; j < eql; j++) {
179 | thisq = eachq[j];
180 | if (isUnsupportedMediaQuery(thisq)) {
181 | continue;
182 | }
183 | mediastyles.push({
184 | media: thisq.split("(")[0].match(respond.regex.only) && RegExp.$2 || "all",
185 | rules: rules.length - 1,
186 | hasquery: thisq.indexOf("(") > -1,
187 | minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || ""),
188 | maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || "")
189 | });
190 | }
191 | }
192 | applyMedia();
193 | }, makeRequests = function() {
194 | if (requestQueue.length) {
195 | var thisRequest = requestQueue.shift();
196 | ajax(thisRequest.href, function(styles) {
197 | translate(styles, thisRequest.href, thisRequest.media);
198 | parsedSheets[thisRequest.href] = true;
199 | w.setTimeout(function() {
200 | makeRequests();
201 | }, 0);
202 | });
203 | }
204 | }, ripCSS = function() {
205 | for (var i = 0; i < links.length; i++) {
206 | var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
207 | if (!!href && isCSS && !parsedSheets[href]) {
208 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
209 | translate(sheet.styleSheet.rawCssText, href, media);
210 | parsedSheets[href] = true;
211 | } else {
212 | if (!/^([a-zA-Z:]*\/\/)/.test(href) && !base || href.replace(RegExp.$1, "").split("/")[0] === w.location.host) {
213 | if (href.substring(0, 2) === "//") {
214 | href = w.location.protocol + href;
215 | }
216 | requestQueue.push({
217 | href: href,
218 | media: media
219 | });
220 | }
221 | }
222 | }
223 | }
224 | makeRequests();
225 | };
226 | ripCSS();
227 | respond.update = ripCSS;
228 | respond.getEmValue = getEmValue;
229 | function callMedia() {
230 | applyMedia(true);
231 | }
232 | if (w.addEventListener) {
233 | w.addEventListener("resize", callMedia, false);
234 | } else if (w.attachEvent) {
235 | w.attachEvent("onresize", callMedia);
236 | }
237 | })(this);
238 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Respond.js",
3 | "description": "min/max-width media query polyfill",
4 | "version": "1.4.2",
5 | "homepage": "https://github.com/scottjehl/Respond",
6 | "homepageShortened": "https://j.mp/respondjs",
7 | "author": {
8 | "name": "Scott Jehl",
9 | "email": "scott@filamentgroup.com",
10 | "url": "https://filamentgroup.com"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/scottjehl/Respond.git"
15 | },
16 | "bugs": {
17 | "url": "https://github.com/scottjehl/Respond/issues"
18 | },
19 | "licenses": [
20 | {
21 | "type": "MIT",
22 | "url": "https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT"
23 | }
24 | ],
25 | "devDependencies": {
26 | "grunt-cli":"~0.1",
27 | "grunt": "~0.4.0",
28 | "grunt-contrib-jshint": "~0.2.0",
29 | "grunt-contrib-qunit": "~0.3.0",
30 | "grunt-contrib-uglify": "0.2.7"
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/matchmedia.addListener.js:
--------------------------------------------------------------------------------
1 | /*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license */
2 | (function( w ){
3 | "use strict";
4 | // Bail out for browsers that have addListener support
5 | if (w.matchMedia && w.matchMedia('all').addListener) {
6 | return false;
7 | }
8 |
9 | var localMatchMedia = w.matchMedia,
10 | hasMediaQueries = localMatchMedia('only all').matches,
11 | isListening = false,
12 | timeoutID = 0, // setTimeout for debouncing 'handleChange'
13 | queries = [], // Contains each 'mql' and associated 'listeners' if 'addListener' is used
14 | handleChange = function(evt) {
15 | // Debounce
16 | w.clearTimeout(timeoutID);
17 |
18 | timeoutID = w.setTimeout(function() {
19 | for (var i = 0, il = queries.length; i < il; i++) {
20 | var mql = queries[i].mql,
21 | listeners = queries[i].listeners || [],
22 | matches = localMatchMedia(mql.media).matches;
23 |
24 | // Update mql.matches value and call listeners
25 | // Fire listeners only if transitioning to or from matched state
26 | if (matches !== mql.matches) {
27 | mql.matches = matches;
28 |
29 | for (var j = 0, jl = listeners.length; j < jl; j++) {
30 | listeners[j].call(w, mql);
31 | }
32 | }
33 | }
34 | }, 30);
35 | };
36 |
37 | w.matchMedia = function(media) {
38 | var mql = localMatchMedia(media),
39 | listeners = [],
40 | index = 0;
41 |
42 | mql.addListener = function(listener) {
43 | // Changes would not occur to css media type so return now (Affects IE <= 8)
44 | if (!hasMediaQueries) {
45 | return;
46 | }
47 |
48 | // Set up 'resize' listener for browsers that support CSS3 media queries (Not for IE <= 8)
49 | // There should only ever be 1 resize listener running for performance
50 | if (!isListening) {
51 | isListening = true;
52 | w.addEventListener('resize', handleChange, true);
53 | }
54 |
55 | // Push object only if it has not been pushed already
56 | if (index === 0) {
57 | index = queries.push({
58 | mql : mql,
59 | listeners : listeners
60 | });
61 | }
62 |
63 | listeners.push(listener);
64 | };
65 |
66 | mql.removeListener = function(listener) {
67 | for (var i = 0, il = listeners.length; i < il; i++){
68 | if (listeners[i] === listener){
69 | listeners.splice(i, 1);
70 | }
71 | }
72 | };
73 |
74 | return mql;
75 | };
76 | }( this ));
77 |
--------------------------------------------------------------------------------
/src/matchmedia.polyfill.js:
--------------------------------------------------------------------------------
1 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
2 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
3 |
4 | (function(w){
5 | "use strict";
6 | w.matchMedia = w.matchMedia || (function( doc, undefined ) {
7 |
8 | var bool,
9 | docElem = doc.documentElement,
10 | refNode = docElem.firstElementChild || docElem.firstChild,
11 | // fakeBody required for
12 | fakeBody = doc.createElement( "body" ),
13 | div = doc.createElement( "div" );
14 |
15 | div.id = "mq-test-1";
16 | div.style.cssText = "position:absolute;top:-100em";
17 | fakeBody.style.background = "none";
18 | fakeBody.appendChild(div);
19 |
20 | return function(q){
21 |
22 | div.innerHTML = "";
23 |
24 | docElem.insertBefore( fakeBody, refNode );
25 | bool = div.offsetWidth === 42;
26 | docElem.removeChild( fakeBody );
27 |
28 | return {
29 | matches: bool,
30 | media: q
31 | };
32 |
33 | };
34 |
35 | }( w.document ));
36 | }( this ));
37 |
--------------------------------------------------------------------------------
/src/respond.js:
--------------------------------------------------------------------------------
1 | /* Respond.js: min/max-width media query polyfill. (c) Scott Jehl. MIT Lic. j.mp/respondjs */
2 | (function( w ){
3 |
4 | "use strict";
5 |
6 | //exposed namespace
7 | var respond = {};
8 | w.respond = respond;
9 |
10 | //define update even in native-mq-supporting browsers, to avoid errors
11 | respond.update = function(){};
12 |
13 | //define ajax obj
14 | var requestQueue = [],
15 | xmlHttp = (function() {
16 | var xmlhttpmethod = false;
17 | try {
18 | xmlhttpmethod = new w.XMLHttpRequest();
19 | }
20 | catch( e ){
21 | xmlhttpmethod = new w.ActiveXObject( "Microsoft.XMLHTTP" );
22 | }
23 | return function(){
24 | return xmlhttpmethod;
25 | };
26 | })(),
27 |
28 | //tweaked Ajax functions from Quirksmode
29 | ajax = function( url, callback ) {
30 | var req = xmlHttp();
31 | if (!req){
32 | return;
33 | }
34 | req.open( "GET", url, true );
35 | req.onreadystatechange = function () {
36 | if ( req.readyState !== 4 || req.status !== 200 && req.status !== 304 ){
37 | return;
38 | }
39 | callback( req.responseText );
40 | };
41 | if ( req.readyState === 4 ){
42 | return;
43 | }
44 | req.send( null );
45 | },
46 | isUnsupportedMediaQuery = function( query ) {
47 | return query.replace( respond.regex.minmaxwh, '' ).match( respond.regex.other );
48 | };
49 |
50 | //expose for testing
51 | respond.ajax = ajax;
52 | respond.queue = requestQueue;
53 | respond.unsupportedmq = isUnsupportedMediaQuery;
54 | respond.regex = {
55 | media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,
56 | keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,
57 | comments: /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,
58 | urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,
59 | findStyles: /@media *([^\{]+)\{([\S\s]+?)$/,
60 | only: /(only\s+)?([a-zA-Z]+)\s?/,
61 | minw: /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
62 | maxw: /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
63 | minmaxwh: /\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,
64 | other: /\([^\)]*\)/g
65 | };
66 |
67 | //expose media query support flag for external use
68 | respond.mediaQueriesSupported = w.matchMedia && w.matchMedia( "only all" ) !== null && w.matchMedia( "only all" ).matches;
69 |
70 | //if media queries are supported, exit here
71 | if( respond.mediaQueriesSupported ){
72 | return;
73 | }
74 |
75 | //define vars
76 | var doc = w.document,
77 | docElem = doc.documentElement,
78 | mediastyles = [],
79 | rules = [],
80 | appendedEls = [],
81 | parsedSheets = {},
82 | resizeThrottle = 30,
83 | head = doc.getElementsByTagName( "head" )[0] || docElem,
84 | base = doc.getElementsByTagName( "base" )[0],
85 | links = head.getElementsByTagName( "link" ),
86 |
87 | lastCall,
88 | resizeDefer,
89 |
90 | //cached container for 1em value, populated the first time it's needed
91 | eminpx,
92 |
93 | // returns the value of 1em in pixels
94 | getEmValue = function() {
95 | var ret,
96 | div = doc.createElement('div'),
97 | body = doc.body,
98 | originalHTMLFontSize = docElem.style.fontSize,
99 | originalBodyFontSize = body && body.style.fontSize,
100 | fakeUsed = false;
101 |
102 | div.style.cssText = "position:absolute;font-size:1em;width:1em";
103 |
104 | if( !body ){
105 | body = fakeUsed = doc.createElement( "body" );
106 | body.style.background = "none";
107 | }
108 |
109 | // 1em in a media query is the value of the default font size of the browser
110 | // reset docElem and body to ensure the correct value is returned
111 | docElem.style.fontSize = "100%";
112 | body.style.fontSize = "100%";
113 |
114 | body.appendChild( div );
115 |
116 | if( fakeUsed ){
117 | docElem.insertBefore( body, docElem.firstChild );
118 | }
119 |
120 | ret = div.offsetWidth;
121 |
122 | if( fakeUsed ){
123 | docElem.removeChild( body );
124 | }
125 | else {
126 | body.removeChild( div );
127 | }
128 |
129 | // restore the original values
130 | docElem.style.fontSize = originalHTMLFontSize;
131 | if( originalBodyFontSize ) {
132 | body.style.fontSize = originalBodyFontSize;
133 | }
134 |
135 |
136 | //also update eminpx before returning
137 | ret = eminpx = parseFloat(ret);
138 |
139 | return ret;
140 | },
141 |
142 | //enable/disable styles
143 | applyMedia = function( fromResize ){
144 | var name = "clientWidth",
145 | docElemProp = docElem[ name ],
146 | currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
147 | styleBlocks = {},
148 | lastLink = links[ links.length-1 ],
149 | now = (new Date()).getTime();
150 |
151 | //throttle resize calls
152 | if( fromResize && lastCall && now - lastCall < resizeThrottle ){
153 | w.clearTimeout( resizeDefer );
154 | resizeDefer = w.setTimeout( applyMedia, resizeThrottle );
155 | return;
156 | }
157 | else {
158 | lastCall = now;
159 | }
160 |
161 | for( var i in mediastyles ){
162 | if( mediastyles.hasOwnProperty( i ) ){
163 | var thisstyle = mediastyles[ i ],
164 | min = thisstyle.minw,
165 | max = thisstyle.maxw,
166 | minnull = min === null,
167 | maxnull = max === null,
168 | em = "em";
169 |
170 | if( !!min ){
171 | min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
172 | }
173 | if( !!max ){
174 | max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
175 | }
176 |
177 | // if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true
178 | if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
179 | if( !styleBlocks[ thisstyle.media ] ){
180 | styleBlocks[ thisstyle.media ] = [];
181 | }
182 | styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
183 | }
184 | }
185 | }
186 |
187 | //remove any existing respond style element(s)
188 | for( var j in appendedEls ){
189 | if( appendedEls.hasOwnProperty( j ) ){
190 | if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){
191 | head.removeChild( appendedEls[ j ] );
192 | }
193 | }
194 | }
195 | appendedEls.length = 0;
196 |
197 | //inject active styles, grouped by media type
198 | for( var k in styleBlocks ){
199 | if( styleBlocks.hasOwnProperty( k ) ){
200 | var ss = doc.createElement( "style" ),
201 | css = styleBlocks[ k ].join( "\n" );
202 |
203 | ss.type = "text/css";
204 | ss.media = k;
205 |
206 | //originally, ss was appended to a documentFragment and sheets were appended in bulk.
207 | //this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one!
208 | head.insertBefore( ss, lastLink.nextSibling );
209 |
210 | if ( ss.styleSheet ){
211 | ss.styleSheet.cssText = css;
212 | }
213 | else {
214 | ss.appendChild( doc.createTextNode( css ) );
215 | }
216 |
217 | //push to appendedEls to track for later removal
218 | appendedEls.push( ss );
219 | }
220 | }
221 | },
222 | //find media blocks in css text, convert to style blocks
223 | translate = function( styles, href, media ){
224 | var qs = styles.replace( respond.regex.comments, '' )
225 | .replace( respond.regex.keyframes, '' )
226 | .match( respond.regex.media ),
227 | ql = qs && qs.length || 0;
228 |
229 | //try to get CSS path
230 | href = href.substring( 0, href.lastIndexOf( "/" ) );
231 |
232 | var repUrls = function( css ){
233 | return css.replace( respond.regex.urls, "$1" + href + "$2$3" );
234 | },
235 | useMedia = !ql && media;
236 |
237 | //if path exists, tack on trailing slash
238 | if( href.length ){ href += "/"; }
239 |
240 | //if no internal queries exist, but media attr does, use that
241 | //note: this currently lacks support for situations where a media attr is specified on a link AND
242 | //its associated stylesheet has internal CSS media queries.
243 | //In those cases, the media attribute will currently be ignored.
244 | if( useMedia ){
245 | ql = 1;
246 | }
247 |
248 | for( var i = 0; i < ql; i++ ){
249 | var fullq, thisq, eachq, eql;
250 |
251 | //media attr
252 | if( useMedia ){
253 | fullq = media;
254 | rules.push( repUrls( styles ) );
255 | }
256 | //parse for styles
257 | else{
258 | fullq = qs[ i ].match( respond.regex.findStyles ) && RegExp.$1;
259 | rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
260 | }
261 |
262 | eachq = fullq.split( "," );
263 | eql = eachq.length;
264 |
265 | for( var j = 0; j < eql; j++ ){
266 | thisq = eachq[ j ];
267 |
268 | if( isUnsupportedMediaQuery( thisq ) ) {
269 | continue;
270 | }
271 |
272 | mediastyles.push( {
273 | media : thisq.split( "(" )[ 0 ].match( respond.regex.only ) && RegExp.$2 || "all",
274 | rules : rules.length - 1,
275 | hasquery : thisq.indexOf("(") > -1,
276 | minw : thisq.match( respond.regex.minw ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
277 | maxw : thisq.match( respond.regex.maxw ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
278 | } );
279 | }
280 | }
281 |
282 | applyMedia();
283 | },
284 |
285 | //recurse through request queue, get css text
286 | makeRequests = function(){
287 | if( requestQueue.length ){
288 | var thisRequest = requestQueue.shift();
289 |
290 | ajax( thisRequest.href, function( styles ){
291 | translate( styles, thisRequest.href, thisRequest.media );
292 | parsedSheets[ thisRequest.href ] = true;
293 |
294 | // by wrapping recursive function call in setTimeout
295 | // we prevent "Stack overflow" error in IE7
296 | w.setTimeout(function(){ makeRequests(); },0);
297 | } );
298 | }
299 | },
300 |
301 | //loop stylesheets, send text content to translate
302 | ripCSS = function(){
303 |
304 | for( var i = 0; i < links.length; i++ ){
305 | var sheet = links[ i ],
306 | href = sheet.href,
307 | media = sheet.media,
308 | isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
309 |
310 | //only links plz and prevent re-parsing
311 | if( !!href && isCSS && !parsedSheets[ href ] ){
312 | // selectivizr exposes css through the rawCssText expando
313 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
314 | translate( sheet.styleSheet.rawCssText, href, media );
315 | parsedSheets[ href ] = true;
316 | } else {
317 | if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) ||
318 | href.replace( RegExp.$1, "" ).split( "/" )[0] === w.location.host ){
319 | // IE7 doesn't handle urls that start with '//' for ajax request
320 | // manually add in the protocol
321 | if ( href.substring(0,2) === "//" ) { href = w.location.protocol + href; }
322 | requestQueue.push( {
323 | href: href,
324 | media: media
325 | } );
326 | }
327 | }
328 | }
329 | }
330 | makeRequests();
331 | };
332 |
333 | //translate CSS
334 | ripCSS();
335 |
336 | //expose update for re-running respond later on
337 | respond.update = ripCSS;
338 |
339 | //expose getEmValue
340 | respond.getEmValue = getEmValue;
341 |
342 | //adjust on resize
343 | function callMedia(){
344 | applyMedia( true );
345 | }
346 |
347 | if( w.addEventListener ){
348 | w.addEventListener( "resize", callMedia, false );
349 | }
350 | else if( w.attachEvent ){
351 | w.attachEvent( "onresize", callMedia );
352 | }
353 | })(this);
354 |
--------------------------------------------------------------------------------
/test/test.css:
--------------------------------------------------------------------------------
1 | /*
2 | This is just a test file for making sure the script is working properly.
3 | If it is, the media queries below will change the body's background color depending on the browser width.
4 | For a realistic use case for media queries: read up on Responsive Web Design:
5 | http://www.alistapart.com/articles/responsive-web-design/
6 | */
7 |
8 | body {
9 | background: black;
10 | color: #333;
11 | font-family: Helvetica, sans-serif;
12 | }
13 | p {
14 | width: 60%;
15 | min-width: 18.75em; /* 300px @ 16px */
16 | max-width: 43.75em; /* 700px @ 16px */
17 | margin: 2em auto;
18 | background: #fff;
19 | padding: 20px;
20 | }
21 | a {
22 | color: #333;
23 | }
24 |
25 | /* hide the attribute-test element. test2.css will show it */
26 | #attribute-test {
27 | display: none;
28 | }
29 |
30 | /*styles for 300 and up @ 16px!*/
31 | /* The max-width declaration below blocks this from ever working */
32 | @media only screen and (min-width: 18.75em){
33 | body {
34 | background: yellow;
35 | }
36 | }
37 |
38 |
39 | /*styles for 480px - 620px @ 16px!*/
40 | @media only screen and (min-width: 30em) and (max-width: 38.75em) {
41 | body {
42 | background: green;
43 | }
44 | }
45 |
46 |
47 |
48 |
49 | @media screen and (min-width: 38.75em),only print,projector{body{background:red;}}
50 |
51 | /*styles for 800px and up @ 16px!*/
52 | @media screen and (min-width: 50em){
53 | body {
54 | background: blue;
55 | }
56 | }
57 |
58 | /*styles for 1100px and up @ 16px!*/
59 | @media screen and (min-width: 68.75em){
60 | body {
61 | background: orange;
62 | }
63 | }
64 |
65 | /*one with pixels too! */
66 | /* NOTE - if the user were to increase his browser font size to 20px (chrome: Large),
67 | the above (68.75em) media query will be incorrectly ignored!!!
68 |
69 | Assuming 20px browser setting, we would expect to see this progression:
70 | yellow > green > red > blue > NAVY > orange
71 |
72 | However, the orange never kicks in... which seems like a browser bug!
73 | Here's the math (assuming 20px browser setting):
74 | 1200/20 = 60em < 68.75em
75 | */
76 | @media screen and (min-width: 1200px){
77 | body {
78 | background: navy;
79 | }
80 | }
81 |
82 | @media only screen and (min-width: 1250px) and (min--moz-device-pixel-ratio: 1.5),
83 | only screen and (min-width: 1250px) and (-moz-min-device-pixel-ratio: 1.5),
84 | only screen and (min-width: 1250px) and (-o-min-device-pixel-ratio: 3/2),
85 | only screen and (min-width: 1250px) and (-webkit-min-device-pixel-ratio: 1.5),
86 | only screen and (min-width: 1250px) and (min-device-pixel-ratio: 1.5),
87 | only screen and (min-width: 1250px) and (min-resolution: 1.5dppx),
88 | screen and (min-width: 1250px) {
89 |
90 | body {
91 | background-color: pink;
92 | }
93 | }
--------------------------------------------------------------------------------
/test/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Respond JS Test Page
6 |
7 |
8 |
9 |
10 |
11 |
This is just a visual test file, and an ugly one at that! For unit tests, visit the Respond.js unit test suite
12 |
13 |
The media queries in the included CSS file simply change the body's background color depending on the browser width. If you see any colors aside from black, then the media queries are working in your browser. You can resize your browser window to see it change on the fly.