1. 程式人生 > >ie相容響應式佈局的實現總結 和 針對ie瀏覽器的CSS

ie相容響應式佈局的實現總結 和 針對ie瀏覽器的CSS

ie瀏覽器hack
.demo {
	padding:10px;
	padding:9px\9; /* all ie */
	padding:8px\0; /* ie8-9 目前應用於IE8的單獨hack,情況比較少 */
	*padding:5px; /* ie6-7 */
	+padding:7px; /* ie7 */
	_padding:6px; /* ie6 */
}這是所有ie的hack了,360用的ie核心,跟本機的ie有關係

雖然說響應式設計的理想狀態是,需對pc/移動各種終端進行響應;但是現實是高解析度的pc端與手機終端螢幕相差太大,像電商這樣有大量圖片和文字資訊的同時排版要求精準的頁面,設計一個同時適應高解析度pc又適合小尺寸的手機終端是挑戰;同時高解析度下pc頁面資訊量巨大,對於手機端使用者是否需要,也許會造成頻寬浪費;再者手機終端和pc終端的使用者操作習慣也相差甚大,這種多圖多資訊量要求精準的頁面,設計出來恐怕會是2個完全不同的版本,也許各自維護更方便。由於業務形態原因,隨著使用者解析度的提高,1024×768已不再是主流,寬屏使用者比例越來越大,因此我們的響應式考慮如何充分利用PC使用者裝置上更多空間而設計。下圖為淘寶使用者的螢幕解析度和瀏覽器比例,鑑於ie8-瀏覽器目前佔比約70%,mediaquery的ie8-相容迫於現實還是要做,淚……

media query簡介

1.link標籤方式

<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 }
}

媒體型別有很多種:‘aural’, ‘braille’, ‘handheld’, ‘print’, ‘projection’,‘screen’, ‘tty’, ‘tv’、‘embossed’、‘speech’、’3d-glasses’,但最常用的是screen和print,對於前端們來講最常用的應該只有screen了。應用於所有媒體型別可以用all,省略不寫預設就是all。media query支援很多表達式,常用的如下,

完整的檢視這裡

@mediaall and (min-width: 400px) and (max-width: 700px) {}
@mediaall and (orientation: portrait) {   }
@mediaand (min-device-width: 800px) { }

利用media query可以輕鬆實現不同螢幕寬度時切換不同的頁面佈局,但是很不幸ie8及以下都還不支援mediaquery,於是開始了下面的media query相容之旅……

目前實現media query ie相容的庫比較成熟的有respond.jscss3-mediaqueries-js它們各有優劣

,respond.js 壓縮後1k,只實現了mediaquery中最常用的min-widthmax-width的相容;css3-mediaqueries-js基本實現了所有css3規範中的mediaquery特性的相容,所以導致壓縮有16k,測試反饋其效能遠低於respond.js;不過確實一淘首頁2次響應式設計均只需用到max-width和min-width,Modernizr H5BP也均推薦使用respond.js,下面具體看看它們的實現吧

respond.js原始碼分析

使用方式 1.在css中正常用 min/max-width media queries @mediascreen and (min-width: 480px){ ...stylesfor 480pxand up go here } 2.引入respond.min.js,但要在css的後面(越早引入越好,在ie下面看到頁面閃屏的概率就越低,因為最初css會先渲染出來,如果respond.js載入得很後面,這時重新根據mediaquery解析出來的css會再改變一次頁面的佈局等,所以看起來有閃屏的現象)

實現思路

  • 1.把head中所有的css路徑取出來放入陣列
  • 2.然後遍歷陣列一個個發ajax請求
  • 3.ajax回撥後僅分析response中的mediaquery的min-width和max-width語法,分析出viewport變化區間對應相應的css塊
  • 4.頁面初始化時和window.resize時,根據當前viewport使用相應的css塊。
