Bootstrap裏面就引入了這個js文件,從名字看出來是自適應的兼容。打開IE看了一下,效果挺好的,自適應的效果挺好的。Respond.js讓不支持CSS3 Media Query的瀏覽器包括IE6-IE8等其餘瀏覽器支持查詢。php
1.在css中正經常使用 min/max-width media queries
@media screen and (min-width: 480px){ ...styles for 480px and up go here }
2.引入respond.min.js,但要在css的後面(越早引入越好,在ie下面看到頁面閃屏的機率就越低,由於最初css會先渲染出來,如 果respond.js加載得很後面,這時從新根據media query解析出來的css會再改變一次頁面的佈局等,因此看起來有閃屏的現象)css
實現思路
-
1.把head中全部<link rel=「sheetstyle」 href=「xx」/>的css路徑取出來放入數組
-
2.而後遍歷數組一個個發ajax請求
-
3.ajax回調後僅分析response中的media query的min-width和max-width語法,分析出viewport變化區間對應相應的css塊
-
4.頁面初始化時和window.resize時,根據當前viewport使用相應的css塊。
//檢測是否支持media query,檢測css是否有效的方法都差很少,建立一個元素應用該css後檢測元素寬度,而後清除該元素。 window.matchMedia = window.matchMedia || (function(doc, undefined){ var bool, docElem = doc.documentElement, refNode = docElem.firstElementChild || docElem.firstChild, // fakeBody required for 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 = ''; docElem.insertBefore(fakeBody, refNode); bool = div.offsetWidth == 42; docElem.removeChild(fakeBody); return { matches: bool, media: q }; }; })(document);
....... if( !!href && isCSS && !parsedSheets[ href ] ){ // selectivizr exposes css through the rawCssText expando if (sheet.styleSheet && sheet.styleSheet.rawCssText) { //sheet.styleSheet.rawCssText看不懂,原來是方便selectivizr和respond.js聯用,http://selectivizr.com/tests/respond/ //selectivizr的做用是 CSS3 selectors for IE;約定將原csstext放在styleSheet的link上的擴展屬性rawCssText上;這裏若是聯用selectivizr能夠少次ajax請求 translate( sheet.styleSheet.rawCssText, href, media ); parsedSheets[ href ] = true; } else { if( (!/^([a-zA-Z:]*//)/.test( href ) && !base) || href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){ requestQueue.push( { href: href, media: media } ); } } } .......
其他的代碼就 是ajax實現和translate media query的max-width min-width的邏輯了;能夠看出這裏必須依賴ajax請求css路徑才能獲得css文件中的mediaquery的內容,那ajax的跨域問題就要 解決了;因爲咱們的靜態資源都是要放cdn的,respond.js也給出了跨域方法,即引入代理頁面。html
//把cross-domain/respond-proxy.html 放到cdn上 //把cross-domain/respond.proxy.gif 放到當前域服務器上 <!-- 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>
這裏ajax跨域實現是經過代理頁面將獲取到的css,再經過window.name通訊實現;如在respond.proxy.js中git
function checkFrameName() { var cssText; try { cssText = iframe.contentWindow.name; var now = new Date().getTime(),useTime = now - initTime; alert('獲取css耗時:'+ useTime + 'ms'); } catch (e) { } if (cssText) { ……//銷燬以前用於通訊的iframe,後續回調callback callback(cssText); } else{ win.setTimeout(checkFrameName, 100); } } win.setTimeout(checkFrameName, 500);//500ms後確認內部iframe的name值是否傳遞過來,後續再更新當前viewport該用的css。
由於實現跨域代理的問題,初始化頁面時應用上所有css耗時較長,如下光測試從開始執行該js文件到css取回調用以前的耗時爲500ms-515ms之間(每次刷新結果不同),ie8下測試結果以下 github
測試結果發現,刷新頁面後會有明顯的閃屏(以該測試demo爲例,一開始頁面背景是黑色的,這是默認css中的,跨域js執行完成後分析出 media query中的該viewport尺寸下應該應用red的背景,因此又變成紅色),間隔時間爲500ms以上。因此體驗不是很好,並且該場景中ajax跨 域目前已經沒有更好的實現方式,500ms間隔的閃屏避免不了。ajax
同時由於是ajax請求css,因此會由於響應式而額外產生一個請求,好在以前css請求過一遍,此次ajax請求是讀取瀏覽器緩存中的,以下圖中fiddler的檢測結果中的第三個請求和第六個請求: 跨域
-
優勢:壓縮後僅1k,不跨域時性能ok,只需引入respond.js通用易用
-
缺點:僅支持media query的min-width和max-width(用於響應式夠用);支持跨域,雖然配置有點麻煩,實現跨域代價高並且有閃屏體驗欠佳。