移動端web開發的設計稿與工作流

致謝

一直以來移動端適配便是困擾自己的一個難題,今天休息,查閱了很多資料將其整理出來。本文中很多做法是直接借鑒了網上的文章,主要有從網易與淘寶的font-size思考前端設計稿與工作流手機端頁面自適應解決方案—rem布局進階版(附源碼示例),向大神致謝。

移動設備的分辨率

設備 屏幕尺寸 邏輯分辨率(pt) Reader 物理分辨率(px)
iPhone 3GS 3.5寸 320*480 @1x 320*480
iPhone 4/4S 3.5寸 320*480 @2x 640*960
iPhone 5/5S/5C 4.0寸 320*568 @2x 640*1136
iPhone 6/6S 4.7寸 375*667 @2x 750*1134
iPhone 6/6S Plus 5.5寸 414*736 @3x 1242*2208
  1. pt是邏輯分辨率,簡單理解就是跟屏幕的尺寸有關系,是個長度跟視覺的單位。
  2. px是物理分辨率,簡單理解為像素點,跟屏幕的尺寸是沒關系的。

小結:pt與px的關系是,一個單位的pt里包含幾個px,包含的px越多,則越清晰。但因為人視網膜的關系,最多只能識別單位pt里2個像素點,大于2個像素點,人眼識別不出,所以6plus看上去不會比6更清晰。

移動端web開發的設計稿與工作流

移動端web開發的難點之一是適應各種分辨率的移動設備——眾所周知,應該使用rem。
但實際操作中,如何確定html上的font-size,是一個難點。一般有以下幾種方式:

使用CSS3媒體查詢

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

用CSS3媒體查詢明顯不足有:

  1. 需要寫大量的媒體查詢以適應不同的設備
  2. 媒體查詢的范圍不一定合適
  3. 每個媒體查詢里的font-size難以定義
  4. 每次給元素設置rem都需要根據某個分辨率html的font-size去算,工作量大。

小結:CSS3媒體查詢理論上可以,但操作起來不靈活

簡單問題簡單解決

有些web app比較簡單,記住一個開發原則就好:文字流式,控件彈性,圖片等比縮放。以圖描述:


移動端布局1.png

網易的做法

網易的頁面復雜度較高,隨著分辨率增大,網易頁面的效果也會發生明顯變化,要達到這種效果,就需要使用rem作為單位,且<font color="red">html的font-size是通過js計算出來的。</font>
網易移動web的工作流可以總結如下:

第一步 設置視口的viewport

<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">

第二步 以iphone6/6S設計稿為基準確定body及頁面元素的尺寸

網易網頁的設計稿是基于iphone6/6S,物理分辨率(設計稿寬度)為750px,邏輯分辨率(deviceWidth)為375。
為了計算方便,先拿設計稿豎著的橫向分辨率除以100得到body元素的寬度:750 / 100 = 7.5rem
同理,布局時頁面上的元素的尺寸,可以拿設計圖標注的尺寸除以100得到。

第三步 計算html的fontSize以適配各個尺寸的屏幕

    document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';

第四步 細節調整

當deviceWidth大于設計稿的橫向分辨率時,html的font-size始終等于橫向分辨率/body元素寬。

之所以這么干,是因為當deviceWidth大于640時,則物理分辨率大于1280,應該去訪問pc網站了。只需將第三步做下調整即可。

    var deviceWidth = document.documentElement.clientWidth;
    if(deviceWidth > 640) deviceWidth = 640;
    document.documentElement.style.fontSize = deviceWidth / 6.4 + 'px';

可能需要額外的媒介查詢

網頁上有一些結構是不需要隨著屏幕變大而相應調整,比如底部導航欄,此時可以使用媒體查詢。

淘寶的做法

知識預備,了解viewport

通常我們采用如下代碼設置viewport:

    <meta name="viewport"   content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

這樣整個網頁在設備內顯示時的頁面寬度就會等于設備邏輯像素大小,也就是device-width。這個device-width的計算公式為:設備的物理分辨率/(devicePixelRatio * scale)

devicePixelRatio稱為設備像素比,每款設備的devicePixelRatio都是已知,并且不變的,目前高清屏,普遍都是2,不過還有更高的,比如2.5,3等。淘寶觸屏版布局的前提就是viewport的scale根據devicePixelRatio動態設置.

  • 在devicePixelRatio為2的時候,scale為0.5
  • 在devicePixelRatio為3的時候,scale為0.3333

這么做目的是為了保證頁面的大小與設計稿保持一致,比如如果是750的橫向物理分辨率,那么實際頁面的device-width也等于750。

接下來要解決的問題是:
元素的尺寸該如何計算,比如說設計稿上某一個元素的寬為150px,換算成rem應該怎么算呢?這個值等于設計稿標注尺寸/該設計稿對應的html的font-size。拿淘寶來說的,他們用的設計稿是750的,所以html的font-size就是75,如果某個元素時150px的寬,換算成rem就是150 / 75 = 2rem。

第一步 動態設置viewport的scale

    var scale = 1 / devicePixelRatio;
    document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

第二步 動態計算html的font-size

    document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

因為第一步已經根據devicePixelRatio動態設置scale,此時device-width便等于頁面的橫向物理分辨率(document.documentElement.clientWidth),也就是設計稿的的橫向物理分辨率。
淘寶的做法是,設計稿是750,那么html的font-size就是75。

