一、stackoverflow上面对css3-mediaqueries.js与respond.js的比较

css3-mediaqueries.js

Pros

Supports min, max and min+max mediaqueries
Supports px and em values
Reacts on window resize
Elaborates on-page CSS (style tag) and external stylesheets

Cons

Doesn't support width mediaquery
Doesn't elaborate link[media="screen and ..."] nor @imported stylesheet

respond.js

Pros

Supports min, max and min+max mediaqueries
Supports px and em values
Reacts on window resize
Elaborates external stylesheets only

Cons

Doesn't support width mediaquery
Doesn't elaborate on-page CSS, link [media="screen and ..."] nor @imported stylesheets
It may cause a javascript error when combined with jQuery on load events, to solve it you need to place the script at the end of the page

二、Respond.js源码分析

https://github.com/scottjehl/Respond

A fast & lightweight polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more)

Respond.js应用的例子,参考http://skinnyties.com

查看skinnyties.com源代码,可以看到

可以在GitHub上可以下载它的未压缩版本respond.src.js(或者将min文件format,不推荐,因为JS压缩后的变量名都是处理过的,不方便阅读),本文使用Fiddler进行本地重定向,分析源码。

1.监听resize事件,以达到改变窗口大小实时响应

function callMedia(){
applyMedia( true );
}
if( win.addEventListener ){
// 标准2级DOM事件模型
win.addEventListener( "resize", callMedia, false );
}
else if( win.attachEvent ){
// IE事件模型(6、7、8)
win.attachEvent( "onresize", callMedia );
}

2.提取CSS文件路径

var doc = win.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" ),
requestQueue = [], // 遍历CSS路径
ripCSS = function(){
for( var i = 0; i < links.length; i++ ){
var sheet = links[ i ],
href = sheet.href,
media = sheet.media,
isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet"; if( !!href && isCSS && !parsedSheets[ href ] ){
// selectivizr exposes css through the rawCssText expando
if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
translate( sheet.styleSheet.rawCssText, href, media );
parsedSheets[ href ] = true;
} else {
// 判断条件:
// 1.有形如http://这样的href需要判断http://后面的根目录是否等于location.host。
// 2.不以形如http://这样开头的href,同时不包含<base>,
// 所以它不支持带有<base>的相对href
if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) ||
href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){
requestQueue.push( {
href: href,
media: media
} );
}
}
}
}
makeRequests();
}

3.发送ajax请求返回CSS内容

// 递归执行获得CSS文本
// 递归配合shift()可以保证最后被遍历的CSS具有最高的优先级
makeRequests = function(){
if( requestQueue.length ){
var thisRequest = requestQueue.shift(); ajax( thisRequest.href, function( styles ){
translate( styles, thisRequest.href, thisRequest.media );
parsedSheets[ thisRequest.href ] = true; // 在递归函数外面包裹一层setTimeout,
// 使得函数以异步的方式执行,防止栈溢出
win.setTimeout(function(){ makeRequests(); },0);
} );
}
}
// ajax方法
ajax = function( url, callback ) {
var req = xmlHttp();
if (!req){
return;
}
req.open( "GET", url, true );
req.onreadystatechange = function () {
if ( req.readyState !== 4 || req.status !== 200 && req.status !== 304 ){
return;
}
callback( req.responseText );
};
if ( req.readyState === 4 ){
return;
}
req.send( null );
}

4.取出CSS中具有形如 @media screen and (max-width: 480px) 的各个块

translate = function( styles, href, media ){
// 匹配各个@media {...}
var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ),
ql = qs && qs.length || 0; //try to get CSS path
href = href.substring( 0, href.lastIndexOf( "/" ) ); var repUrls = function( css ){
return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" );
},
// useMedia=true表示<link>是否具有media属性并且
// CSS样式中没有@media块
useMedia = !ql && media; //if path exists, tack on trailing slash
if( href.length ){ href += "/"; } if( useMedia ){
ql = 1;
} for( var i = 0; i < ql; i++ ){
var fullq, thisq, eachq, eql; //media attr
if( useMedia ){
fullq = media;
rules.push( repUrls( styles ) );
}
// rules保存了每个@media块内部的样式
else{
fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1;
rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
} eachq = fullq.split( "," );
eql = eachq.length; for( var j = 0; j < eql; j++ ){
thisq = eachq[ j ];
// 所有media块
mediastyles.push( {
media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all",
// 对应media块在rules数组中的样式
rules : rules.length - 1,
hasquery : thisq.indexOf("(") > -1,
minw : thisq.match( /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
maxw : thisq.match( /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
} );
}
} applyMedia();
}

5.将匹配的样式加入文档中

applyMedia = function( fromResize ){
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(); // 函数节流,延迟调用
if( fromResize && lastCall && now - lastCall < resizeThrottle ){
win.clearTimeout( resizeDefer );
resizeDefer = win.setTimeout( applyMedia, resizeThrottle );
return;
}
else {
lastCall = now;
}
// 遍历所有media
for( var i in mediastyles ){
if( mediastyles.hasOwnProperty( i ) ){
var thisstyle = mediastyles[ i ],
min = thisstyle.minw,
max = thisstyle.maxw,
minnull = min === null,
maxnull = max === null,
em = "em"; // 支持以em为单位的宽度,定义了一个getEmValue方法计算em能换算成多少px if( !!min ){
min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
}
if( !!max ){
max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
} // 筛选宽度匹配的样式
if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
if( !styleBlocks[ thisstyle.media ] ){
styleBlocks[ thisstyle.media ] = [];
}
styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
}
}
} // 删除已存在的respond样式
for( var j in appendedEls ){
if( appendedEls.hasOwnProperty( j ) ){
if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){
head.removeChild( appendedEls[ j ] );
}
}
} // 在文档中插入respond样式
for( var k in styleBlocks ){
if( styleBlocks.hasOwnProperty( k ) ){
var ss = doc.createElement( "style" ),
css = styleBlocks[ k ].join( "\n" ); ss.type = "text/css";
ss.media = k; // originally, ss was appended to a documentFragment and sheets were appended in bulk.
// 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!
head.insertBefore( ss, lastLink.nextSibling ); if ( ss.styleSheet ){
// IE下
ss.styleSheet.cssText = css;
}
else {
ss.appendChild( doc.createTextNode( css ) );
} //存储在appendedEls中,下次以便跟踪删除
appendedEls.push( ss );
}
}
}

