一點關於移動端頁面開發的總結

寫在最前:

 對於移動端頁面的開發本身很早就想作下簡單的總結了,但感受不知道該從何提及,有一天看了兩篇網上一位做者的文章(後面資源裏面會給出連接),以爲寫得真的是很好,可是還有一些問題我不是很清楚,因此本身也查閱了相關的文獻,結合前面那位做者的一些思路,寫下了這篇總結。固然,有說的不對的地方,還望指出,謝謝。css

準備工做:

 照例,貼下個人博客地址,別忘了去點贊哈~html

兩個像素:設備像素+css像素前端

  • 設備像素:絕對單位,設備像素即設備的物理像素,對於每一個設備來講,其設備像素是固定的,它是每一個設備能控制顯示的最小單位。一般咱們所說的1920x1080像素分別率就用的是設備像素。
  • css像素:適用於web編程,是前端開發在描述css樣式時常常用到的像素單位。好比,設置某個div的寬度爲width:200px,這個就是css像素,是一種抽象概念,實際上並不存在。

頁面的縮放:git

  • 當用戶放大或者縮小頁面時,改變的是css像素,而設備像素不會發生改變。如:頁面中一個div,它的寬度是200px,當用戶操做頁面,放大兩倍,此時一個css像素的面變成了4個設備像素的面積:寬放大2倍x高放大兩倍
  • 頁面縮放比例(zoom level)= screen.width / window.innerWidth (通常狀況下能夠這麼計算)

設備像素比(DPR):github

  • 在頁面縮放比爲1的狀況下,設備像素比(DPR) = 設備像素個數 / 視覺視口css像素個數(device-width)
  • 對於不一樣的設備來講設備像素比是不同的。在早期iphone的DPR值是等於1的,可是後來引入了高密度屏幕,即爲了更清晰的展現畫面,在有限的設備空間內引入了更多的設備像素。因此後來iphone設備的DPR就改變了,值通常爲2。能夠經過調試器看到設備的設備像素比,以下圖所示:

場景再現:

移動端需求:給你一個750px的設計稿,上面畫了一個200px的矩形框。web

 既然是寫移動端頁面,做爲一名前端開發者,我想大家首先就會在裏面敲下這樣一句話:編程

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
複製代碼

 看上去只有那麼熟悉了。這句話什麼意思?它有什麼做用呢?彆着急,咱們先來理解下viewport這個概念。瀏覽器

viewport:bash

 viewport即視口,它的做用是限制頁面的根元素即。在PC端,視口能夠當作只有一個,即咱們所看到的頁面窗口,它的大小由瀏覽器窗口來決定。可是在M端視口分爲兩類:視覺視口(visual viewport)和佈局視口(layout viewport),後文我會詳細解釋爲何移動端有這兩個視口。(既然M端作了這樣的劃分,咱們也能夠對PC端採起一樣的方式,即PC端viewport就是PC端的visual viewport)iphone

 因此,對於PC端來講,根元素的大小就能夠由visual viewport來肯定了。那麼,怎麼計算呢?下面分狀況給出相應的計算方式:

  1. 瀏覽器沒有出現(橫向、縱向)滾動條且沒有人爲的去設置元素的寬高(html的寬高能夠人爲的去設置,可是通常狀況下咱們不建議這樣作):
html的寬度 = document.documentElement.clientWidth = document.documentElement.offsetWidth = window.innerWidth
複製代碼
  1. 瀏覽器出現滾動條且沒有人爲的去設置元素的寬高:
html的寬度 = document.documentElement.clientWidth = document.documentElement.offsetWidth = window.innerWidth - 滾動條的寬度
複製代碼
  1. 人爲設置了的寬度時:
html的寬度 = document.documentELement.offsetWidth
複製代碼

 如此,PC端就能夠按照其viewport的尺寸進行頁面的佈局。有了上面的基礎,咱們接下來看看M端頁面。M端較之於PC端,一個顯然的不一樣就是設備的尺寸。M端的屏幕寬度大多<=400px,不像PC端那樣,動不動就是上千像素。這樣PC端的頁面到了移動端,可謂是不堪入目,下面是真實的網站截圖,

  • PC端頁面:

  • PC端頁面放到移動端:

 能夠看到,在沒有作M頁面優化的狀況下,PC端頁面放到M端時,爲了讓你看清整個頁面,強行把裏面的內容進行縮放,以致於模糊不清,簡直沒法直視。(固然人家的頁面是作了M端優化的,爲了看效果我是把裏面的給刪掉了,哈哈哈,機智吧~)

