移動端開發(web app) 之移動端佈局 知識總結

App 分類

圖片描述

如上圖,Native app 是使用原生開發的 app, 優勢是性能更好,還能調用系統的 api ,可是發佈 app 流程繁瑣,並且不跨平臺。css

Web app, 優勢是跨平臺,修改方便,缺點是不能調用原生的 api, 並且用戶體驗不如原生 app, 好。html

Hybrid app, 結合了上面兩個的優勢,能夠說是很 nice。android

尺寸相關概念

CSS 像素

又稱爲設備獨立像素、邏輯像素。CSS中使用的一個抽象的概念,單位是 pxios

值是相對的,並非絕對的,根據 dpr 來肯定一個 CSS 像素表明幾個物理像素,還有一些狀況,例如用戶縮放的時候,,dpr 也會跟着變爲 2, 此時一個 CSS 像素表明兩個物理像素。css3

注意: 電腦當中的一個設備像素通常是等於一個 CSS 像素。因此咱們在 PS 當中的切圖大小,通常也表明物理像素表示的大小。web

設備像素

又稱爲物理像素,任何設備屏幕的物理像素的數量自出場開始就是固定不變的,單位是 pt(點)。一個物理像素即屏幕上一個發光的點。物理像素單個點的大小由廠商決定,大小不固定。api

屏幕尺寸

指的是屏幕對角線的長度,單位爲英寸,注意英寸是長度單位,不是面積單位。1英寸(inch)=2.54釐米(cm)瀏覽器

屏幕尺寸=屏幕斜邊的像素/PPI。app

圖片描述

像素密度 PPI

單位面積上(英寸)像素(設備像素)的數量。它是一個定值,是一個固定的參數。PPI=屏幕斜邊的像素/屏幕尺寸。以下:dom

圖片描述

因此要提升 PPI的話,須要增長水平和豎直方向的像素點數量。所以,同一尺寸(inch)下,PPI提升了一倍,那像素會變爲原來的4倍,也就是所 PPI 增長 N 倍,單位面積上的像素點的數量變爲原來的 N^N 倍,以下圖。查詢不一樣設備的 ppi

圖片描述

PPI 的值越高,表明在必定尺寸的屏幕上像素數量越多,屏幕越清晰。以下同一張圖片。

圖片描述

但同時,因爲單位面積(英寸)並無變,因爲 PPI 的變大,對應的物理像素點會縮小。和上面的物理像素點的規律相反,PPI 增長 N 倍,單位面積上的像素點的大小將變爲原來的 1 / N^N 倍。以下圖:

圖片描述

同時對於一張圖像,放到比當前 PPI 大的設備上時,也將按照上面的比例變小。例如一個放到一個 PPI 爲本身的 2 倍的設備上時,圖像將縮小四倍,以下圖。

圖片描述

可是在實際當中咱們更但願圖片保持原有大小,而且最好是也不變模糊,保持原有的清晰度。對於上面的狀況,解決方案是設備的 DPR 須要是原來設備的 2 倍,即便一個 CSS 像素須要表明的物理像素點須要變爲原來的 2 倍,這就保持了圖像的大小未發生改變,同時圖片的分辨率也須要變爲原來的兩倍,這樣就保持圖像的清晰度未發生改變。

像素比 DPR

DPR=物理像素/css像素。獲取:window.devicePixelRatio查詢1查詢2

它的本質是指一個 CSS 像素表明幾個 物理像素。它的意義是爲了讓圖像可以早高清屏上顯示。

其實上當像素比超過 2 後,肉眼是識別不出來的。

視口 ViewPort

只針對 PC 端的頁面直接放到移動端的狀況的話,默認會進行縮小。首先是由於移動端的像素點通常比 PC 端更加的密集,因此相應的物理像素點都會變得很小,同時在這個縮放的基礎之上,瀏覽器還會根據狀況繼續進行縮小。縮放比=物理像素(即設備像素)/ 視口寬度(html 的寬度,默認是 980px, 用document.documentElement.clientWidth方法獲取)。因此在移動端開發的時候,咱們須要正確的設置 ViewPort的值。

典型的 ViewPort 的設置值爲下面這樣:

<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
  • width: device-width(設備的實際寬度--即設備的 css 像素)。
  • user-scalable: 是否容許用戶在設置或者默認的視口寬度上進行頁面縮放,值爲no或yes,表明不容許與容許。
  • initial-scale: 頁面初始縮放值,值爲一個數字(能夠帶小數)。
  • minimum-scale: 頁面最小可以縮放的比例,值爲一個數字(能夠帶小數)。
  • maximum-scale: 頁面最大可以縮放的比例,值爲一個數字(能夠帶小數)。

須要注意的是,在移動端,若是不限制縮放,那麼爲了保證頁面所有可見,會對頁面總體進行縮放, 縮放的計算方式爲: 縮放比(initial-scale)=css像素(設備css像素)/viewport寬度(html寬度)

