先說說響應式佈局的一些基本認識:css
響應式佈局的表現是:網頁經過css媒介查詢判斷可視區域的寬度,在不一樣的範圍應用不一樣的樣式,以便在不一樣尺寸的設備上呈現最佳的界面效果。典型的例子是,有一個商品列表頁,應用響應式佈局後,可能在pc上是用4列展現,在平板上用3列展現,在手機上只用1列展現。這種佈局的最大好處就是節省人力、資源和時間,因此不少公司都喜歡用。而響應式佈局有兩個必須的要求:html
1)是viewport的設置,width跟initial-scale要採用以下配置,保證viewport的寬度與device width相同:node
2)是要利用media query,針對不一樣的width範圍,編寫不一樣的css,好比bootstrap:android
須要注意的是:第(1)個要求提到的device width與media query裏面的device-width屬性表達的意思有些區別:第(1)個要求提到的device width在移動設備下指的是設備的寬度,可是在pc下指的是瀏覽器可視區域的寬度,好比下面這個網頁,我把瀏覽器窗口縮小,而後你看它viewport裏儘管已經把width設置成了device-width,可是網頁大小卻不是個人桌面的分辨率寬度(設備寬度):web
media query裏的device-width屬性,始終指的是設備的寬度。因此響應式佈局的媒介查詢要用width屬性,不用device-width屬性,由於在桌面設備下,把瀏覽器窗口縮小的時候,device-width並不會發生改變,當調整瀏覽器窗口大小就看不到響應式的效果。chrome
再來看lib-flexible的特色:bootstrap
lib-flexible在適配的時候會修改viewport的initial-scale,致使viewport的width不等於device width。這是採用lib-flexible,在iphone6 plus下適配後,自動添加的viewport設置代碼:瀏覽器
在這個viewport的做用下,網頁的縮放係數爲0.3333333333333333,iphone6 plus的device width爲414個不縮放的css像素,通過縮放以後,viewport的width等於device width / 0.3333333333333333,爲1242個縮放後的css像素,遠遠大於device width:app
假如你的網頁想同時使用響應式佈局和lib-flexible,而後你寫了一個媒介查詢,須要在1024px以上的分辨率(桌面設備)呈現某個特殊樣式(代碼僅僅是爲了舉例):webapp
會發現這個頁面在iphone6 plus下也會應用到該媒介查詢的樣式:
究其緣由是:iphone6 plus下的網頁因爲lib-flexible的做用,致使頁面的width與實際物理分辨率的寬相等,也就是1242個像素,徹底達到了該媒介查詢的範圍。
因此,在使用lib-flexible的項目裏很難再實現響應式佈局,要是有人有這種綜合二者一塊兒使用的想法,可得注意了。實際上,這兩個方案本質性的東西就不相同,適用的場景也不相同。響應式佈局的目的是一套代碼,可以在手機平板和pc上都能良好展示,適用於網站類的項目,而lib-flexible解決的是手機端網頁的適配問題,壓根無論平板和pc的狀況,適用於web app類的項目。
web app有時候會設計出一些特別細的線條或者邊框,若是咱們直接經過css設置邊框爲1px:
結果會發現這種邊框在手機裏看起來的效果,顯得特別地粗,之因此會有這個效果,緣由很簡單,由於如今大部分手機的分辨率很高,一個css像素,好比上面代碼中的1px,可能至關於2個甚至3個物理分辨率像素,而不像pc,一個css像素始終等於1個物理分辨率像素,因此手機裏看到的1px會比實際的粗。
爲了解決這個問題,你可能會想到用0.5px來代替1px,不過這個是解決不了問題的,並且帶小數的像素在不一樣的瀏覽器下絕對是一個坑,千萬要儘可能避免。
那麼一般在web app下顯示1px的作法是怎樣的呢,前陣子在weui的源碼中看到了一個很好的辦法,值得分享:
這個辦法並非利用border屬性來顯示邊框,而是利用了僞類和transform,最妙的是這個transform,0.5px辦不到的事情,它卻辦獲得。
因爲lib-flexible在適配的時候,會縮放網頁,致使css代碼中的1px等於物理分辨率的1px,這樣子這個1px邊框的問題在通過lib-flexible適配的設備下就很好解決了,直接應用border: 1px solid;便可。可是lib-flexible如今只適配了iphone設備,安卓設備壓根沒適配:
致使在安卓設備下,1px的邊框問題依然存在。因此爲了在lib-flexible的項目裏解決1px的問題,就得綜合兩種作法了:
這個作法,我作過測試,在我devicePixelRatio爲3的meilan note上,顯示出的線條很是細膩,看起來很舒服,iphone的效果也不錯,借別人的機子測試過,因此有興趣的人能夠借鑑使用,有問題儘管提出,看看能不能有更好的辦法解決。這是我用魅藍note作測試的截圖:
第1根線是上面的mixin效果;第二根線是直接使用border: 1px solid的效果。
注:以上提到的這個1px邊框的作法有三個缺點,在使用的時候須要注意:
1)它會佔用掉before僞類
2)無法作圓角
3)很難實現多條邊框,除非嵌套,或者再利用上after僞類。
儘管如此,以上這個作法仍是很是有用的作法,由於這種細線邊框屬於比較特殊的設計要求,並非每處邊框都得作成這樣,在開發webapp的時候用這個方法保證特殊線條的設計要求,其它的邊線,我以爲直接用border並無關係,你能夠直接用你的手機打開bootstrap的官方頁面,看它裏面的按鈕邊框,效果都還不錯。
幾年以前,retina屏,也就是所謂的高清屏,還不像如今這麼廣泛,12年我買的第一個安卓機是華爲u8825d,分辨率只有480*800,並且當時市面上大部分安卓機基本上都是這個分辨率,像iphone4 那種640*960級別的機子不多,爲了解決普通背景圖片在iphone4下顯示模糊的問題,基本都是採用這種作法:
估計當時應該是320的設計稿,img_1x.png是在320設計稿下切出的圖,而後img_2x.png是在320設計稿矢量放大2倍後切出的圖,高清屏顯示img_2x.png,這樣就能解決當時iphone4背景圖片模糊的問題。
時至今日,手機都是走高配置,低價格的發展路線,480*800這種級別的機子,市面上愈來愈少,大部分手機的分辨率級別都達到了iphone4的標準,比iphone4的清晰級別更高的手機也愈來愈多,一個800塊的魅藍note,它的devicePixelRatio都已經達到了3,原先解決background-image問題的方法,須要調整一下才能適用於如今:
代碼中的2x和3x是至關於320的設計稿而言的,2x代替了原先的1x,3x代替了原先的2x。如今的設計稿也再也不是320,而是640,2x就是在640下切出的圖,3x是在640基礎上矢量放大1.5切出的圖。在這個代碼的做用下,分辨率在640如下的設備都會顯示2x的圖,因爲2x的圖自己是在640的設計稿切出的,因此這些設備下不會有模糊的現象,在640以上的分辨率,會顯示3x的圖,因爲3x的圖是在960的分辨率下切出的,因此這種圖在分辨率小於960的設備下都不會模糊。之前1x的狀況根本不用再考慮了,之後不會再有須要1x圖的設備,說不定過幾年,市面上的手機全是devicePixelRatio在2.5以上的標準時,連2x的狀況也不用考慮了。
lib-flexible在iphone6推出以後,把設計稿的尺寸提升到了750,切圖時仍是按2x和3x的方法來切,這樣的話,通過lib-flexible適配的設備,分辨率在750如下都會顯示2x的圖,確定不會模糊;分辨率在750以上的設備,會顯示3x的圖,也不會出現模糊。不過因爲lib-flexible只適配了iphone的問題,因此我上篇博客中提到的用data-dpr來顯示不一樣的圖片的作法是錯誤的,由於有些安卓機,好比個人魅族node,devicePixelRatio是3,打開app頁面,看到的圖片卻仍然仍是2x的,顯然達不到適配的要求,因此不能用data-dpr去適配,而應該採用下面這個作法:
這個代碼的最終效果是:
1)devicePixelRatio大於等於2.5的設備都會應用到3x圖
2)其它設備都會應用到2x的圖。
這個方法,在chrome的模擬器裏測試過不少機型,效果不錯,不過它只適用於不使用雪碧圖的背景圖片,若是要在lib-flexible的項目裏使用雪碧圖做背景圖片,同時又要考慮retina屏的話,須要將上面這個方法稍微改動一下。
首先看下不使用lib-flexible時,雪碧圖背景在retina下是怎麼作的,以騰訊的一個活動頁面來講明http://qzs.qq.com/qzone/qzact/act/qzapp/qzone5.0/mobile/index.html,這是它在使用1x的雪碧圖時某個元素的background的樣式:
這是它在使用2x的雪碧圖時某個元素的background的樣式:
總結下它這個作法:
1)先把設計稿切出的圖,合併成一張雪碧圖,騰訊這個例子的設計稿是320的,因此它的切圖都是1x的,這張雪碧圖也就是1x的,大小爲643 * 152
2)設計稿放大2倍,切圖合併成一張2x的雪碧圖,大小爲1286 * 304
3)普清屏下只應用background-image和background-position屬性,設置1x雪碧圖做爲背景,代碼參考截圖
4)高清屏下除了應用background-image和background-position屬性,還要應用background-size屬性,而且這個background-size的大小要設置爲1x雪碧圖的大小,background-position的值要與(3)裏配置的值相同,代碼參考截圖。
若是把它作成一個mixin的話應該是相似這樣的:
考慮到1x不會再有的狀況,上面這個mixin能夠再調整一下:
默認用2x的圖,devicePixelRatio大於等於2.5的設備用3x的圖。這個調整後的mixin就是lib-flexible下,使用雪碧圖背景的方法,應用舉例:
sprite.png用750設計稿的切圖合併後的大小是414 * 232,.btn-android這個按鈕的position爲0 –64px。
儘管這個方法看起來完美,可是不建議使用,由於它的適配效果很差,這是iphone6下的效果:
看起來不錯,那是固然的,由於這就是它默認沒有任何縮放的效果。而後看iphone6 plus的效果:
這就不能忍了,樣式差的離譜。形成這個差別的緣由也很簡單,就是rem的反作用,騰訊的頁面裏全部position,size都是不帶小數的數值,並且2x跟1x之間是整數的翻倍,而不是3x跟2x之間的1.5倍,lib-flexible會致使大部分的設備下position和size都是小數數值,因此很難保證背景圖片縮放後還能經過position顯示到正確的位置:
從網頁優化的角度來講,減小請求數,減小請求數據大小是兩個基本的思路,雪碧圖就是一個減小請求數可是不能減小請求數據量的方法。lib-flexible不能使用兼容3x屏的雪碧圖的狀況看起來是它一個大的缺陷,但實際上也並不是如此:雪碧圖若是用不了,就採用別的思路來優化,我能想到的更好的就是圖片的延遲加載和懶加載,在app頁面裏控制好默認只加載首屏的圖片,而且採用延遲和懶加載的方式,避免阻塞頁面的加載,也能有極好的用戶體驗,打開手機淘寶的頁面給人的感受就是如此,並且你去看看手機淘寶的應用會發現它根本就沒有用雪碧圖,可是速度仍是很快。