如何解決M端設備尺寸過小的問題呢:

 既然移動端的視覺視口太窄(瀏覽器的寬度)而不能知足css佈局的需求,那麼就想辦法弄一個更寬的視口出來,知足M端佈局需求。此時,layout viewport應運而生。

 佈局視口比視覺視口要寬的多,M端就是根據佈局視口來進行css佈局的。並且在M端,元素的大小是由佈局視口來肯定的,就像咱們以前談到的PC端和視覺視口的關係那樣。那麼,佈局視口到底有多大呢,以及他是怎樣去計算的呢?

 對於M端來講,其佈局視口的大小取決於瀏覽器廠商,一些常見的佈局視口取值以下表所示:

browser viewport width
Safiri 980px
Opera 850px
Android WebKit 800px
IE 974px

跟PC端有點相似,佈局視口的大小可有下面的方式取得:

佈局視口的寬度 = document.documentElement.clientWidth
佈局視口的高度 = document.documentElement.clientHeight
複製代碼

有了這個佈局視口的概念後,咱們再來看看PC端頁面放到M端,會呈現出怎樣的狀況:

 看到了麼,此時頁面到了M端之後,不會強行的去縮放裏面的內容,而是根據佈局視口的大小去進行css佈局,因爲佈局視口比視覺視口(瀏覽器的寬度)大不少,就出現了滾動條。因此,經過滾動頁面你能夠清楚的看到頁面的整個內容了。可是,這還不是咱們想要的M端頁面,咱們想要怎樣一種效果呢?應該是這樣:咱們不想頁面出現滾動條,並且想要頁面全部的內容都呈如今咱們的視野範圍內。即要是咱們可以本身去控制M端佈局視口的大小就行了,讓它以一個用戶比較溫馨的大小呈如今屏幕上,標籤幫咱們完成了這一舉動,讓咱們繼續看看吧。

meta:

 最初是由蘋果公司提出的,後來被多家瀏覽器廠商複製。其目的是爲了調整M端佈局視口的大小,以適應各類寬度的移動設備。該標籤應該置於標籤內,其語法以下所示:

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" user-scalable=no>
複製代碼

 是否是很熟悉,對啦,咱們在文章的開頭時曾寫過。關於viewport咱們再也不解釋,下面簡單說一下content裏面的內容。content屬性的值是一個字符串,字符串裏面的內容是由逗號隔開的名值對,一共5個:

  1. width:佈局視口的寬度,能夠本身設定準確的值如width=300,也能夠是一些特殊值,如width=device-width,顧名思義就是設備的寬度
  2. initial-scale:設置頁面的初始縮放程度,能夠是小數
  3. minimum-scale:設置頁面的最小縮放程度
  4. maximum-scale:設置頁面的最大縮放程度
  5. user-scalable: 是否容許用戶對頁面進行縮放

 因此,列子中代碼的含義就是,設置佈局視口的寬度爲設備的寬度,頁面的初始縮放比例、最小縮放比例以及最大縮放比例值爲1,不容許用戶縮放頁面。

 好了,寫到這裏,你們或多或少對有了必定的瞭解吧,下面咱們就開始真正的移動端頁面開發了,哈哈哈,費了老大勁兒解釋,可是我以爲頗有必要吧。

移動端頁面開發:

&承接上面的需求,咱們在750px的設計稿(其實這也是如今iPhone6/7的設計稿樣子)上看到了一個寬高都是200px的綠色矩形框,以下圖所示:

 因而咱們這樣設計代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>移動端頁面開發</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .weekend {
            width: 200px;
            height: 200px;
            background-color: green;
        }
    </style>
</head>
<body>
    <div class="weekend"></div>
</body>
</html>
複製代碼

 效果以下所示:

image

 咋一看,哎,不對呀,矩形框的寬高沒有問題,可是設計稿上的設備寬度是750,而瀏覽器顯示的寬度則是375,這是怎麼回事呢。其實,設計稿是按照設備像素去設計的,因此在頁面縮放比爲1的狀況下,根據公式:

DPR = 設備像素/視覺視口css像素個數(device-width)
複製代碼

 在iphone7上DPR=2,因此1個css像素等效於2個設備像素,因此對於矩形框的寬度,應該設爲200/2=100px,固然對於其餘的DPR值,咱們應該用設計稿上的設備像素/DPR,獲得真正應該獲得的css像素。可是,若是咱們不想每次都去計算真正的css像素值,而是讓瀏覽器自動去計算呢。別忘了,咱們前面提到的中content的 值initial-scale,它縮放的是css的像素,因此利用這個特性,設置initial-scale = 1/DPR,此時M端一個設備像素就等於一個css像素了,這樣咱們就能夠直接將設計稿上的像素值設爲css的像素值,而不用人爲的去計算了。代碼以下: (多說一句,利用window.devicePixelRatio能夠獲取設備的DPR值)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>移動端頁面開發</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .weekend {
            width: 200px;
            height: 200px;
            background-color: green;
        }
    </style>
