寒冬winter 發佈在像winter同樣冷2015年8月7日view:70095HTML5CSSCSS3移動開發css
在文章任何區域雙擊擊便可給文章添加【評註】!浮到評註點上能夠查看詳情。html
看到小黑的文章 關於webapp中的文字單位的一些搗騰 感受很贊。尤爲是,他提到了手機淘寶的meta,因此以爲要講講咱們這方面的一些實踐。git
手機淘寶從2014年中開始,全面推行flexible設計。什麼叫flexible呢?其實flexible就是responsive的低端形態和基礎。對咱們來講,最直觀的感覺就是,在超寬屏幕上,網頁顯示不會兩邊留白。之前pc時代你們常常講的流體佈局,其實就是一種flexible design。只不過,流體的表述角度是實現,flexible的表述角度是結果,爲了跟高大上的responsive保持一致,咱們這裏使用了flexible這個說法。github
討論方案以前,須要先了解三個關鍵概念:web
單位英寸像素數(Pixel Per Inch,PPI):現實世界的一英寸內像素數,決定了屏幕的顯示質量app
設備像素比率(Device Pixel Ratio,DPR):物理像素與邏輯像素(px)的對應關係webapp
分辨率(Resolution):屏幕區域的寬高所佔像素數佈局
當咱們決定不一樣屏幕的字體和尺寸的單位時,屏幕的這幾個參數很是重要。字體
場景1——Resolution適配flex
一張banner圖片,當你面對不一樣的屏幕時你但願它的行爲是怎樣的?
在這個場景中,咱們主要須要面對的是分辨率適配問題,考慮到多數網頁都是縱向滾動的,在不一樣的屏幕尺寸下,banner的行爲應該是老是鋪滿屏幕寬度以及老是保持寬高比。
最天然的思路是使用百分比寬度,可是假如使用百分比寬度,即width:100%,咱們又有兩種思路來實現固定寬高比:一是利用img標籤的特性,只設寬度等圖片加載完,這種方法會致使大量的重排,而且非固定高度會致使懶加載等功能難以實現,因此果斷放棄;二是使用before僞元素的margin撐開高度,這種方法是比較乾淨的純css實現,可是不具有任何複用性並且要求特定html結構,因此也只好放棄了。
因而,剩下最合適的辦法是使用其它相對單位,原本最合適的單位是vw,它的含義是視口寬度,可是這個單位存在嚴重的兼容問題,因此也只好放棄。
最後咱們只好配合js來作,硬算也是一條路,可是一樣不具有任何可複用性,最終咱們選擇了rem,咱們用js給html設置一個跟屏幕寬度成正比的font-size,而後把元素寬高都用rem做爲單位。
這是咱們目前的線上方案了,它是一個近乎Hack的用法,已知的問題包括:
某些Android機型會丟掉rem小數部分
佔用了rem單位
不是純css方案
場景2——PPI適配
一段文字,當你面對不一樣的屏幕時你但願它的行爲是怎樣的?
顯然,咱們在iPhone3G和iPhone4的Retina屏下面,但願看到的文字尺寸是相同的,也就是說,咱們不但願文字在Retina屏尺寸變小,此外,咱們在大屏手機上,但願看到更多文字,以及,如今絕大多數的字體文件,是自帶一些點陣尺寸的,一般是16px和24px,因此咱們不但願出現13px、15px這樣的奇葩尺寸。
這樣的特徵決定了,場景1中的rem方案,不適合用到段落文字上。因此段落文字應該使用px做爲單位,考慮到Retina,咱們利用media query來指定不一樣的字體,考慮到dpr斷定的兼容性,咱們用寬度替換來代替:
.a {
font-size:12px}
@media (min-width: 401px){
.a {
font-size:24px
}}
另外一種場景,一些標題性文字,但願隨着屏幕寬而增大的,咱們能夠仍然使用rem做爲單位。超過35px(我的直觀感覺)的文字,已經不用太考慮點陣信息了,靠字體的矢量信息也能渲染的很好。
場景3——DPR匹配
一個區塊,設計稿上有1像素邊框,當你面對不一樣的屏幕時你但願它的行爲是怎樣的?
這個場景,需求很簡單,設計師但願在任何屏幕上這條線都是1物理像素。
好吧,固然這個問題的答案不是寫1px那麼簡單。在retina屏下面,若是你寫了這樣的meta
<meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
你將永遠沒法寫出1px寬度的東西,除此以外,inline的SVG等元素,也會按照邏輯像素來渲染,整個頁面的清晰度會打折。
因此,手機淘寶用JS來動態寫meta標籤,代碼相似這樣:
var metaEl = doc.createElement('meta');var scale = isRetina ? 0.5:1;
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');if (docEl.firstElementChild) {
document.documentElement.firstElementChild.appendChild(metaEl);} else {
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
documen.write(wrap.innerHTML);}
結語
總的來講,手機淘寶的flexible方案是綜合運用rem和px兩種單位+js設置scale和html字體。
這些JS的內容,能夠在咱們開源的庫ml中找到: