移動Web佈局

移動Web開發之移動頁面佈局

前言

本文針對手機設備設計的頁面,並不是兼容全設備的響應式佈局,常見的MobileWeb頁面如H5頁面、手機頁面、WAP頁、webview頁面等等。在不一樣尺寸的手機設備上,頁面「相對性的達到合理的展現(自適應)」或者「保持統一效果的等比縮放(看起來差很少)css

深刻概念引出viewport

Pixel

  • 設備像素
    • 在LCD顯示器中,基於點陣排列,每個像素右由紅綠藍子像素組成

    • CRT顯示器html

  • CSS像素(用於控制元素樣式的樣式單位像素,是一個相對值)
    • CSS像素與屏幕像素1:1一樣大小時:前端

    • 瀏覽器窗口寬度必定的狀況下,把頁面放大(Ctrl+),CSS像素(黑色邊框)開始被拉伸,此時1個CSS像素大於1個屏幕像素html5

ppi(Pixel Per Inch)

  • 這裏討論的是隻針對顯示設備(另外還有打印照片時的分辨率、打印精度),指的是屏幕密度。PPI全稱爲Pixel Per Inch,譯爲每英寸像素取值。ppi值越高,單位面積內所佔的像素越多,顯示的畫質越好。
  • PPi中的pixel指的是物理(設備)像素。node


  • ppi是每臺設備的一個定值,一個固定參數,下圖以Samsung Galaxy S4爲例android

  • ppi太高帶來的問題,相同的圖片素材,ppi越高的設備顯示越小。下圖爲一個分辨率像素在屏幕中的位置css3

  • 因爲這樣的問題存在,高ppi(高清屏)設備下的UI會採起必定的縮放比例,讓文本或素材放大(也就是讓分辨率像素或CSS像素放大),下面是CSS像素和物理像素的比例公式:DevicePixelRatio是手機的物理像素與實際使用像素的縮放比(會隨着手機默認縮放比和人爲縮放瀏覽器頁面改變))git

    DevicePixelRatio定義以下:
    
      window.devicePixelRatio = physical pixels / dips(device-independent pixels即CSS像素)

dppx(dots per pixel)

  • 表示單個CSS像素佔用的物理像素個數,與DPR等價,只不過是從微觀的角度。

dpi(Dots per inch)

  • 對於顯示設備的像素密度而言,dpi與ppi是等價的。

CSS Reference Pixel

  • W3C規定(CSS Reference Pixel),把人眼可以辨別到的,距離本身一個手臂長度(約28英寸),像素密度爲96dpi設備上的一個物理像素設爲參考像素(目的是爲了保證CSS像素在不一樣設備、不一樣距離觀測到的大小一致)
  • 經過CSS參考像素能夠計算出在不一樣的設備上使用合適的CSS像素大小,使得視覺上一致。
    github

  • 那麼問題來了,如何實踐這個標準呢?經過使用viewportweb

    <meta name="viewport">

viewport

  • 默認狀況下,手機屏幕以980px去渲染頁面,(下圖圖像爲320px,設備爲iphone4)

  • 此時經過設置渲染寬度爲320px,即爲手機設備的分辨率,此時圖像是充滿整個區域的

  • 經過上面可得,能夠設置width=device-width(手機屏幕分辨率),指定佈局寬度等於手機分辨率寬度,能夠實現
    • 爲移動設備開發的響應式網頁時,你會面臨多重分辨率狀況,沒有必要使用到重量級的mediaquery
    • 避免手機瀏覽器使用桌面分辨率寬度(980px等)去渲染頁面
    • 兼容手機橫屏或豎屏
  • 下面爲viewport的通常設置

    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  • 另外Viewport還分爲兩種,Layout Viewport和Visual Viewport