window.matchMedia = window.matchMedia ||(function(doc, undefined){
  var bool,
      docElem = doc.documentElement,
      refNode = docElem.firstElementChild || docElem.firstChild,
      //fakeBody required for
      fakeBody= doc.createElement_x('body'),
      div     = doc.createElement_x('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);
//檢測是否支援mediaquery,檢測css是否有效的方法都差不多,建立一個元素應用該css後檢測元素寬度,然後清除該元素。
<pre name="code" class="css">.......
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 forIE;約定將原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-widthmin-width的邏輯了;可以看出這裡必須依賴ajax請求css路徑才能得到css檔案中的mediaquery的內容,那ajax的跨域問題就要解決了;由於我們的靜態資源都是要放cdn的,respond.js也給出了跨域方法,即引入代理頁面。

//把cross-domain/respond-proxy.html放到cdn上
//把cross-domain/respond.proxy.gif放到當前域伺服器上
"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跨域實現是通過代理頁面將獲取到的css,再通過window.name通訊實現;如在respond.proxy.js中

function checkFrameName() {
    varcssText;
 
    try{
        cssText= iframe.contentWindow.name;
                varnow = 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之間(每次重新整理結果不一樣).

測試結果發現,重新整理頁面後會有明顯的閃屏(以該測試demo為例,一開始頁面背景是黑色的,這是預設css中的,跨域js執行完成後分析出mediaquery中的該viewport尺寸下應該應用red的背景,所以又變成紅色),間隔時間為500ms以上。所以體驗不是很好,而且該場景中ajax跨域目前已經沒有更好的實現方式,500ms間隔的閃屏避免不了。

同時因為是ajax請求css,所以會因為響應式而額外產生一個請求,好在之前css請求過一遍,這次ajax請求是讀取瀏覽器快取中的.


respond.js總結

  • 優點:壓縮後僅1k,不跨域時效能ok,只需引入respond.js通用易用
  • 缺點:僅支援mediaquery的min-width和max-width(用於響應式夠用);支援跨域,雖然配置有點麻煩,實現跨域代價高而且有閃屏體驗欠佳。

css3-mediaqueries-js原始碼分析

css3-mediaqueries-js官方文件和demo都沒有,相對於respond.jscss3-mediaqueries-js支援幾乎所有的media query的語法,訪問測試demo

實現邏輯

其實現邏輯和respond.js差不多,只是更加支援的mediaquery更加全面,同時支援內聯style,支援各種寬度單位(em|ex|px|in|cm|mm|pt|pc),但是這裡的初始化是在domready後執行,為了讓使用者感覺不出頁面有閃屏(之前應用初始化樣式然後js提取mediaquery中的樣式再覆蓋一遍)現象,這裡的實現是先將html移出可視區域外,等解析完mediaquery後再重置回來,但實際目測感覺稍有閃屏(當然這裡的測試是測試body背景色,移出可視區域外不管用,當然絕大部分響應式場景是適用的),實現如下:

//prevent jumping of layout by hiding everything beforepainting 先將html移出可視區域外
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 width
    if(ua.ie) {
        docEl.style.width= '1px';
    }
    setTimeout(function() {
        docEl.style.width= ''; // undowidth
        docEl.style.marginLeft= ''; // undohide
        varnow = new Date().getTime();
        varuseTime = now - initTime;
        alert('mediaquery生效時間:'+useTime+'ms');
    },0);
    //remove this listener to prevent following execution
    cssHelper.removeListener('cssMediaQueriesTested',arguments.callee);
});

其餘實現和respond.js基本一致,也需要使用ajax,所以css3-media-queries.js本身不支援跨域,當然非要支援跨域也可以,也可以像respond.js一樣使用代理頁面跨域即可,但也會出現閃屏的現象。還是先看看不跨域情況下,大多數人為什麼選擇respond.js,主要原因還是完美支援的mediaquery特性導致壓縮後16K,下載和執行時間都遜於respond.js.

css3-mediaqueries-js總結

  • 優點:1、基本支援所有css3中的media query語法
  • 缺點:1、不支援跨域(如cdn),就算支援了跨域也存在閃屏現象;2、和respond.js對比效能較差

全域性切換class

因為css/js需要放到cdn上面,需要跨域,css3-mediaqueries-js不支援跨域,respond.js支援跨域但是實現跨域後效能較差,有閃屏體驗也差,而且配置麻煩,不方便各個業務通用。對比respond.js和css3-mediaqueries-js可知,實現響應式應用min-width和max-width足矣;同時模擬mediaquery的效果只需要在2個關鍵時間點根據viewport切換css(初始化頁面時和window.resize)即可。所以可以選擇切換csslink,可以動態切換css塊,也可以切換class

  • 切換csslink(優點:邏輯清晰;缺點:增加請求數,維護麻煩,如修改一個模組涉及到3個尺寸的響應,至少需要改3個檔案)
"stylesheet" type="text/css"media="screenand (max-width: 990px)" href="respond750.css&uuot;>
stylesheet"type="text/css" media="screen and(max-width: 1200px)"href="respond990.css">

  • 切換內聯css塊(respond.js和css3-mediaqueries-js就是通過js分析出mediaquery然後自動根據當前viewport切換css塊,這個理想環境下是最好的,自動分析只管寫mediaquery,但是依賴ajax獲取css內容,跨域實現成本高體驗也不好)
  • 全域性切換class(特別是初始化頁面時最好在頁面內容未開始渲染之前切換class,不然會出現像韓國naver購物頻道在寬屏時重新整理效果,重新整理時內容由中間向外偏),特定viewport用特殊全域性class標記,響應式樣式繼承在該class下,實現大致如下:

實現方式

@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這種方式維護也是個問題,首先是js分散2處,body最上方切換全域性class,domready時window.resize時切換class,同時響應式尺寸增加時,需要改變js判斷條件;再看css的維護,mediaquery一份,加全域性class一份相同的,維護需要同時修改2次,初期media query幾十行也能接受,但是後來改版mediaquery幾百行,這樣維護成本就大大增加了,全域性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;
      }
    }
  }
}
/*這樣只需維護上面一處程式碼即可*/
#channels > .w1200;
@media (max-width:1119px){
  #channels> .w990;
}
@media (max-width:989px){
  #channels> .w750;
}
.w990{
  #channels> .w990;
}
.w750{
  #channels> .w750;
}