</head>
<body>
    <div class="weekend"></div>
    <script>
        var scale = 1/window.devicePixelRatio;
        document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=device-width, initial-scale=' + scale + ', user-scalable=no')
    </script>
</body>
</html>
複製代碼

 效果以下所示:

 這下好了,好像達到咱們想要的效果了,但是爲何說好像呢,看到這裏的朋友不知道有沒有想過這樣一個問題,假如如今你不是iphone7的設備,而是iphone5,他們的DPR值都爲1,可是設備的寬度倒是不同的。然而咱們的代碼設計並無考慮到這樣的狀況,咱們來驗證下這個想法,用iphone5看一下頁面效果,以下所示:

 果真,iphone5上仍是100px,這該如何是好呢?咱們應該留意到了這樣一個現象,隨着設備的寬度在變化,由於咱們設置了頁面佈局視口的寬度值等於device-width,而html的寬度又是由佈局視口所決定的(document.documentElement.clientWidth),因此只要咱們想到有什麼辦法能讓頁面中元素的寬度可以隨着根元素的變化而變化,這樣咱們就可以達到想要的效果了。是的,沒錯,就是rem,我想對於rem這個概念應該並不陌生吧。簡單來講,rem是一個相對單位,是相對於html字體大小的單位。舉個例子:  當咱們設置html {font-size: 10px}時,設置頁面某個div {width: 2rem},此時div通過計算後的寬度就等於2*10即20px。因此,經過rem的這個功能,咱們就能夠實現咱們想要的效果了。開始寫吧,代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>移動端頁面開發</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .weekend {
            width: 2.666667rem;
            height: 2.666667rem;
            background-color: green;
        }
    </style>
</head>
<body>
    <div class="weekend"></div>
    <script>
        var scale = 1/window.devicePixelRatio;
        document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=device-width, initial-scale=' + scale + ', user-scalable=no');
        document.documentElement.style.fontSize = document.documentElement.clientWidth / 10;
    </script>
</body>
</html>
複製代碼

 代碼修改的地方有兩處,一個是script裏面,添加了一個修改根元素fontSize的語句,爲何要除以100呢,由於直接取document.documentElement.clientWidth的值感受有點略大了,這個標準孫便設計的,想怎麼來怎麼來。==可是有個地方咱們得注意一下:==就是font-size的最小值問題,咱們不能設置得過小不然無效== 。另一個地方就是style裏面css樣式,由於是750px的設計稿,因此width值設置爲200/(750/100),一樣若是是640px的設計稿,就是200/(640/100),哈哈,大功告成,咱們來看一看效果:

 終於,大功告成,真是不容易啊,但是,這個真的就是最佳的解決方案麼?那可未必。大家看,咱們在設置css的樣式的時候,須要用設計稿上的樣式去除以fontSize轉化後的值,好比說750的設計稿,就要除以75;640的設計稿就要除以64,畢竟這些值不是什麼容易除盡的值,因此計算起來還比較麻煩。那有沒有什麼解決方案呢?哈哈哈,辦法總比困難多,根據網上有人提出的解決方案,完美的解決了這個問題,其實就一句話,我這裏不作解釋,留給各位本身去體會,相信在前面介紹的基礎上,這段代碼是很容易解釋的,代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="">
    <title>移動端頁面開發</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .weekend {
            width: 2rem;
            height: 2rem;
            background-color: green;
        }
    </style>
</head>
<body>
    <div class="weekend"></div>
    <script>
        document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
    </script>
</body>
</html>
複製代碼

 就一句話,巧妙的解決了移動端設計的問題,對於設計稿上的寬度,只要除以100便可。

寫在最後:

 終於,這篇文章算是完結了,花了本身一個週六的時間,固然裏面關於最後移動端頁面的設計思路是對別人文章的很大借鑑,可是總體不少地方都有本身的想法總結與移動端知識的延伸。其實,咱們再來看M端,無外乎兩個方面是咱們須要考慮的問題:一個是移動端一個css像素和一個設備像素的對等關係,一個是不一樣設備的寬度自適應問題。知道怎麼去解決這兩個問題,那麼你就算是基本上掌握了移動端頁面設計的主要思想。固然,無論是對別人借鑑也好,仍是本身領悟也好,主要是本身對這部分知識點有所掌握,可以站在本身的角度獨立完成這篇總結,對我而言也是極好的。裏面有些說得不正確的地方,還望各位讀者指出,謝謝~

參考資料:

A tale of two viewports — part one

A tale of two viewports — part two

一篇真正教會你開發移動端頁面的文章(1)

一篇真正教會你開發移動端頁面的文章(2)

相關文章
相關標籤/搜索