三、Respond.js带来的跨域请求问题

Respond.js通过ajax请求CSS文件,所以如果CSS文件存放在CDN上面(或者子域中),那么需要引入一个代理页面实现跨域连接。

GitHub地址

引入方法:

<!-- Respond.js proxy on external server -->
<link href="http://externalcdn.com/respond-proxy.html" id="respond-proxy" rel="respond-proxy" /> <!-- Respond.js redirect location on local server -->
<link href="/path/to/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" /> <!-- Respond.js proxy script on local server -->
<script src="/path/to/respond.proxy.js"></script>

Media Queries之Respond.js的更多相关文章

  1. Respond.js – 让不懂爱的 IE6-8 支持 CSS3 Media Query

    respond.min.js <script src="js/respond.min.js"></script> respond.min.js代码: /*! ...

  2. IE9中Media queries在iframe无效的解决方法

    在css中有5个media querie @media screen and(min-width:0px)and(max-width:319px){ body {background-color:re ...

  3. Respond.js – 让 IE6-8 支持 CSS3 Media Query

    Respond.js 是一个快速.轻量的 polyfill,用于为 IE6-8 以及其它不支持 CSS3 Media Queries 的浏览器提供媒体查询的 min-width 和 max-width ...

  4. Respond.js让IE6-8支持CSS3 Media Query

    原文地址:http://caibaojian.com/respondjs.html   使用方式   官方demo地址:http://scottjehl.github.com/Respond/test ...

  5. css3 @media支持ie8用respond.js 解决IE6~8的响应式布局问题

    respond.js插件实现原理 接下来,需要理解respond.js的实现思路: 第一步,将head中所有外部引入的CSS文件路径取出来存储到一个数组当中: 第二步,遍历数组,并一个个发送AJAX请 ...

  6. css3的媒体查询(Media Queries)

    我今天就总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. 先看一个简单的例子: <link rel="stylesheet" media="scr ...

  7. CSS3的媒体查询(Media Queries)与移动设备显示尺寸大全

    媒体查询介绍 我今天就总结一下响应式设计的核心CSS技术Media(媒体查询器)的用法. 先看一个简单的例子: <link rel="stylesheet" media=&q ...

  8. 第11章 Media Queries 与Responsive 设计

    Media Queries--媒体类型(一) 随着科学技术不断的向前发展,网页的浏览终端越来越多样化,用户可以通过:宽屏电视.台式电脑.笔记本电脑.平板电脑和智能手机来访问你的网站.尽管你无法保证一个 ...

  9. Respond.js的作用

    在html页面中我们经常看到 <!--[if lt IE 9]>    //判断当前浏览器的版本是否小于IE 9          <script src="https:/ ...

随机推荐

  1. python使用unittest模块selenium访问斗鱼获取直播信息

    import unittest from selenium import webdriver from bs4 import BeautifulSoup as bs class douyu(unitt ...

  2. 013 GC机制

    本文转自:https://www.cnblogs.com/shudonghe/p/3457990.html 最近还是在找工作,在面试某移动互联网公司之前认为自己对Java的GC机制已经相当了解,其他面 ...

  3. Jmeter命令行选项

    示例:jmeter.bat -n -j %tmp%\%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2%%time:~ ...

  4. 《跟老齐学Python Django实战》读后感

    1.说一下这本书,讲解的很细致,内容选取足够入门Django. 2.在学习这本书要注意的几点: <1>如果你想跟着敲这本书的代码必须要安装:Django版本1.10.1(当然也可以玩玩新版 ...

  5. fsarchiver创建系统镜像(dd命令也可以)

    fsarchiver简介 fsarchiver可以将整个文件系统的内容保存成一个压缩形式的归档文件,包含文件系统本身.所以用来做系统镜像是一个不错的选择,一旦系统崩溃但可以进入救援模式,我们就可以使用 ...

  6. 发布PHP项目(nginx+PHP7+mysql 5.6)

    一.环境检查 1.检查nginx ps -ef | grep "nginx" 显示如下内容则代表nginx启动正常 root 3285 1 0 12:57 ? 00:00:00 n ...

  7. Photon3Unity3D.dll 解析三——OperationRequest、OperationResponse

    OperationRequest 代表Operation操作的Request,包含Code和Parameters OperationCode  Byte类型的值,代表操作,由LiteOpCode定义了 ...

  8. bind1st bind2nd的使用

    STL中的函数 bind1st. bind2nd用于将一个二元算子转换成一元算子,需要两个 参数,要转换的bf和一个值v. 参考:http://blog.csdn.net/simahao/articl ...

  9. Python股票信息抓取(三)

    最近在看mongodb,然后会用了一些最简单的mongodb的操作,然后想着结合股票信息的数据的抓取,然后将数据存储在mongodb中,对于mongo和数据库的最大的区别是,mongo不需要建表,直接 ...

  10. golang基础之三-字符串,时间,流程控制,函数

    strings和strconv的使用 strings strings.HasPrefix(s string,preffix string) bool:判断字符串s是否以prefix开头 stirngs ...