一、前言
在眾多的移動設備中,前端開發人員如何在不同屏幕大小,不同程度的高清屏下去百分百的還原設計稿,從來都不是一件簡單的事情,需要考慮眾多因素,權衡利弊,做出取舍,結合需求去選擇最合適的方案。
之前有一篇:如何設計移動端高清方案
二、面對的問題
在不同大小和高清的屏幕下:
(1)如何保證 頁面布局的一致性:不錯亂,不變形;
(2)如何保證 字體大小的一致性:大屏顯示更大,小屏顯示更小或者更多;
(3)如何保證 1px的邊框一致性:不同的高清屏也能正常顯示1px的高度;
(4)如何正確 圖片清晰度一致性:不停大小和高清屏下都能看到清晰的圖片。
如果把這幾個問題按重要程度排序的話,我想應該是這樣的:
布局 > 字體大小 > 1px邊框 > 高清圖
三、布局
方案一:百分比布局
使用子元素在父元素下的百分比為單位,使用子元素在不同屏幕下寬度表現一致。利用img標簽的特性,只設寬度等圖片加載完,這種方法會導致大量的重排,並且非固定高度會導致懶加載等功能難以實現。
缺點:
(1)寬度是可以隨屏幕適應,但是高度不能,寬屏會被拉伸,具體表現為,iphone4中看到的是正方形,而在iphone6s中會看到長方形。
(2)需要手動計算子元素在父元素下的百分比,計算麻煩。
(3)百分比的大小往往需要精確到小數位6到8位。
方案二:媒體查詢調整
1、一種是結合百分比或者flex布局,對特定的模塊在特定的屏幕寬度范圍內做調整。
2、另外一種是結合rem,對不同的屏幕寬度范圍內的設備設置不同的rem參照字體大小。
html{font-size:10px} @media screen and (min-width:321px) and (max-width:375px){html{font-size:11px}} @media screen and (min-width:376px) and (max-width:414px){html{font-size:12px}} @media screen and (min-width:415px) and (max-width:639px){html{font-size:15px}} @media screen and (min-width:640px) and (max-width:719px){html{font-size:20px}} @media screen and (min-width:720px) and (max-width:749px){html{font-size:22.5px}} @media screen and (min-width:750px) and (max-width:799px){html{font-size:23.5px}} @media screen and (min-width:800px){html{font-size:25px}}
缺點:
無法完全適配到android設備的各種屏幕,無法保證顯示的一致性。比如:定義了一個模塊的高度是321至375下是40px,那么這個模塊在這個范圍內顯示的就是40px,而不是隨着屏幕變化而變化的。
方案三:flex布局
類似於百分比布局,無需計算百分比,可以很好的適配到所有屏幕,手機天貓就是典型的flex布局,flex做了很好的兼容處理,高度寫死,可查看頂部搜索欄的源碼。
缺點:
1、有着和百分比一樣的缺點,高度不便於調整。
2、有幾種不同的flex標准,在低端ios和安卓中有着各種兼容性問題。
方案四:使用rem單位
和上面幾種布局方案結合使用,主要是做高度調整,保證布局一致。
視口不縮放使用rem
分析:
1、根據圖片可以看出網易為750的設計稿,因為750下是html字體大小是100px,這樣在切圖時,方便px轉rem,750設計稿上是大小是50px,那么轉換成rem就是.5rem(如:24px -> .24rem);
2、px轉rem簡單方便;
3、沒有做1px高清屏處理;
4、未做圖片高清處理。
視口縮放下使用rem
分析:
1、設計稿750的
320 dpr=1 font-size=32px
320 dpr=2 font-size=64px
375 dpr=2 font-size=75px
414 dpr=3 font-size=124.2px
換算規則:(屏幕寬度*dpr)/10 (除以10是為了把屏幕分為10份。為了將來替換成vm或者vh單位方便)
2、屏幕根據dpr的值進行了相應的縮放;
3、很好的還原了1px高清屏真實度;
4、圖片使用了750px下的兩倍圖,並沒有做按dpr的值加載不同的圖片;
5、px轉rem需要使用工具轉換。
方案五:使用vw
面對的屏幕的分辨率,DPR,1px,2X圖等一系列問題,不再是使用hack手段處理,而是使用原生的css技術處理。在flexible方案中通過js模擬vw特性,現在vw已經得到眾多瀏覽器的支持,直接使用vw單位在適配的布局中。
vw是viewPort的視窗的長度單位,這里視窗指的是瀏覽器可視化的區域,而這個可視化區域是window.innerWidth/window.innerHeight的大小。
涉及到單位:vw,vh,vmin,vmax。
vw:是viewPort width的簡寫,1vw = window.innerWidth的1%;
vh:類似,1vh = window.innerHeight的1%;
vmin:是當前vw和vh中較小的值;
vmax:是vw的vh中較大的值;
目前出視覺設計稿,我們都是使用750px
寬度的,從上面的原理來看,那么100vw = 750px
,即1vw = 7.5px,我們可以根據設計圖中的px直接轉換成對應的vw值,又要開始計算,我們可以使用postcss的插件postcss-px-to-viewport,我們直接寫px,postcss編譯之后就是我們需要的vw。
實際是喲女的時候,我們可以進行相關參數配置
"postcss-px-to-viewport": { viewportWidth: 750, viewportHeight: 1334, unitPrecision: 5, viewportUnit: 'vw', selectorBlackList: [], minPixelValue: 1, mediaQuery: false }
哪些地方是可以使用vw來適配的?
(1)容器適配,可以使用vw;
(2)文本適配,使用vw;
(3)大於1px的邊框,圓角,陰影都可以使用vw;
(4)內距和外距,可以使用vw;
解決retina下的1px方案,依舊是使用postcss插件,postcss-write-svg,使用postcss-write-svg你可以通過border-image
或者background-image
兩種方式來處理。
.example {
border: 1px solid transparent; border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch; //或者使用background-image //background: white svg(square param(--color #00b1ff)); }
這樣PostCSS會自動幫你把CSS編譯出來:
.example {
border: 1px solid transparent; border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E") 2 2 stretch; // background: white url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%2300b1ff' width='100%25' height='100%25'/%3E%3C/svg%3E"); }
還需要在head中添加
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />
四、我理解的最佳實踐
1、用戶體驗要求很高的頁面,如UV較高的頁面,活動頁這些應該以用戶體驗優先,使用vw是實現頁面的適配,通過postcss-px-to-viewport把px轉換成vw;更好實現長寬比(針對img,video,iframe),通過postcss-aspect-ratio-mini插件實現;為了解決1px的問題,使用post-write-svg,自動生成borde-image或者background-image的圖片。
注意:px轉換成vw,多少會存在一定的像素誤差,無法完全整除。
2、在其他頁面,股東視口,不縮放,使用rem做布局適配,js添加屏幕標識以便調整字體大小,使用@2x圖片,只做ios8+的1px處理
五、參考
1、https://www.w3cplus.com/css/vw-for-layout.html
2、http://coderlt.coding.me/2016/03/08/retina-screen-adapter/