還原視覺稿,多屏適配

  • 對於移動端開發而言,爲了作到頁面高清的效果,視覺稿的規範每每會遵循如下兩點:
    • 首先,選取一款手機的屏幕寬高做爲基準(之前是iphone4的320×480,如今更多的是iphone6的375×667)。
    • 對於retina屏幕(如: dpr=2),爲了達到高清效果,視覺稿的畫布大小會是基準的2倍,也就是說像素點個數是原來的4倍(對iphone6而言:原先的375×667,就會變成750×1334)。]
  • 字體、高寬間距、圖像(圖標、圖片)
    • 矢量化、字體化、image-set等
    • 在知足快速開發的需求下,利用 css 將圖像限定在元素內( img 圖片使用[max-]width: 100%,背景圖像使用background-size ),佈局只針對元素進行。
  • 幾個問題(詳情
    • retina下,圖片高清問題
    • retina下,border: 1px問題
    • 多屏適配佈局問題
    • 字體大小問題

如下圖爲例,分析移動Web開發在頁面架構和佈局的方法及差別性(效果圖爲640px)

1.固定高度,寬度自適應

  • 實現
    • viewport width 設置爲 device-width,以較小寬度(如 320px)的視覺稿做爲參照進行佈局
    • 垂直方向的高度和間距使用定值,水平方向混合使用定值和百分比或者利用flex彈性佈局
    • 圖像元素根據容器使用定值或background-size縮放
    • 代碼段

      <meta name="viewport" content="width=device-width,initial-scale=1">
  • 要點
    • 因爲高度固定,寬度自適應,在大屏幕手機下元素被拉長了,因此設計的時候只能設計橫向拉伸的元素佈局,存在不少侷限性。
    • 以小寬度做爲參照是由於若是佈局知足了小寬度的擺放,當屏幕變寬時,簡單的填充空白就能夠了(好比網易新聞);而若是反過來就可能形成「擠壞了」,考慮 header 區域,左測 logo 右測橫向 nav 的狀況。
    • 須要小寬度的佈局,又須要大寬度的圖像,這是一個矛盾點。
    • 兼容性較好。
  • 案例

2.固定寬度,viewport縮放

  • 實現
    • 視覺稿、頁面寬度、viewport width 使用統一寬度,利用瀏覽器自身縮放完成適配。頁面樣式(包括圖像元素)徹底按照視覺稿的尺寸,使用單位px便可。
    • 固定寬度值考慮如下兩點:
    • 代碼段
      • head頭部(根據屏幕寬度來動態生成viewport,生成的 viewport 基本是這樣)

        <meta name="viewport" content="width=640,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">
      • css style

        body {
              width: 640px;
              margin: 0 auto;
           }

  • 優勢:
    • 開發簡單:縮放交給瀏覽器,徹底按視覺稿切圖。
    • 還原精準:絕對等比例縮放,能夠精準還原視覺稿(不考慮清晰度的狀況下)。
    • 測試方便:在PC端便可完成大部分測試,手機端只需酌情調整一些細節(好比圖標、字體混合排列時,由於字體不一樣形成的對齊問題)。
  • 存在的問題:
    • 像素丟失:對於一些分辨率較低的手機,可能設備像素還未達到指定的 viewport 寬度,此時屏幕的渲染可能就不許確了。比較常見的是邊框「消失」了,不過隨着手機硬件的更新,這個問題會愈來愈少的。
    • 縮放失效:某些安卓機不能正常的根據 meta 標籤中 width 的值來縮放 viewport,須要配合 initial-scale 。
    • 文本折行:存在於縮放失效的機型中,某些手機爲了便於文本的閱讀,在文本到達 viewport 邊緣(非元素容器的邊緣)時即進行折行,而當 viewport 寬度被修正後,瀏覽器並無正確的重繪,因此就發現文本沒有佔滿整行。一些經常使用的段落性文本標籤會存在該問題。
  • 解決問題
    • 縮放失效問題需經過 js 動態設定 initial-scale。

      var fixScreen = function() {
            var metaEl = doc.querySelector('meta[name="viewport"]'),
                metaCtt = metaEl ? metaEl.content : '',
                matchScale = metaCtt.match(/initial\-scale=([\d\.]+)/),
                matchWidth = metaCtt.match(/width=([^,\s]+)/);
      
            if ( metaEl && !matchScale && ( matchWidth && matchWidth[1] != 'device-width') ) {
                var    width = parseInt(matchWidth[1]),
                    iw = win.innerWidth || width,
                    ow = win.outerWidth || iw,
                    sw = win.screen.width || iw,
                    saw = win.screen.availWidth || iw,
                    ih = win.innerHeight || width,
                    oh = win.outerHeight || ih,
                    ish = win.screen.height || ih,
                    sah = win.screen.availHeight || ih,
                    w = Math.min(iw,ow,sw,saw,ih,oh,ish,sah),
                    scale = w / width;
      
                if ( ratio < 1) {
                    metaEl.content += ',initial-scale=' + ratio + ',maximum-scale=' + ratio + ', minimum-scale=' + scale;
                }
            }
        }
    • 文本折行問題

      section, p, div,
        h1, h2, h3, h4, h5, h6,
        .fix-break { 
           background: tranparent url('about:blank');
           word-break: break-all;
        }
  • 案例

3.rem作寬度,viewport縮放

  • 實現
    • 依照某特定寬度設定 rem 值(即 html 的 font-size),頁面任何須要彈性適配的元素,尺寸均換算爲 rem 進行佈局,不須要適配的元素仍是使用 px 爲單位。
    • 當頁面渲染時,根據頁面有效寬度進行計算,調整 rem 的大小,動態縮放以達到適配的效果。
    • 根據 devicePixelRatio 設定 initial-scale 來放大 viewport,使頁面按照物理像素渲染,提高清晰度。
    • 經過JS去動態計算根元素的font-size(全部設備均兼容),也可使用media query(兼容本身網站主流的一些屏幕設備)
    • 根據設備像素比(window.devicePixelRatio)給設置data-dpr
    • 代碼段(動態生成 viewport)

      不用寫 meta 標籤,該方法mobile-util.js根據 dpr 自動生成,並在 html 標籤中加上 data-dpr 和 font-size 兩個屬性值。
  • 優勢:
    • 清晰度高,能達到物理像素的清晰度。
    • 能解決 DPR 引發的「1像素」問題。
    • 向後兼容較好,即使屏幕寬度增長、PPI 增長該方案依舊適用。
  • 缺點:
    • 適配 js 需儘量早進入,減小(避免)viewport 變化引發的重繪。
    • 某些Android機會丟掉 rem 小數部分。
    • 須要預編譯庫進行單位轉換。
  • 一些注意的地方

    • chrome當font-size小於12時,rem會按照12來計算,設置基準值要考慮這一點。
    • 較小的背景圖(好比一些 icon)的 background-size 不要使用具體 rem 數值,裁剪後會出現邊緣丟失。應使用與元素等尺寸切圖,設定 background-size: contain|cover 來縮放。
  • 動態調整 rem 的方法以下:

    var fixScreen = function() {
          var metaEl = doc.querySelector('meta[name="viewport"]'),
              metaCtt = metaEl ? metaEl.content : '',
              matchScale = metaCtt.match(/initial\-scale=([\d\.]+)/),
              matchWidth = metaCtt.match(/width=([^,\s]+)/);
    
          if ( !metaEl ) { // REM
              var docEl = doc.documentElement,
                  maxwidth = docEl.dataset.mw || 750, // 每 dpr 最大頁面寬度
                  dpr = isIos ? Math.min(win.devicePixelRatio, 3) : 1,
                  scale = 1 / dpr,
                  tid;
    
              docEl.removeAttribute('data-mw');
              docEl.dataset.dpr = dpr;
              metaEl = doc.createElement('meta');
              metaEl.name = 'viewport';
              metaEl.content = 'initial-scale=' + ratio + ',maximum-scale=' + ratio + ', minimum-scale=' + scale;
              docEl.firstElementChild.appendChild(metaEl);
    
              var refreshRem = function() {
                  var width = docEl.getBoundingClientRect().width;
                  if (width / dpr > maxwidth) {
                      width = maxwidth * dpr;
                  }
                  var rem = width / 16;
                  docEl.style.fontSize = rem + 'px';
              };
    
              //...
    
              refreshRem();
          }
      }
  • 案例

4.響應式佈局(pc & mobile)

  • 實現
    • 使用 viewport meta 標籤在手機瀏覽器上控制佈局
    • 使用 Media Queries 適配對應樣式
  • 要點
    • 響應式這種方式在國內不多有大型企業的複雜性的網站在移動端用這種方法去作,主要緣由是工做大,維護性難
    • 適用於中小型的門戶或者博客類站點會採用響應式的方法從web page到web app直接一步到位,由於這樣反而能夠節約成本,不用再專門爲本身的網站作一個web app的版本。
  • 優勢
    • Native APP:Objective-C or Java – 學習成本高
    • Hybrid APP: 外殼+Web APP,需安裝。
    • 響應式Web APP:HTML5+JS+CSS – 門檻低,極易上手,迭代快
    • 無需安裝成本,迭代更新容易

  • 案例

小結

  • 前三種方案爲H5頁面、手機頁面、WAP頁、webview頁面移動經常使用方案
  • 第一種方案只能作一些列表等簡單排列的樣式,面對更復雜的頁面,每每須要絕對定位和百分比等,尺寸與視覺稿有出入。
  • 第二種和第三種方案不會和設計圖有差,第三種方案比第二種方案更靈活,有兩種單位可用,rempx
  • 靈活運用min-height和min-width
  • 能用flex佈局的不要使用浮動和絕對定位(不利於頁面擴展)

移動開發規範

字體設置

  • 使用無襯線字體
  • iOS 4.0+ 使用英文字體 Helvetica Neue,以前的iOS版本降級使用 Helvetica。中文字體設置爲華文黑體STHeiTi。 需補充說明,華文黑體並不存在iOS的字體庫中http://support.apple.com/kb/HT5878, 但系統會自動將華文黑體 STHeiTi 兼容命中系統默認中文字體黑體-簡或黑體-繁
  • 原生Android下中文字體與英文字體都選擇默認的無襯線字體

    body {
          font-family: "Helvetica Neue", Helvetica, STHeiTi, sans-serif;
      }

基礎交互

  • 設置全局的CSS樣式,避免圖中的長按彈出菜單與選中文本的行爲

    a, img {
          -webkit-touch-callout: none; /* 禁止長按連接與圖片彈出菜單 */
      }
    
      html, body {
          -webkit-user-select: none;   /* 禁止選中文本(如無文本選中需求,此爲必選項) */
          user-select: none;
      }

跨瀏覽器測試

瀏覽器兼容性:

  • pc端模擬
    • PC端Chrome瀏覽器模擬手機調試頁面,佈局上幾乎和真機上沒有差異了,只是真機能夠看到的細節更多、操做真實環境
  • 真機調試
    • 微信、手機QQ、QQ瀏覽器:可使用騰訊TBS studio、手機、usb數據線能夠在測試線上頁面
    • Android:經過手機chrome、PC chrome和usb;鏈接數據一樣能夠在手機上chrome瀏覽器對頁面進行調試。
  • BrowserSync 同步操做
    - 使用node.js command prompt 安裝BrowserSync
    - 在node.js command prompt 在要建立服務器的目錄下面執行:browser-sync start --server --files="*" 命令便可,表示建立一個服務器並監聽該目錄下的文件變更

    - 讓手機與電腦處於同一局域網下,可使用電腦分享熱點手機鏈接(如360無線wifi + 網卡)

  • 更多更詳細測試方案

實踐應用

  • demo1(運用的是第一種方案,可是有些元素高度沒有固定,而是自適應,以此適應圖片的縮放。)

參考資料

拓展閱讀

相關文章
相關標籤/搜索