ie兼容响应式布局的实现总结 和 针对ie浏览器的CSS
參考鏈接:http://zhidao.baidu.com/link?url=bQioDKMnG_eQoE6dCxzd2hPtMyiB7phu6hBdOupn1Pjk1hV-ItXFZS5GDUBoH5qrfi9LXkUoSciXTiGN36G6LK
參考鏈接:http://blog.sina.com.cn/s/blog_601b97ee0101aszo.html
雖然說響應(yīng)式設(shè)計(jì)的理想狀態(tài)是,需對pc/移動(dòng)各種終端進(jìn)行響應(yīng);但是現(xiàn)實(shí)是高分辨率的pc端與手機(jī)終端屏幕相差太大,像電商這樣有大量圖片和文字信息的同時(shí)排版要求精準(zhǔn)的頁面,設(shè)計(jì)一個(gè)同時(shí)適應(yīng)高分辨率pc又適合小尺寸的手機(jī)終端是挑戰(zhàn);同時(shí)高分辨率下pc頁面信息量巨大,對于手機(jī)端用戶是否需要,也許會(huì)造成帶寬浪費(fèi);再者手機(jī)終端和pc終端的用戶操作習(xí)慣也相差甚大,這種多圖多信息量要求精準(zhǔn)的頁面,設(shè)計(jì)出來恐怕會(huì)是2個(gè)完全不同的版本,也許各自維護(hù)更方便。由于業(yè)務(wù)形態(tài)原因,隨著用戶分辨率的提高,1024×768已不再是主流,寬屏用戶比例越來越大,因此我們的響應(yīng)式考慮如何充分利用PC用戶設(shè)備上更多空間而設(shè)計(jì)。下圖為淘寶用戶的屏幕分辨率和瀏覽器比例,鑒于ie8-瀏覽器目前占比約70%,mediaquery的ie8-兼容迫于現(xiàn)實(shí)還是要做,淚……
media query簡介
miediaquery有2種引入方式:1.link標(biāo)簽方式
<link "stylesheet" type="text/css"media="screen" href="sans-serif.css"> <link "stylesheet" type="text/css"media="print" href="serif.css">2.css方式
@mediascreen {* { font-family: sans-serif } }媒體類型有很多種:‘a(chǎn)ural’, ‘braille’, ‘handheld’, ‘print’, ‘projection’,‘screen’, ‘tty’, ‘tv’、‘embossed’、‘speech’、’3d-glasses’,但最常用的是screen和print,對于前端們來講最常用的應(yīng)該只有screen了。應(yīng)用于所有媒體類型可以用all,省略不寫默認(rèn)就是all。media query支持很多表達(dá)式,常用的如下,完整的查看這里:
@mediaall and (min-width: 400px) and (max-width: 700px) {} @mediaall and (orientation: portrait) { } @mediaand (min-device-width: 800px) { }利用media query可以輕松實(shí)現(xiàn)不同屏幕寬度時(shí)切換不同的頁面布局,但是很不幸ie8及以下都還不支持mediaquery,于是開始了下面的media query兼容之旅……
目前實(shí)現(xiàn)media query ie兼容的庫比較成熟的有respond.js和css3-mediaqueries-js;它們各有優(yōu)劣,respond.js 壓縮后1k,只實(shí)現(xiàn)了mediaquery中最常用的min-widthmax-width的兼容;css3-mediaqueries-js基本實(shí)現(xiàn)了所有css3規(guī)范中的mediaquery特性的兼容,所以導(dǎo)致壓縮有16k,測試反饋其性能遠(yuǎn)低于respond.js;不過確實(shí)一淘首頁2次響應(yīng)式設(shè)計(jì)均只需用到max-width和min-width,Modernizr 和 H5BP也均推薦使用respond.js,下面具體看看它們的實(shí)現(xiàn)吧
respond.js源碼分析
使用方式官方demo地址:http://scottjehl.github.com/Respond/test/test.html
1.在css中正常用 min/max-width media queries ????@mediascreen and (min-width: 480px){ ????????...stylesfor 480pxand up go here ????} 2.引入respond.min.js,但要在css的后面(越早引入越好,在ie下面看到頁面閃屏的概率就越低,因?yàn)樽畛鮟ss會(huì)先渲染出來,如果respond.js加載得很后面,這時(shí)重新根據(jù)mediaquery解析出來的css會(huì)再改變一次頁面的布局等,所以看起來有閃屏的現(xiàn)象)實(shí)現(xiàn)思路
- 1.把head中所有的css路徑取出來放入數(shù)組
- 2.然后遍歷數(shù)組一個(gè)個(gè)發(fā)ajax請求
- 3.ajax回調(diào)后僅分析response中的mediaquery的min-width和max-width語法,分析出viewport變化區(qū)間對應(yīng)相應(yīng)的css塊
- 4.頁面初始化時(shí)和window.resize時(shí),根據(jù)當(dāng)前viewport使用相應(yīng)的css塊。
其余的代碼就是ajax實(shí)現(xiàn)和translate media query的max-widthmin-width的邏輯了;可以看出這里必須依賴ajax請求css路徑才能得到css文件中的mediaquery的內(nèi)容,那ajax的跨域問題就要解決了;由于我們的靜態(tài)資源都是要放cdn的,respond.js也給出了跨域方法,即引入代理頁面。
//把cross-domain/respond-proxy.html放到cdn上 //把cross-domain/respond.proxy.gif放到當(dāng)前域服務(wù)器上 "http://externalcdn.com/respond-proxy.html"id="respond-proxy" rel="respond-proxy" />"/path/to/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" />"/path/to/respond.proxy.js">這里ajax跨域?qū)崿F(xiàn)是通過代理頁面將獲取到的css,再通過window.name通信實(shí)現(xiàn);如在respond.proxy.js中
function checkFrameName() {varcssText;try{cssText= iframe.contentWindow.name;varnow = new Date().getTime(),useTime = now - initTime;alert('獲取css耗時(shí):'+useTime + 'ms');}catch(e) { }if(cssText) {……//銷毀之前用于通信的iframe,后續(xù)回調(diào)callbackcallback(cssText);}else{win.setTimeout(checkFrameName,100);} } win.setTimeout(checkFrameName, 500);//500ms后確認(rèn)內(nèi)部iframe的name值是否傳遞過來,后續(xù)再更新當(dāng)前viewport該用的css。因?yàn)閷?shí)現(xiàn)跨域代理的問題,初始化頁面時(shí)應(yīng)用上全部css耗時(shí)較長,以下光測試從開始執(zhí)行該js文件到css取回調(diào)用之前的耗時(shí)為500ms-515ms之間(每次刷新結(jié)果不一樣).
測試結(jié)果發(fā)現(xiàn),刷新頁面后會(huì)有明顯的閃屏(以該測試demo為例,一開始頁面背景是黑色的,這是默認(rèn)css中的,跨域js執(zhí)行完成后分析出mediaquery中的該viewport尺寸下應(yīng)該應(yīng)用red的背景,所以又變成紅色),間隔時(shí)間為500ms以上。所以體驗(yàn)不是很好,而且該場景中ajax跨域目前已經(jīng)沒有更好的實(shí)現(xiàn)方式,500ms間隔的閃屏避免不了。
同時(shí)因?yàn)槭莂jax請求css,所以會(huì)因?yàn)轫憫?yīng)式而額外產(chǎn)生一個(gè)請求,好在之前css請求過一遍,這次ajax請求是讀取瀏覽器緩存中的.
respond.js總結(jié)
- 優(yōu)點(diǎn):壓縮后僅1k,不跨域時(shí)性能ok,只需引入respond.js通用易用
- 缺點(diǎn):僅支持mediaquery的min-width和max-width(用于響應(yīng)式夠用);支持跨域,雖然配置有點(diǎn)麻煩,實(shí)現(xiàn)跨域代價(jià)高而且有閃屏體驗(yàn)欠佳。
css3-mediaqueries-js源碼分析
css3-mediaqueries-js官方文檔和demo都沒有,相對于respond.jscss3-mediaqueries-js支持幾乎所有的media query的語法,訪問測試demo
實(shí)現(xiàn)邏輯
其實(shí)現(xiàn)邏輯和respond.js差不多,只是更加支持的mediaquery更加全面,同時(shí)支持內(nèi)聯(lián)style,支持各種寬度單位(em|ex|px|in|cm|mm|pt|pc),但是這里的初始化是在domready后執(zhí)行,為了讓用戶感覺不出頁面有閃屏(之前應(yīng)用初始化樣式然后js提取mediaquery中的樣式再覆蓋一遍)現(xiàn)象,這里的實(shí)現(xiàn)是先將html移出可視區(qū)域外,等解析完mediaquery后再重置回來,但實(shí)際目測感覺稍有閃屏(當(dāng)然這里的測試是測試body背景色,移出可視區(qū)域外不管用,當(dāng)然絕大部分響應(yīng)式場景是適用的),實(shí)現(xiàn)如下:
//prevent jumping of layout by hiding everything beforepainting 先將html移出可視區(qū)域外 var docEl =document.documentElement;docEl.style.marginLeft= '-32767px';//make sure it comes back after a while 異常處理,萬一獲取mediaquerycss失敗,重置回來 setTimeout(function (){docEl.style.marginTop = ''; },20000);……// return visibility after media queries are tested生效后重新可見 cssHelper.addListener('cssMediaQueriesTested', function() {//force repaint in IE by changing widthif(ua.ie) {docEl.style.width= '1px';}setTimeout(function() {docEl.style.width= ''; // undowidthdocEl.style.marginLeft= ''; // undohidevarnow = new Date().getTime();varuseTime = now - initTime;alert('mediaquery生效時(shí)間:'+useTime+'ms');},0);//remove this listener to prevent following executioncssHelper.removeListener('cssMediaQueriesTested',arguments.callee); });其余實(shí)現(xiàn)和respond.js基本一致,也需要使用ajax,所以css3-media-queries.js本身不支持跨域,當(dāng)然非要支持跨域也可以,也可以像respond.js一樣使用代理頁面跨域即可,但也會(huì)出現(xiàn)閃屏的現(xiàn)象。還是先看看不跨域情況下,大多數(shù)人為什么選擇respond.js,主要原因還是完美支持的mediaquery特性導(dǎo)致壓縮后16K,下載和執(zhí)行時(shí)間都遜于respond.js.
css3-mediaqueries-js總結(jié)
- 優(yōu)點(diǎn):1、基本支持所有css3中的media query語法
- 缺點(diǎn):1、不支持跨域(如cdn),就算支持了跨域也存在閃屏現(xiàn)象;2、和respond.js對比性能較差
全局切換class
因?yàn)閏ss/js需要放到cdn上面,需要跨域,css3-mediaqueries-js不支持跨域,respond.js支持跨域但是實(shí)現(xiàn)跨域后性能較差,有閃屏體驗(yàn)也差,而且配置麻煩,不方便各個(gè)業(yè)務(wù)通用。對比respond.js和css3-mediaqueries-js可知,實(shí)現(xiàn)響應(yīng)式應(yīng)用min-width和max-width足矣;同時(shí)模擬mediaquery的效果只需要在2個(gè)關(guān)鍵時(shí)間點(diǎn)根據(jù)viewport切換css(初始化頁面時(shí)和window.resize)即可。所以可以選擇切換csslink,可以動(dòng)態(tài)切換css塊,也可以切換class
- 切換csslink(優(yōu)點(diǎn):邏輯清晰;缺點(diǎn):增加請求數(shù),維護(hù)麻煩,如修改一個(gè)模塊涉及到3個(gè)尺寸的響應(yīng),至少需要改3個(gè)文件)
- 切換內(nèi)聯(lián)css塊(respond.js和css3-mediaqueries-js就是通過js分析出mediaquery然后自動(dòng)根據(jù)當(dāng)前viewport切換css塊,這個(gè)理想環(huán)境下是最好的,自動(dòng)分析只管寫mediaquery,但是依賴ajax獲取css內(nèi)容,跨域?qū)崿F(xiàn)成本高體驗(yàn)也不好)
- 全局切換class(特別是初始化頁面時(shí)最好在頁面內(nèi)容未開始渲染之前切換class,不然會(huì)出現(xiàn)像韓國naver購物頻道在寬屏?xí)r刷新效果,刷新時(shí)內(nèi)容由中間向外偏),特定viewport用特殊全局class標(biāo)記,響應(yīng)式樣式繼承在該class下,實(shí)現(xiàn)大致如下:
實(shí)現(xiàn)方式
@mediascreen and (min-width: 990px) {.content{width:990px;color:red;} } @mediascreen and (min-width: 1200px) {.content{width:1200px;color:green;} } .w990 .content {width: 990px;color: red; } .w1200 .content {width: 1200px;color: green; } "w990"> "content">content全局切換class這種方式維護(hù)也是個(gè)問題,首先是js分散2處,body最上方切換全局class,domready時(shí)window.resize時(shí)切換class,同時(shí)響應(yīng)式尺寸增加時(shí),需要改變js判斷條件;再看css的維護(hù),mediaquery一份,加全局class一份相同的,維護(hù)需要同時(shí)修改2次,初期media query幾十行也能接受,但是后來改版mediaquery幾百行,這樣維護(hù)成本就大大增加了,全局class和media querycopy相同的代碼引入less解決,使用方法如下:
#channels {.w1200(){.etao-channels{padding:170px 0 0 30px;li{margin-right:25px;}}}.w990(){.etao-channels{padding:25px 0 0 15px;li{margin-right:8px;}}.w750(){.etao-channels{padding:5px 00 5px;li{margin-right:5px;}a{color:#333;}}} } /*這樣只需維護(hù)上面一處代碼即可*/ #channels > .w1200; @media (max-width:1119px){#channels> .w990; } @media (max-width:989px){#channels> .w750; } .w990{#channels> .w990; } .w750{#channels> .w750; }目前 一淘新首頁采用以上方法維護(hù),支持1200px、990px、750px三個(gè)尺寸的響應(yīng),不得不承認(rèn)維護(hù)成本還是偏高,歡迎各種改進(jìn)建議,
總結(jié)
以上是生活随笔為你收集整理的ie兼容响应式布局的实现总结 和 针对ie浏览器的CSS的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习之MCMC算法(转载)
- 下一篇: html5/css3响应式布局介绍