initial-scale = 1,能夠達到和 width=device-width, 同樣的效果。若是都設置了,取二者的最大值。

通常當咱們都禁止用戶進行縮放,以下:

minimum-scale=1,maximum-scale=1,user-scalable=no

通常根據上面的公式,咱們能夠經過設置縮放比,動態的設置 viewport 的寬度。

meta 標籤

禁止識別電話與郵箱(可是郵箱沒效果)
            <meta name="format-detection" content="telephone=no,email=no" />

            設置添加到主屏後的標題(ios)
            <meta name="apple-mobile-web-app-title" content="標題">

            添加到主屏幕後,全屏顯示,刪除蘋果默認的工具欄和菜單欄(無用)
            <meta name="apple-mobile-web-app-capable" content="yes" />

            放在桌面上的logo
            <link rel="apple-touch-icon-precomposed" href="iphone_logo.png" />

            啓動時候的畫面(無用)
            <link rel="apple-touch-startup-image" href="logo_startup.png" />

            設置x5內核瀏覽器只能豎屏瀏覽(只有UC有效)
            <meta name="x5-orientation" content="portrait" />
            
            設置x5內核瀏覽器全屏瀏覽
            <meta name="x5-fullscreen" content="true" />
            
            設置UC瀏覽器只能豎屏瀏覽
            <meta name="screen-orientation" content="portrait">
            
            設置UC瀏覽器全屏瀏覽
            <meta name="full-screen" content="yes">
            若是想屏蔽全部瀏覽器的橫屏的話,須要在後面陀螺儀那章節講

移動端樣式重置

一、禁止用戶選中文字,安卓無效(在事件那章解決,包括長按的時候會出菜單,用阻止touchstart後的默認行爲搞定)
                    -webkit-user-select: none;
二、禁止長按彈出系統菜單
                    -webkit-touch-callout: none;
三、去除android下a/button/input標籤被點擊時產生的邊框 & 去除ios下a標籤被點擊時產生的半透明灰色背景
                    -webkit-tap-highlight-color: rgba(0,0,0,0);
四、切換橫豎屏或者用戶本身經過瀏覽器設置的話,能夠改變字體的大小(須要給body下的全部元素)
                    -webkit-text-size-adjust: 100%;
五、按鈕在ios下都是圓角
                    -webkit-appearance: none;    //button與input都會有個默認背景
                    border-radius: 0;    //input有個默認圓角
六、修改placeholder的樣式
                    input::-webkit-input-placeholder{
                        color:#000;    //默認的樣式
                    }
                    input:focus::-webkit-input-placeholder{
                        color:#f00;    //點擊後的樣式
                    }
七、字體
                    ios
                        默認中文字體是Heiti SC
                        默認英文字體是Helvetica
                        默認數字字體是HelveticaNeue
                        無微軟雅黑字體
                    android
                        默認中文字體是Droidsansfallback
                        默認英文和數字字體是Droid Sans
                        無微軟雅黑字體
                    
                    font-family: helvetica;

移動端適配

適配是爲了一版設計稿走天下,適配的範圍包括字體、寬高、間距、圖像

在熟悉瞭解了前面的概念以後,下面就來介紹移動端的適配幾種方式。

百分比適配

根據父級設置寬度。可是有時候百分比不太好算,並且計算的時候須要知道父級的高度。

viewport 縮放適配

把全部機型的 css 像素設置成一致的,那麼切圖的時候只須要切一種尺寸的就能夠了。代碼以下

(function(){
                //獲取css像素(viewport沒有縮放)
                var curWidth=document.documentElement.clientWidth;
                var targetWidth=375; // 最終尺寸
                var scale=curWidth/targetWidth; // 縮放比
                var view=document.getElementById('view');
                view.content='initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+''; // 這樣設置了之後,全部設備上的 viewport 都爲 375了。
            })();

注意這裏也須要將最大和最小縮放比設置爲和初始的值同樣,否則若是它們都仍是 1 的話,前面的就沒有效果了,由於如今仍是規定最大最小的縮放比爲 1。

缺點:由於如今在任何設備上的viewport的寬度都爲固定的寬度,例如 375 的圖片放到 大屏幕上,由於寬度是固定的,因此確定會變得模糊

DPR 縮放適配

根據dpr的值,把視口進行縮放,縮放到物理像素,也就是把css像素的值設置成物理像素,讓全部的設備都變成一個css像素對應一個設備像素,方便切圖

(function(){
                /*
                    375*2    750 
                    320*2    640

                    375/?=750    => 375/750=2
                    1/dpr // 公式

                    320/scale=640    =>     scale=320/640    1/2
                 */

                var meta=document.querySelector('meta[name="viewport"]');
                var scale=1/window.devicePixelRatio;

                if(!meta){
                    //這個條件成立說明用戶沒有寫meta標籤,我須要建立一個
                    meta=document.createElement('meta');
                    meta.name='viewport';
                    meta.content='width=device-width,initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+'';
                    document.head.appendChild(meta);
                }else{
                    meta.setAttribute('content','width=device-width,initial-scale='+scale+',user-scalable=no,minimum-scale='+scale+',maximum-scale='+scale+'');
                }
            })();