目前一淘新首頁採用以上方法維護,支援1200px、990px、750px三個尺寸的響應,不得不承認維護成本還是偏高,歡迎各種改進建議,

相關推薦

ie相容響應佈局實現總結 針對ie瀏覽器CSS

ie瀏覽器hack .demo { padding:10px; padding:9px\9; /* all ie */ padding:8px\0; /* ie8-9 目前應用於IE8的單獨hack,情況比較少 */ *padding:5px; /* ie6

關於響應佈局總結px,em與rem

1.px  在Web頁面初期製作中我們都是用px來設定我們的文字的,因為它比較穩定和準確。但是當用戶在瀏覽器中瀏覽我們製作的Web頁面時,它改變了瀏覽器的字型大小,會使Web頁面佈局被打破。這樣對於那些關心自己網站可用性的客戶來說,就是一個大問題了。因此,這時就提出了使用e

響應佈局設計指南教程(1)--響應時代的設計歷程

如果你還沒有接觸過響應式佈局,你得先明白響應式佈局和之前用的佈局方式稍稍有些不同,因為響應式佈局的目的是為了使網頁適應不同裝置,你需要一段時間的學習來最終實現一個響應式佈局的網頁。 我想展示一些舊的設計流程帶來的問題,在此基礎上引入一些新的方法和工具,在這個過程中,你將在學

頁面居中、響應佈局總結

一、水平居中(父容器和子容器的寬度都是不一定的) 1.inline-block+text-align 如果不希望元素內的文字水平居中,那麼需要在child中設定text-align為left。 2.table+margin 只需要設定子元

響應佈局實現方法

1,響應式佈局:簡而言之,就是一個網站能夠相容多個終端——而不是為每個終端做一個特定的版本。這個概念是為解決移動網際網路瀏覽而誕生的。 2,實現響應式佈局的三種方式     1. CSS3-Medi

原生JS相容所有瀏覽器獲取瀏覽器高度寬度,響應佈局 js 獲取瀏覽器高度寬度值(相容瀏覽器)

var width = window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;

響應佈局實現方法原理

昨天我在馬海祥部落格上跟大家詳細的介紹過《什麼是響應式網頁設計?》,我覺的響應式網頁設計不僅僅是一種趨勢,還更是一個新的設計解決方案!它有助於解決不同的解析度和裝置(臺式電腦,膝上型電腦,平板,手機)相關的設計問題。既然是設計的問題,這裡就會涉及到很多層面的角色,包括互動

響應布局想法實現

收藏 後退 append pre complete 一個 reat time rec 看過這篇文章,寫的挺全面, 從幾個方面分析響應式寫法優劣,先收藏: http://caibaojian.com/web-app-rem.html 最終方案: //designWidt

笨鳥兒 靜態佈局、自適應佈局、流佈局響應佈局、彈性佈局等的概念區別

一、靜態佈局(Static Layout) 即傳統Web設計,網頁上的所有元素的尺寸一律使用px作為單位。 1、佈局特點:不管瀏覽器尺寸具體是多少,網頁佈局始終按照最初寫程式碼時的佈局來顯示。常規的pc的網站都是靜態(定寬度)佈局的,也就是設定了min-width,這樣的話,如果小於這個寬度就會

CSS3 - 使用彈性盒子(Flex Box)實現完美居中、柵格系統及響應佈局

CSS3彈性盒子介紹 彈性盒子是 CSS3 的一種新的佈局模式。 CSS3 彈性盒( Flexible Box 或 flexbox),是一種當頁面需要適應不同的螢幕大小以及裝置型別時確保元素擁有恰當的行為的佈局方式。 引入彈性盒佈局模型的目的是提供一種更加有效的方式來對一個容器中的子

移動端流體佈局響應佈局注意事項——day nine

流體佈局: 什麼是流體佈局? 流體是採用了一些設定,當寬度大於多少時怎麼展示,小於多少時怎麼展示,而且展示的方式向水流一樣,一部分一部分的載入 移動端有兩種設計方式: 全屏設計,在 PC 端和 PAD 平板也可以無縫瀏覽,但圖片卻會失真。 固屏設計、雖然會留有白邊,

@media 相容ie8-CSS3響應佈局(@media screen)相容IE6-8的方法 (IE9以下)

最近做了一個響應式網站,主要用到了CSS3裡的@media screen,今天無意用IE8打開發現網站竟然不正常,才知道原來IE8不相容響應式@media screen呢。下面跟大家分享下青島星網的解決方法。 我看了下IE6-IE8下載入網站,網站不能正常顯示的主要原因就是沒有載入成功CSS,也

rem實現簡單的響應佈局

rem是什麼? rem(font size of the root element)是指相對於根元素的字型大小的單位。簡單的說它就是一個相對單位。看到rem大家一定會想起em單位,em(font size of the 

如何根據不同裝置型別快速地實現網頁介面的響應佈局,只需一句程式碼立馬實現

在學習網頁製作的過程中,如何根據不用的裝置讓網頁介面能夠顯示出最佳的效果,這是讓廣大初學者為之煩惱的事情,但是今天如果你看了這篇博文,你的憂慮將一掃而光,會讓你感受到前端的樂趣。 首先,如何實現這樣的佈局呢?只需要一句程式碼就能實現,接下來讓我們看一下吧! 當我們在進行程式碼編寫時,我們只需要這樣編寫:

一行css程式碼輕鬆實現前端響應佈局(vw+rem)

大家知道rem可以用來做響應式佈局,只是html元素上的font-size樣式需要根據螢幕寬度來指定。 之前有用@media媒體查詢,根據各種螢幕寬度寫html的樣式,也用過類似lib-flexible這樣的js庫動態改變html樣式,總覺得挺麻煩的。 今天突然想到vw這個單位,發現用它來做響應式佈局實在

表現層響應響應佈局螢幕適配佈局

1.響應式佈局:     響應式佈局是根據瀏覽器寬度,解析度,橫屏,豎屏等情況來自動改變元素展示的一種佈局方式,一般可以使用柵格方式來實現,一般有兩種思路,一種是桌面端瀏覽器優先,擴充套件到移動端瀏覽器適配,另一種是以移動端優先,擴充套件到桌面瀏覽器適配。由於移動端網路和計算

Bootstrap框架響應佈局

彈性佈局 1.浮動+百分比佈局 2.FIex佈局 Flex佈局對於設計比較複雜的頁面非常有用,實現螢幕和瀏覽器視窗大小發生變化時保持元素的相對位置和大小不變 響應式佈局 Responsive design,意在實現不同螢幕解析度的終端上瀏覽網頁的不同展示方式。通過響應式設計能使網站在

響應佈局自適應佈局詳解

注:響應式佈局等於流動網格佈局,而自適應佈局等於使用固定分割點來進行佈局。 自適應佈局給了你更多設計的空間,因為你只用考慮幾種不同的狀態。而在響應式佈局中你卻得考慮上百種不同的狀態。雖然絕大部分狀態差異較小,但仍然也算做差異。它使得把握設計最終效果變得更難,同樣讓響

@media 相容ie8-CSS3響應佈局(@media screen)相容IE6-8的方法 (IE9以下)

最近做了一個響應式網站,主要用到了CSS3裡的@media screen,今天無意用IE8打開發現網站竟然不正常,才知道原來IE8不相容響應式@media screen呢。下面跟大家分享下青島星網的解決方法。 我看了下IE6-IE8下載入網站,網站不能正常顯示的主要原因就是

通過媒體查詢實現響應頁面學習總結

如有錯誤歡迎指正與批評 對於響應式頁面,我個人的理解就是一種可以根據瀏覽器的屬性進行相應的佈局和屬性的變化的web頁面,它可以通過媒體查詢的形式來實現 媒體查詢 媒體查詢就是根據設定斷點檢測媒體的各種屬性,然後相應地執行某一段程式碼端的功能 它的基本格式是: