本文原文發表於2016年我的github,但是直到現在為止還有很多童鞋問我相關概念,於是整理下再分享一下。
一、基礎概念
在瞭解如何做H5頁面適配前,大家都應該把移動端涉及的一些概念搞明白,比如:dpr
是什麼意思?
二、為什麼要做頁面適配
2.1 PC端為什麼要解決瀏覽器相容
因為在PC端,由於瀏覽器種類太多啦,比如幾個常用的:IE、火狐、Chrome、Safari等。同時,由於歷史原因,不同瀏覽器在不同時期針對當時的WEB標準有一些不一樣的處理(雖然大部分一樣),比如:IE6、IE8、IE10+等對於一些JS事件處理、CSS樣式渲染有所不同。
而恰恰又有一些人在使用著不同型別的瀏覽器,以及不同瀏覽器的不同版本。所以,為了能讓你的網站讓這些不同的人看到效果一致,你就不得不做相容,除非這些人不是你的目標使用者。
2.2 移動端為什麼要做適配
在移動端雖然整體來說大部分瀏覽器核心都是webkit,而且大部分都支援CSS3的所有語法。但是,由於手機螢幕尺寸不一樣,解析度不一樣,或者你需要考慮橫豎屏的問題,這時候你也就不得不解決在不同手機上,不同情況下的展示效果了。
另外一點,UI一般輸出的視覺稿只有一份,比如淘寶就會輸出:750px
寬度的(高度是動態的一般不考慮)(詳情),這時候開發人員就不得不針對這一份設計稿,讓其在不同螢幕寬度下顯示 一致
。
一致
是什麼意思?就是下面提到的幾個主要解決的問題。
三、頁面適配主要解決的問題
- 元素自適應問題
- 文字rem問題
- 高清圖問題
- 1畫素問題
- 橫豎屏顯示問題
- 手機字型縮放問題
3.1 元素自適應問題
舉個例子:
在 1080px
的視覺稿中,左上角有個logo,寬度是 180px
(高度問題同理可得)。
那麼logo在不同的手機螢幕上等比例顯示應該多大尺寸呢?
其實按照比例換算,我們大致可以得到如下的結果:
- 在CSS畫素是
375px
的手機上,應該顯示多大呢?結果是:375px * 180 / 1080 = 62.5px
- 在CSS畫素是
360px
的手機上,應該顯示多大呢?結果是:360px * 180 / 1080 = 60px
- 在CSS畫素是
320px
的手機上,應該顯示多大呢?結果是:320px * 180 / 1080 = 53.3333px
以下就是一些實現思路:
方案1:使用css的媒體查詢 @media
@media only screen and (min-width: 375px) {
.logo {
width : 62.5px;
}
}
@media only screen and (min-width: 360px) {
.logo {
width : 60px;
}
}
@media only screen and (min-width: 320px) {
.logo {
width : 53.3333px;
}
}
複製程式碼
這個方案有2個比較突出的問題:
- 如果再多一種螢幕尺寸,就得多寫一個
@media
查詢塊; - 頁面上所有的元素都得在不同的
@media
中定義一遍不同的尺寸,這個代價有點高。
方案2:使用 rem
單位
注意我們的推導公式:
- 在CSS畫素是
375px
的手機上,應該顯示多大呢?結果是:375px * 180 / 1080 = 62.5px
- 在CSS畫素是
360px
的手機上,應該顯示多大呢?結果是:360px * 180 / 1080 = 60px
- 在CSS畫素是
320px
的手機上,應該顯示多大呢?結果是:320px * 180 / 1080 = 53.3333px
@media only screen and (min-width: 375px) {
html {
font-size : 375px;
}
}
@media only screen and (min-width: 360px) {
html {
font-size : 360px;
}
}
@media only screen and (min-width: 320px) {
html {
font-size : 320px;
}
}
.logo{
width : 180rem / 1080;
}
複製程式碼
方案2有效的解決了方案1中,同一個元素需要在多個 media 中寫的問題,這裡只需要多定義幾個 media 就可以大致解決問題了。
但是本方案仍然有以下問題:
- 針對不同的手機解析度,需要寫多套
@media
查詢語句,多一種機型就需要多寫一套查詢語句,而且隨著現在手機的層出不窮,這個頁面很有可能在一些新出的機型上有問題。 - 每個元素都需要除以1080這個設計稿的尺寸。
針對除以1080我們能不能直接放到html的font-size上,變成這樣:
@media only screen and (min-width: 375px) {
html {
font-size : 375px / 1080;
}
}
@media only screen and (min-width: 360px) {
html {
font-size : 360px / 1080;
}
}
@media only screen and (min-width: 320px) {
html {
font-size : 320px / 1080;
}
}
.logo{
width : 180rem;
}
複製程式碼
如果變成這樣,那麼 .logo
的css中就只需要按設計稿的尺寸大小寫就可以了。到底可不可以呢?
答案是:不可以。
主要原因是,瀏覽器有最小字型限制:
- PC上最小
font-size=12
- 手機上最小
font-size=8
如果小於最小字型,那麼字型預設就是最小字型。
再來看上面的css,比如:
@media only screen and (min-width: 375px) {
html {
font-size : 375px / 1080; //0.347222px
}
}
.logo{
width : 180rem; //期望結果:375px / 1080 * 180 = 62.5px
}
複製程式碼
所以當你這麼設定font-size時,在手機上由於小於最小字型8px,所以頁面會按照預設字型算。
所以,最終就相當於你是這麼設定的:
@media only screen and (min-width: 375px) {
html {
font-size : 8px;
}
}
.logo{
width : 180rem; //實際結果:1440px
}
複製程式碼
所以,大家在設定html的font-size的時候一定要保證最小等於8px!
因而為了解決這個問題,建議大家使用Sass這種Css開發語言,可以定義公式的,這樣寫css就方便了。
最終使用Sass的程式碼如下:
@media only screen and (min-width: 375px) {
html {
font-size : 375px;
}
}
@media only screen and (min-width: 360px) {
html {
font-size : 360px;
}
}
@media only screen and (min-width: 320px) {
html {
font-size : 320px;
}
}
//定義方法:calc
@function calc($val){
@return $val / 1080;
}
.logo{
width : calc(180rem);
}
複製程式碼
以上方案雖然解決了問題,但任然有以下缺陷:
- 不同的尺寸需要寫多個
@media
- 依賴css的開發工具,比如:sass/less等
- 所有涉及到使用rem的地方,全部都需要呼叫方法
calc()
,這個也挺麻煩的。
方案3:js動態設定根字型
由於方案2最主要的問題就是需要針對不同的螢幕尺寸,定義多個 @media
,所以我們先將這個字型設定改為動態設定。
注意我們的推導公式:
- 在CSS畫素是
375px
的手機上,應該顯示多大呢?結果是:375px * 180 / 1080 = 62.5px
- 在CSS畫素是
360px
的手機上,應該顯示多大呢?結果是:360px * 180 / 1080 = 60px
- 在CSS畫素是
320px
的手機上,應該顯示多大呢?結果是:320px * 180 / 1080 = 53.3333px
//獲取手機螢幕寬度
var deviceWidth = document.documentElement.clientWidth;
//將方案二中的media中的設定,在這裡動態設定
//這裡設定的就是html的font-size
document.documentElement.style.fontSize = deviceWidth + 'px';
複製程式碼
需要注意:
document.documentElement.clientWidth 這個語句能獲取到的準確的手機尺寸的前提是建立在html中設定瞭如下標籤:
<meta name="viewport" content="width=device-width"> 複製程式碼
要不然獲取到的結果將始終是:980(檢視原因)
然後Sass中就可以按照設計稿的尺寸大小去寫就行了:
//定義方法:calc
@function calc($val){
@return $val / 1080;
}
.logo{
width : calc(180rem);
}
複製程式碼
如果不考慮別的因素,只是頁面元素大體適配的話,該方案基本就滿足要求了,但是現實中我們其實還有很多問題,所以我們的方案還需要繼續優化。
3.2 文字rem問題
文字也採用rem的單位主要有什麼問題呢?
- 可能會出現通過rem計算,最終呈現到頁面上是
23.335px
這樣的奇葩的字型大小,可能還會因此出現鋸齒、模糊不清等問題; - 對於大屏希望一行顯示的文字多一些,小屏顯示的少一些,而不是一視同仁的全部顯示同樣多的文字。這樣在大屏下顯得文字特別大(下文
3.5 橫豎屏顯示問題
會仔細講)。
對於以上問題,我個人的建議:
- 對於出現奇葩字型的問題,其實手機上表現並沒那麼明顯,主要原因是現在螢幕顯示效果統一編號,另外html對字型顯示也做優化,所以,如果產品要求不嚴格,可以不用考慮處理;
- 對於橫豎屏問題,看情況吧,如果要求不嚴格,也可以不用考慮。
如果一定要解決這個問題,那麼字型就不要使用rem方案了,而是繼續使用px單位。
我們上面提到 大屏
小屏
其實隱含的意思並不是手機螢幕大,而是手機的螢幕解析度不一樣,其實就是dpr不一樣,所以我們針對不同的dpr設定具體的字型就可以了。
比如,我們針對頁面的標題的字型大小就可以如下設定:
.title {
font-size: 12px;
}
[data-dpr="2"] .title {
font-size: 24px;
}
[data-dpr="3"] .title {
font-size: 36px;
}
複製程式碼
3.3 高清圖問題
先來看看 這裡 這篇文章,有講解了為什麼在有些螢幕上要使用 @2x
@3x
的高清圖。
再來看看 這裡 講解了具體的高清圖的解決方案。
我這裡簡單歸納下。
3.3.1 對於 <img>
標籤引入的圖片高清解決方案
1、使用 srcset
標籤
<img src="http://g.ald.alicdn.com/bao/uploaded/i1/TB1d6QqGpXXXXbKXXXXXXXXXXXX_!!0-item_pic.jpg_160x160q90.jpg" srcset="http://img01.taobaocdn.com/imgextra/i1/803091114/TB2XhAPaVXXXXXmXXXXXXXXXXXX_!!803091114.jpg 2x, http://gtms04.alicdn.com/tps/i4/TB1wDjWGXXXXXbtXVXX6Cwu2XXX-398-510.jpg_q75.jpg 3x">
複製程式碼
關於
srcset
的說明:猛戳這裡
2、使用js自帶的 Image
非同步載入圖片
<img id="img" data-src1x="xxx@1x.jpg" data-src2x="xxx@2x.jpg" data-src3x="xxx@3x.jpg"/>
複製程式碼
var dpr = window.devicePixelRatio;
if(dpr > 3){
dpr = 3;
};
var imgSrc = $('#img').data('src'+dpr+'x');
var img = new Image();
img.src = imgSrc;
img.onload = function(imgObj){
$('#img').remove().prepend(imgObj);//替換img物件
};
複製程式碼
3.3.2 對於背景圖片高清解決方案
1、使用 media query
來處理
/* 普通螢幕(裝置畫素比例小於等於1)使用1倍的圖 */
.css{
background-image: url(img_1x.png);
}
/* 高清螢幕(裝置畫素比例大於等於2)使用2倍圖 */
@media only screen and (-webkit-min-device-pixel-ratio:2){
.css{
background-image: url(img_2x.png);
}
}
/* 高清螢幕(裝置畫素比例大於等於3)使用3倍圖 */
@media only screen and (-webkit-min-device-pixel-ratio:3){
.css{
background-image: url(img_3x.png);
}
}
複製程式碼
2、使用 image-set
來處理(有相容問題)
.css {
background-image: url(1x.png); /*不支援image-set的情況下顯示*/
background: -webkit-image-set(
url(1x.png) 1x,/* 支援image-set的瀏覽器的[普通螢幕]下 */
url(2x.png) 2x,/* 支援image-set的瀏覽器的[2倍Retina螢幕] */
url(3x.png) 3x/* 支援image-set的瀏覽器的[3倍Retina螢幕] */
);
}
複製程式碼
3.4 1畫素問題
什麼是 1畫素問題 ?
我們說的1畫素,就是指1 CSS畫素。
比如設計師實際了一條線,但是在有些手機上看著明顯很粗,為什麼?
因為這個1px,在有些裝置上(比如:dpr=3),就是用了橫豎都是3的物理畫素矩陣(即:3x3=9 CSS畫素)來顯示這1px,導致在這些裝置上,這條線看上去非常粗!
其實在在中手機上應該是1/3px顯示這條線。
關於 dpr
,不理解的,可以看看之前的 這篇 文章。
問題描述清楚了,我們該怎麼處理呢?
方案1:使用css3的 scaleY(0.5)
來解決
比如:div的border-top的1px問題解決。
.div:before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: auto;
right: auto;
height: 1px;
width: 100%;
background-color: #c8c7cc;
display: block;
z-index: 15;
-webkit-transform-origin: 50% 0%;
transform-origin: 50% 0%;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
.div:before {
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
@media only screen and (-webkit-min-device-pixel-ratio: 3) {
.div:before {
-webkit-transform: scaleY(0.33);
transform: scaleY(0.33);
}
}
複製程式碼
但是,這種方案只能解決直線的問題,涉及到圓角之類的,就無能為力!
方案2:頁面縮放解決問題
我們先來講講頁面縮放能解決1px問題的原理示。
首先大家需要了解一些 viewport
的常識,參考:這裡
假如以下手機的 dpr=2
對於dpr=2的手機裝置,1px就會有 2x2
的物理畫素來渲染,但是當縮放以後其實就變成 1x1
個單位渲染了,看下面示意圖:
所以,我們的思路就是將真個頁面縮小dpr倍,再將頁面的根字型放大dpr倍。這樣頁面雖然變小了,但是由於頁面整體採用rem單位,當根字型放大dpr倍以後,整體都放大了,看上去整體樣式沒什麼變化。
1、將scale設定為1/dpr
假如:dpr = 2
<meta name="viewport" content="width=device-width,initial-scale=0.5">
複製程式碼
2、clientWidth獲取的值會自動擴大dpr倍
比如,以前是360px,當頁面縮小0.5倍,獲取到的值會變為720px。
不知道這個原理的,這篇文章講的還是比較清楚:這裡
var deviceWidth = document.documentElement.clientWidth;
document.documentElement.style.fontSize = deviceWidth + 'px';
複製程式碼
3、css中涉及到1畫素問題的地方使用 px
作為單位
比如:
.box{
border : 1px solid #ddd;
}
複製程式碼
以上步驟最終整理的結果:
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<div class="box">
<div class="logo">Logo</div>
</div>
</body>
</html>
複製程式碼
js:
//獲取螢幕寬度、dpr值
var deviceWidth = document.documentElement.clientWidth,
dpr = window.devicePixelRatio || 1;
//設定根字型擴大dpr倍
//由於deviceWidth當頁面縮小dpr倍時,本身獲取的值就增加dpr倍
//所以這裡不需要再乘以dpr了
document.documentElement.style.fontSize = deviceWidth + 'px';
//設定頁面縮放dpr倍
document.getElementsByName('viewport')[0]
.setAttribute('content','width=device-width;initial-scale=' + 1/dpr)
複製程式碼
scss:
@function calc($val){
@return $val / 1080;
}
.logo{
width : calc(180rem);
}
.box{
border : 1px solid #ddd;
}
複製程式碼
3.5 橫豎屏顯示問題
橫豎屏問題,就是當你橫屏手機、豎屏手機時看到的不一樣的效果問題。
我這裡要說的這個問題,就是設計師會針對橫屏或者豎屏,做不一樣的設計,比如:橫屏時顯示摘要,豎屏時只有標題,這種情況下,我們應該怎麼適配的問題。
關於橫豎屏問題,我將會分2個部分來說明:
- 橫豎屏顯示內容不同;
- 橫豎屏顯示樣式不同;
3.5.1 橫豎屏顯示內容問題
我們知道橫屏,相當於螢幕變寬了,這時候一行顯示的內容就可以更多。所以,設計師可能會對橫豎屏做2種不同的內容設計,如:
如果設計師本身就設計了2套樣式,那麼我們只需要準備2套css,依據橫豎屏直接顯示對應的樣式,然後html中做好相容即可。
下文會將如何判斷橫豎屏。
3.5.2 橫豎屏顯示樣式問題
這裡有個要說的就是,設計師沒有設計橫屏的樣式,那麼如果我們按照上文提到的方案去處理,那麼就會發現在橫屏模式下字型顯得非常大(因為螢幕寬了),顯示的內容就少了。
這種情況會顯得很不協調,雖然還是等比例顯示的,只不過需要多拖動下滾動條而已,但是你會覺得很怪。尤其是再有彈出框的時候,會更麻煩,彈出框有時候可能還會顯示不完全。。。
比如,下面的樣式:
像這種問題,我們上面提到的依據螢幕寬度自動調整根目錄font-size的大小,就有點不合適了。這樣雖然保證了橫向的比例是嚴格按照設計搞來的,但是顯示上非常醜。
所以,我們一般的做法就是在橫屏的時候將 deviceWidth=deviceHeight
。
- 正常豎屏大小:
- 橫屏時讓width=height
- 不做橫豎屏特殊寬度處理時
以上3組畫面對比我們得到的效果是:
- 在橫屏下如果讓width=height,那麼整體頁面的寬度等於豎屏時看到的寬度,整體佈局不會有變化,只是縱向看到的內容多少發生了變化;
- 如果橫屏不做處理,橫屏是width其實就等於豎屏時的height,即700px,這時候整體頁面顯示非常寬,文字比較大。
所以,經過我們的實際對比體驗以後,一致認為橫屏時讓 width=height
體驗比較好。
附上核心程式碼:
var deviceWidth = document.documentElement.clientWidth,
deviceHeight = document.documentElement.clientHeight
//橫屏狀態
if (window.orientation === 90 || window.orientation === -90) {
deviceWidth = deviceHeight;
};
//設定根字型大小
document.documentElement.style.fontSize = deviceWidth + 'px';
複製程式碼
3.5.3 附1:JS檢測橫豎屏
js獲取螢幕旋轉方向:window.orientation
- 0 - 正常方向
- -90 - 螢幕順時鐘旋轉90度
- 90 - 螢幕逆時針旋轉90度
- 180 - 螢幕旋轉180度
window.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", function() {
if (window.orientation === 180 || window.orientation === 0) {
console.log('豎屏狀態!');
};
if (window.orientation === 90 || window.orientation === -90 ){
console.log('橫屏狀態!');
}
}, false);
複製程式碼
3.5.4 附2:CSS判斷橫豎屏
- 寫在同一個CSS中:
@media screen and (orientation: portrait) {
/*豎屏 css*/
}
@media screen and (orientation: landscape) {
/*橫屏 css*/
}
複製程式碼
- 分開寫在2個CSS中,在link中通過media篩選載入:
<!-- 豎屏 -->
<link rel="stylesheet" media="all and (orientation:portrait)" href="portrait.css">
<!-- 豎屏 -->
<link rel="stylesheet" media="all and (orientation:landscape)" href="landscape.css">
複製程式碼
3.6 手機字型縮放問題
手機字型縮放是什麼問題呢?
就是當你在手機 設定 -> 字型設定
中將字型放大或者縮小,使得手機整體系統字型發生了變化,這時候可能就會影響到H5頁面正常的顯示。
經過實際測試,這個問題當前發生的概率不是很大,因為很多手機廠商都已經做了保護措施。但是為了保險起見,我們還是有必要進行檢測,一旦不一樣就要採取措施。
3.6.1 如何檢測手機字型不是預設字型
var deviceWidth = document.documentElement.clientWidth;
//設定根字型大小
var setFz = deviceWidth + 'px';
document.documentElement.style.fontSize = setFz;
//獲取實際html字型大小
var realFz = window.getComputedStyle(document.documentElement)
.getPropertyValue('font-size') //如:360px
//比較二者是否相同
if(setFz !== realFz){
//TODO 設定的字型和實際顯示的字型不同
};
複製程式碼
3.6.2 如果手機字型不是預設字型如何處理
比如:你想設定的字型大小為100px,但是實際大小卻為50px,那麼你可以確定其實使用者字型是縮放了0.5,這時候你就需要將你的字型擴大1倍,這樣才能保證實際頁面的字型是100。
所以,按照這個等比例換算以後,我們就需要重新設定頁頁面的font-size。
var deviceWidth = document.documentElement.clientWidth;
//設定根字型大小
var setFz = deviceWidth + 'px';
document.documentElement.style.fontSize = setFz;
//獲取實際html字型大小
var realFz = window.getComputedStyle(document.documentElement)
.getPropertyValue('font-size') //如:360px
//比較二者是否相同
if(setFz !== realFz){
//去掉單位px,下面要參與計算
setFz = parseFloat(setFz);
realFz = parseFloat(realFz);
//重新計算要設定的新的字型大小
//公式推導:100 -> 50,x -> 100,求x?
//即:setFz -> realFz, x -> setFz,求x?
var x = setFz * setFz / realFz;
//重新設定html的font-size
document.documentElement.style.fontSize = x + 'px';
};
複製程式碼
這麼做理論上已經解決了問題,但是還有點瑕疵,問題就是:
- 如果字型不是預設字型,首先會設定一次font-size,重新計算後再次設定一次font-size,反應到頁面上就是頁面可能會快速晃動一次,因為兩次設定的字型大小不一樣,如果手機配置不高,估計晃動會很明顯。
如何解決這個問題?思路就是:
- 給頁面增加一個隱藏元素,設定其字型大小為100px
- 獲取這個元素在頁面上的實際字型大小是否為100px
- 如果設定的和實際的不等,則計算其比例。
最終程式碼片段如下:
var deviceWidth = document.documentElement.clientWidth;
var setFz = '100px';
//給head增加一個隱藏元素
var h = document.getElementsByTagName('head')[0],
s = document.createElement('span');
s.style.fontSize = setFz;
s.style.display = 'none';
h.appendChild(s);
//判斷元素真實的字型大小是否100px
//如果不相等則獲取真實的字型換算比例
var realFz = getComputedStyle(s).getPropertyValue('font-size');
if(setFz !== 'realFz'){
//去掉單位px,下面要參與計算
setFz = parseFloat(setFz);
realFz = parseFloat(realFz);
//由於:var x = setFz * setFz / realFz;
//公式推導:x -> setFz, y -> deviceWidth
//所以:var y = deviceWidth * x / setFz;
//重置deviceWidth
deviceWidth = deviceWidth * setFz / realFz;
};
document.documentElement.style.fontSize = deviceWidth + 'px';
複製程式碼
四、最終適配方案(v1.0)
除了上面一步步的分析中間的原理之外,我們可能還需要考慮或者遇到以下問題:
- 到底什麼時候動態初始化上面的js指令碼?
- 偶爾還可能會遇到進入頁面時
document.documentElement.clientWidth=0
的bug? - 頁面晃動?頁面空白?頁面整體凌亂然後又正常等問題?
所以,在儘可能的解決諸多問題後,最終的指令碼如下:
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<!-- 正文 -->
</body>
</html>
複製程式碼
js:
/**
* @DESCRIPTION 移動端頁面適配解決方案 v1.0
* @AUTHOR Night
* @DATE 2018年08月01日
*/
(function(window, document){
var docEle = document.documentElement,
dpr = window.devicePixelRatio || 1,
scale = 1 / dpr;
var fontSizeRadio = 1, //手機字型正常比例
isLandscape = false;//是否橫屏
///////////////////////// viewport start //////////////////////////////////
//設定頁面縮放比例並禁止使用者手動縮放
document.getElementsByName('viewport')[0].setAttribute('content','width=device-width,initial-scale='+scale+',maximum-scale='+scale+',minimum-scale='+scale+',user-scalable=no');
///////////////////////// viewport end //////////////////////////////////
//橫屏狀態檢測
if (window.orientation === 90 || window.orientation === -90) {
isLandscape = true;
};
///////////////////// system font-size check start //////////////////////
//試探字型大小,用於檢測系統字型是否正常
var setFz = '100px';
//給head增加一個隱藏元素
var headEle = document.getElementsByTagName('head')[0],
spanEle = document.createElement('span');
spanEle.style.fontSize = setFz;
spanEle.style.display = 'none';
headEle.appendChild(spanEle);
//判斷元素真實的字型大小是否setFz
//如果不相等則獲取真實的字型換算比例
var realFz = getComputedStyle(headEle).getPropertyValue('font-size');
if(setFz !== 'realFz'){
//去掉單位px,下面要參與計算
setFz = parseFloat(setFz);
realFz = parseFloat(realFz);
//獲取字型換算比例
fontSizeRadio = setFz / realFz;
};
///////////////////// system font-size check end //////////////////////
var setBaseFontSize = function(){
var deviceWidth = docEle.clientWidth,
deviceHeight= docEle.clientHeight;
if(isLandscape){
deviceWidth = deviceHeight;
};
docEle.style.fontSize = deviceWidth * fontSizeRadio + 'px';
};
setBaseFontSize();
//頁面發生變化時重置font-size
//防止多個事件重複執行,增加延遲300ms操作(防抖)
var tid;
window.addEventListener('resize', function() {
clearTimeout(tid);
tid = setTimeout(setBaseFontSize, 300);
}, false);
window.addEventListener('pageshow', function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(setBaseFontSize, 300);
};
}, false);
})(window, document);
複製程式碼
scss:
//設計稿尺寸大小,假如設計稿寬度750
$baseDesignWidth = 750;
@function calc($val){
@return $val / $baseDesignWidth;
}
//適配元素採用rem,假如設計稿中元素寬度180
.logo{
width : calc(180rem);
}
//邊框採用px,假如設計稿邊框寬度1px
.box{
border : 1px solid #ddd;
}
複製程式碼
五、新頁面適配技術可以考慮(v2.0)
如果不太考慮老的手機型號,可以採用 viewport
單位。
由於我本人也沒有在專案中使用這個方案,所以不過多發表言論,大家有興趣的可以研究下。
具體方案細節參考:
六、後記
講了這麼多,這裡總結下,任何事情弄懂原理最重要!
比如,當你首次看 使用Flexible實現手淘H5頁面的終端適配 這篇文章的時候你會很感慨,感覺很有收穫,但是當你實際開始專案的時候,卻不知道該怎麼下手。
俗話說,臺上一分鐘,臺下十年功。
為了寫本文以及姊妹篇,我個人零零散散的時間加起來不下1個月,一直到(2016年12月2日
)才發表了本文的第一版。由於收到一些流言反饋和後續知識的積累,於是決定今天(2018年08月01日
)再把它重新整理一遍,以讓大家更清楚這中間的原理。
因為中間涉及的東西太多,只要有一個知識有些不清楚,可能就會卡克!比如這個概念 dips
,不同的文章有不同的說法,而且還給你解釋了它跟 dip
的不同,其實就是指 CSS畫素
,這些人故意發明一些專業詞彙,搞的你暈頭轉向,所以,當你看了我的這兩篇文章,也許還是一知半解,這很正常,慢慢來,多多練習,相信你會明白的。
如果還有哪裡不清楚,或者本文有錯誤的地方,感謝批評指正。
本文重新編輯於:2018年08月01日
- 針對大家的留言以及個人的反覆推敲,重新整理了這遍文章;
- 增加針對手機本身字型放大、縮小的解決方案,以及一些新的替代方案思路。
參考
- 使用Flexible實現手淘H5頁面的終端適配
- 移動開發螢幕適配分析
- 移動端高清、多屏適配方案
- web app變革之rem
- 移動端H5頁面的設計稿尺寸(上)
- 移動端H5頁面的設計稿尺寸(下)
- H5自適應改造方案——rem方案
- 移動端H5頁面之iphone6的適配
- WebKit最新特性srcset簡介
- HTML5實戰與剖析之判斷移動端橫屏豎屏功能
- Retina屏的移動裝置如何實現真正1px的線?
- 解決因為手機設定字型大小導致h5頁面在webview中變形的BUG
(全文完)