rem 適配

rem 是相對於根節點(html)的字體大小。

它的原理是把全部的設備都分紅相同的若干份,再計算元素寬度所佔的份數,開發的時候只須要使用一個特定的設備 而且使用rem 那麼在其餘設備上會自動出現相同的效果即自動適配(很神奇),而且設計稿須要以物理像素爲準來設計 例如分辨率寬爲 375 drp爲2,那麼實際針對該機型的設計搞應該爲750。

媒體查詢方式

即經過媒體查詢,對全部範圍內的尺寸給定一個 html 根結點字體大小。可參考蘇寧易購。

js簡單方式

  1. 計算出每一列的寬度:viewport寬度(css像素)/16(列數),並將其設置爲根結點字體大小。
  2. 根據設計稿量出的實際尺寸除以 dpr,而後再根據換算後的尺寸,除以一列的寬度(1rem),元素佔 n 列
  3. 而後設置元素的寬度爲 nrem。
(function(){
                var html=document.documentElement;    //html
                var width=html.clientWidth;        //css像素
                // 方式一
                html.style.fontSize=width/16+'px';    //把屏幕分紅了16列,以iphone爲例得出一個列的值爲整數
                // 方式二
                html.style.fontSize= 16 * clientWidth / 375 + 'px'; // 以iphone6 爲基準,當大於 iphone6 的尺寸時,字體大小大於 16px, 同理小於時,字體小於 16px。
            })();

js經典方式

相比於上面的普通方式,經典方式省掉了,根據設計稿量出的實際尺寸除以 dpr 這一步,直接將設計稿當中量出來的尺寸除以 100 而後單位爲 rem。下面依然以 iphone6 爲例。

(function(doc, win, designWidth) {
                const html = doc.documentElement;
                const refreshRem = () => {
                    const clientWidth = html.clientWidth;
                    if (clientWidth >= designWidth) { //給寬度一個最大值,若是設備的寬度已經超過設計稿的尺寸了,統一按一個值去算(傳的第三個參數)
                        html.style.fontSize = '100px';
                    } else {
                        html.style.fontSize = 100 * (clientWidth / designWidth) + 'px'; // 這種方式是咱們在切圖的時候不須要手動去除dpr, 已經幫咱們處理好來,可是咱們在計算的時候仍是必須使用1rem = 100px來計算
                    }
                };
                
                //dom加載完的一個事件
                doc.addEventListener('DOMContentLoaded', refreshRem);
            })(document, window, 750);

vw 適配

vw 將頁面分爲 100 份,相關單位以下:

  1. vw Viewport's width的簡寫,1vw等於視口寬度的1%
  2. vh Viewport's height的簡寫,1vh等於視口高度的1%
  3. vmin 取vw和vh中最小的值
  4. vmax 取vw和vh中最大的值

兼容性以下:

  • >=ios 8
  • >=Android 4.4

而且 vw、vh分別表明水平和豎直方向,和橫豎屏沒有關係,會自動根據橫豎屏來計算獲得每一份的寬度,如圖:

圖片描述

有兩種使用 vw 方式

方式一

通篇使用 vw, 和前面 rem 部分提到的 js 簡單部分差很少,只不過省略了計算每一份的過程,瀏覽器自動幫咱們計算 1vw 是多少。注意切圖的使用仍是要除以 dpr。能夠採用 scss 等 css 預處理語言來簡化這個過程。

方式二

經過 vw 設置根節點字體大小,頁面裏的尺寸依然使用rem。可是前提是你要知道頁面當中根節點的字體大小,根節點字體的大小的計算參考前面 rem 佈局部分的 js 經典方式

移動端存在的幾個問題

固定定位

在 ios 下面,若是頁面裏有一個固定定位(fixed)的元素以及一個 input 元素的時候,用戶但凡點擊input調出鍵盤的時候,固定定位元素就會不起做用。解決方式:

  1. 將須要滾動的元素放到一個容器裏面,容器超出就滾動,這樣容器和固定定位元素就會在一個頁面,就算失效了,也在一個頁面內可見。

1px 問題

在移動端 dpr, 每每是 2 及其以上,因此 1px 每每表明多個物理像素,這就是 1px 問題, 解決辦法:

  1. dpr 縮放適配不存在這個問題,由於 dpr 縮放適配是 1px = 1pt
  2. 可使用 css3 提供的 scale 來縮放邊框爲 0.5 倍, 下面是建立了一個僞類,並縮放它的邊框來達到縮放的目的.
section::after{
                content: '';
                position: absolute;
                left: 0;
                top: 0;
                border: 1px solid #000;
                box-sizing: border-box;
                width: 100%;
                height: 100%;
                transform-origin: 0 0;
                transform: scale(0.5);
            }
相關文章
相關標籤/搜索