第三步 確定布局時各個元素的尺寸

布局的時候,各元素的css尺寸 = 設計稿標注尺寸/設計稿橫向分辨率/10 = 設計稿標注尺寸/html的font-size

第四步 細節調整

  1. font-size可能需要額外的媒介查詢,并且font-size不使用rem,這一點跟網易是一樣的。
  2. 跟網易一樣,淘寶也設置了一個臨界點,當設備豎著時橫向物理分辨率大于1080時,html的font-size就不會變化了,原因也是一樣的,分辨率已經可以去訪問電腦版頁面了。

與網易的做法比較

共同點:

  1. 都能適配所有的手機設備,對于pad,網易與淘寶都會跳轉到pc頁面,不再使用觸屏版的頁面
    都需要動態設置html的font-size
  2. 布局時各元素的尺寸值都是根據設計稿標注的尺寸計算出來,由于html的font-size是動態調整的,所以能夠做到不同分辨率下頁面布局呈現等比變化
  3. 容器元素的font-size都不用rem,需要額外地對font-size做媒介查詢
  4. 都能應用于尺寸不同的設計稿,只要按以上總結的方法去用就可以了

不同點

  1. 淘寶還需要動態設置viewport的scale,網易不用
  2. 網易的做法,rem值很好計算,淘寶的做法可能需要使用less和sass的css處理器

阿里團隊的高清方案布局

高清方案的源碼

    'use strict';

    /**
     * @param {Boolean} [normal = false] - 默認開啟頁面壓縮以使頁面高清;  
     * @param {Number} [baseFontSize = 100] - 基礎fontSize, 默認100px;
     * @param {Number} [fontscale = 1] - 有的業務希望能放大一定比例的字體;
     */
    const win = window;
    export default win.flex = (normal, baseFontSize, fontscale) => {
      const _baseFontSize = baseFontSize || 100;
      const _fontscale = fontscale || 1;

      const doc = win.document;
      const ua = navigator.userAgent;
      const matches = ua.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i);
      const UCversion = ua.match(/U3\/((\d+|\.){5,})/i);
      const isUCHd = UCversion && parseInt(UCversion[1].split('.').join(''), 10) >= 80;
      const isIos = navigator.appVersion.match(/(iphone|ipad|ipod)/gi);
      let dpr = win.devicePixelRatio || 1;
      if (!isIos && !(matches && matches[1] > 534) && !isUCHd) {
        // 如果非iOS, 非Android4.3以上, 非UC內核, 就不執行高清, dpr設為1;
        dpr = 1;
      }
      const scale = normal ? 1 : 1 / dpr;

      let metaEl = doc.querySelector('meta[name="viewport"]');
      if (!metaEl) {
        metaEl = doc.createElement('meta');
        metaEl.setAttribute('name', 'viewport');
        doc.head.appendChild(metaEl);
      }
      metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`);
      doc.documentElement.style.fontSize = normal ? '50px' : `${_baseFontSize / 2 * dpr * _fontscale}px`;
    };

原理

與上述淘寶的原理一致。
動態設置 html 的font-size, 同時根據設備DPR調整頁面的縮放值,此時device-width便等于頁面的橫向物理分辨率(document.documentElement.clientWidth),也就是設計稿的的橫向物理分辨率。

優勢

  1. 引用簡單,布局簡便
  2. 根據設備屏幕的DPR,自動設置最合適的高清縮放。
  3. 保證了不同設備下視覺體驗的一致性。(老方案是,屏幕越大元素越大;此方案是,屏幕越大,看的越多)
  4. 有效解決移動端真實1px問題(這里的1px 是設備屏幕上的物理像素)

使用

此方案也是默認 1rem = 100px,布局時,根據設計稿尺寸/100即可得到物理分辨率的尺寸

注意事項

  1. 如果元素的寬度超過效果圖寬度的一半(效果圖寬為640或750),果斷使用百分比寬度,或者flex布局。可以避免類似于在 iphone6 上沒問題, 在 iphone5上會有橫向滾動條的問題
  2. 此方案是根據設備的dpr動態設置html的font-size,且默認DPR是2,1rem = 100px,如果設計稿是iphone 6 sp (dpr = 3),將代碼的最后的flex(false, 100, 1)修改成flex(false, 66.66667, 1)

如何與設計師協作

手機淘寶團隊適配協作模式.png
  1. 視覺設計階段,設計師按寬度750px(iPhone 6)做設計稿,除圖片外所有設計元素用矢量路徑來做。設計定稿后在750px的設計稿上做標注,輸出標注圖。同時等比放大1.5倍生成寬度1125px的設計稿,在1125px的稿子里切圖。
  2. 輸出兩個交付物給開發工程師:一個是程序用到的@3x切圖資源,另一個是寬度750px的設計標注圖。之所以要在@3x的圖里切,這是因為現在市面上也有不少像魅藍note這種超高清屏幕,devicePixelRatio已經達到3了,這個切圖保證在所有設備都清晰顯示。
  3. 開發工程師拿到750px標注圖和@3x切圖資源,完成iPhone6(375pt)的界面開發,需要使用上文提到的適配方法。
  4. 適配調試階段,基于iPhone 6的界面效果,分別向上向下調試iPhone 6 plus(414pt)和iPhone 5S及以下(320pt)的界面效果。由此完成大中小三屏適配。
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容