一、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. 高通msm mdm 总结

    1. svn 获取工程代码命令:svn co svn+ssh://10.20.30.18/svn-repos/msm8916/branches/LA1.1-CS-r113502.2 2. 如何确定那些 ...

  2. linux系统分区参考

    UPDATE: update is used to download package information from all configured sources. UPGRADE:  upgrad ...

  3. Deep Learning基础--机器翻译BLEU与Perplexity详解

    前言 近年来,在自然语言研究领域中,评测问题越来越受到广泛的重视,可以说,评测是整个自然语言领域最核心和关键的部分.而机器翻译评价对于机器翻译的研究和发展具有重要意义:机器翻译系统的开发者可以通过评测 ...

  4. SpringMVC_HelloWorld_03

    通过注解的方式实现一个简单的HelloWorld. 源码 一.新建项目 同SpringMVC_HelloWorld_01 不同的是springmvc配置文件的命名和路径,此处为src/springmv ...

  5. reverse和reverse_copy函数的应用

    reverse函数的作用是:反转一个容器内元素的顺序.函数参数:reverse(first,last);//first为容器的首迭代器,last为容器的末迭代器.它没有任何返回值. 这个函数比较简单, ...

  6. HDU 4725 The Shortest Path in Nya Graph(spfa+虚拟点建图)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4725 题目大意:有n层,n个点分布在这些层上,相邻层的点是可以联通的且距离为c,还有额外给出了m个条边 ...

  7. python discover 函数介绍

    discover(start_dir,pattern='test*.py',top_level_dir=None)找到指定目录下所有测试模块,并可递归查到子目录下的测试木块,只有匹配到的文件名才会被加 ...

  8. 深度揭秘阿里移动端高性能动态化方案Weex

    2016年Qcon大会首日,阿里巴巴资深总监.淘宝移动平台.阿里百川负责人庄卓然宣布移动端高性能动态化方案Weex即时内测,并将于6月开源.此消息一出,群情汹涌,在座的程序猿.攻城狮们纷纷拿起手机扫码 ...

  9. C++实践积累

    C++ STL vector 如何彻底清空一个vector? 实践证明,vector.clear()并不能把vector容量清空,只会让vector.size()变为零,依然很占内存.那如何让vect ...

  10. python调用api方式

    1.shell版本 #!/bin/bash #根据api提供商,获取指定时间格式 datestr=`xxx` #根据api提供商,获取指定加盐密码格式 pwdstr=`xxx` curl -s -X ...