移動端佈局

下面我們所說的是需要兼容的系統爲iOS 5+、Android 2.3+、Windows Phone 8+。對於普通頁面來說,iOS比較好兼容;Android低版本有老規範,需要注意;Windows Phone 8裏按道理說應該是IE11,結果QQ和百度瀏覽器還是IE10的內核。。。
所以一般CSS3的代碼通常要寫兩至四句,兼容以上各種系統:
-webkit-transition: all 0.5s ease;transition: all 0.5s ease;-webkit-box-flex: 1;-webkit-flex: 1;-ms-flex: 1;flex: 1;
這裏沒有火狐什麼事。關於瀏覽器前綴支持,請看caniuse這個網站。
下面我將介紹五種常見的佈局方式,希望給大家一點思路。理解原理,合理運用,不要照抄。


1、固定佈局

固定佈局是第一次做移動端的朋友們最好的選擇方式,思路沿用PC端,上手比較快。<head>裏把viewport加好,然後設想整個網頁的寬度爲320px即可。其他地方PC端怎麼佈局,這裏類似即可。
缺點也顯而易見,大屏手機顯示網頁比較寬,而固定佈局寬度參照永遠是320px,導致左右兩邊會有空白。就像你用27寸顯示器看980px寬度網頁一樣。另一個方面就是手機橫屏的時候,兩邊空白更寬。

2、流動佈局

以前PC端很少用到這種佈局,因爲我們需求要麼網頁就一種寬度,要麼就兩種寬度,分寬窄屏處理。而手機上不同,大部份手機默認寬度都不一樣,所以流動佈局可以很好解決自適應需求。
流動佈局重點就是使用百分比來代替傳統px作爲單位(當前容器寬度除以父級容器實際寬度)。例如設計稿寬度爲640px,上面有一個導航裏包含四個菜單,四周邊距爲20px,四個菜單等寬,那麼邊距應該爲20px/640px=3.125%,每個菜單的寬度爲100%/4=25%。DEMO裏還有邊框,所以記得改變盒子模型,加box-sizing:border-box。
優點是無論網頁寬度如何改變,四個菜單的寬度永遠一樣,並且等寬。缺點是不夠靈活,如果菜單數量有變化,就滿足不了了。

3、浮動佈局

很多樂觀的人,看到Flexbox最新一版的規範,滿心歡喜的覺得移動端可以不用浮動佈局了。但很遺憾,對於Android 2.3支持的Flexbox老規範,連最簡單的多行商品按順序排列,都實現不了。對於這種情況,我喜歡用傳統的浮動方式。因爲對於開發人員,這種循環是最簡單的。再加上:nth-child僞類處理邊距,乾脆利落。所以,我並沒有放棄浮動佈局。當然,因爲不需要兼容老版本IE了,浮動的寫法也變得簡單許多。
.clearfix{    content:"";    display:table;    clear:both;}
我在Less的公共代碼庫裏,也加了這個:
.clearfix(){    &:after{        content:"";        display:table;        clear:both;    }}需要清除浮動,直接寫.clearfix()即可。floid app工具

4、Flexbox佈局

上一篇入門文章已經提到這貨了,不知道你有沒有試過,是不是很神奇?現在我大部份佈局都是用Flexbox,包括你以前用浮動的情況,大部份也可以用Flexbox代替。

例如上面流動佈局用百分比做的寬,侷限性就是無法增加刪除菜單,改變菜單數量。如果改爲用Flexbox佈局,這個問題迎刃而解,不論菜單有多少個,都自動等寬排列成一行。

再說兩點:

Flexbox有好幾版,所以會導致不兼容的情況,特別是Android 2.3。做了個小工具→Flexbox生成工具←。暫時只做了最簡單的幾種情況,但都兼容iOS 5+、Android 2.3+、Windows Phone 8+,滿足日常需求沒問題。
在Flexbox裏,margin很神奇,所以會導致你頻繁用margin:auto;。如果你養成了這個壞習慣,老iOS和老Android裏會死得很慘。建議用Flexbox工具裏的技術屬性,來處理居中情況。

5、混合佈局

把所有學到的知識,靈活運用在佈局中,我稱之爲混合佈局。
例如我上面DEMO裏的混合佈局示例,設計稿寬度640px,邊距20px,左側大圖寬高390px,右側小圖寬高190px。首先外層容器Flexbox,讓裏面左右結構顯示。容器640px去掉左右邊距40px剩600px,左側390px/600px=65%,右側190px/600px=31.66666667%,兩者之間邊距20px/600px=3.33333333%。右側裏面小圖片直接寬度100%,高度跟寬度1:1,最後通過Flexbox讓兩個圖一上一下,完成。三張圖片記得用圖片自適應,比例1:1。

6、定位佈局

定位在移動端也用得挺多,特別是彈窗。
position: fixed;left: 50%;top: 50%;-webkit-transform:  translate3d(-50%,-50%,0);transform:  translate3d(-50%,-50%,0);
如此簡單就搞定水平垂直居中的彈窗。實際使用中,有少數幾個手機的瀏覽器居然不支持translate3d,實在無語。如果非要兼容這些瀏覽器,推薦使用Flexbox彈窗。擴展一下,移動端建議用硬件加速的屬性,相關鏈接1、鏈接2,而不是直接用margin。(我測試過transition移動一個div,margin會卡頓)

需要各位手機網站前端開發人員需要注意的常見問題:
  
a、雖然移動端不用寫:hover,但光寫個:active是不夠的。實測Android 2.3下按過的按鈕會留下瀏覽器默認顏色,所以記得給:visited也加個顏色。
b、遇到寫動畫animation的時候,不要用到僞類上。不然Android是沒效果的。
c、用Flexbox做等分時,記得給寬度。不然Android裏如果內容字數不一樣,會撐開。

其他需要各位來待補充啦!

前言的一些碎碎念:最近一直在寫移動端的頁面,不過一直是用的別人造好的輪子,很多時候並沒有想那是爲什麼,那是怎麼樣要那麼寫,就跟着別人的文檔去了。本以爲自己對移動端的那一丟丟理解,結果很多東西都特麼有問題,所以,今天停下了手中的一些東西,來談下移動端的佈局方案吧

內容有些長,這也是我第一次寫博客,不足之處還請嚴厲指出

一. viewport

  1. 什麼是viewport

    簡單來講,viewport就是瀏覽器上,用來顯示網頁的那一部分區域了,也就是說,瀏覽器的實際寬度,是和我們手機的寬度不一樣的,無論你的手機寬度是320px,還是640px,在手機瀏覽器內部的寬度,始終會是瀏覽器本身的viewport。如今的瀏覽器,都會給自己的本身提供一個viewport的默認值,可能是980px,或者是其他值。就以手機來說吧,目前,新版本的手機瀏覽器,絕大部分是以980px作爲默認的viewport值的。我這裏對新版本的不同平臺下的瀏覽器做了測試,經過測試,iphone下的默認viewport爲980px,安卓下的瀏覽器,目前主流的最新瀏覽器(比如chrome,還有很多國產的像qq,uc)的viewport也是980px了。

  2. viewport是用來幹什麼的

    viewport的默認值,一般來說是大於手機屏幕的。這樣就可以做到當我們在瀏覽桌面端網頁的時候,可以讓桌面端端網頁正常顯示(我們普通頁面設計的時候,一般頁面的主區域是以960px來做的,所以980px這個值,可以做到桌面端網頁的正常顯示)。但是,其實我們手機的屏幕寬度是沒有960px的,因此瀏覽器會出現橫向滾動條。同時,即使是基於980的viewport,我們在移動端瀏覽我們的桌面頁面的體驗其實也並不好,所以,一般的,我們會專門給瀏覽器設計一個移動端的頁面。

  3. 對viewport的控制

    如今可以絕大部分瀏覽器裏(即主流的安卓瀏覽器和ios),都支持對viewport的一個控制了。一般的,我們會這麼寫。

    viewport默認有6個屬性

    • width: 設置viewport的寬度(即之前所提及到的,瀏覽器的寬度詳),這裏可以爲一個整數,又或者是字符串"width-device"
    • initial-scale: 頁面初始的縮放值,爲數字,可以是小數
    • minimum-scale: 允許用戶的最小縮放值,爲數字,可以是小數
    • maximum-scale: 允許用戶的最大縮放值,爲數字,可以是小數
    • height: 設置viewport的高度(我們一般而言並不能用到)
    • user-scalable: 是否允許用戶進行縮放,'no'爲不允許,'yes'爲允許

    我們把這個標籤是在head裏面,像這樣

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

    這樣就可以做到對viewport的控制了

二. 關於我們的設備

  1. 三個需要了解的概念:

    • PPI: 可以理解爲屏幕的顯示密度
    • DPR: 設備物理像素和邏輯像素的對應關係,即物理像素/邏輯像素
    • Resolution: 就是我們常說的分辨率
  2. 物理像素與邏輯像素

    看了我們上面內容一的第一點之後,或許有些人會有些疑問,我的安卓手機,或者iphone6plus(目前應該僅限於這一款機型吧),買回來的是1920x1080的或者其他更高的,比我之前所謂的那個viewport默認的980px要大。

    這樣的問題,也就是我之前所說的物理像素與邏輯像素的關係了(即DPR)。以1920x1080爲例,1080爲物理像素,而我們在viewport中,獲取到的,比如"width-device",是邏輯像素。所以之前viewport的默認值,所比對的大小,其實是邏輯像素的大小,而非物理像素的大小。

    以iphone6爲例,在不做任何縮放的條件下,iphone6的獲取到的'width-device'爲375px,爲屏幕的邏輯像素。而購買時我們所知的750px,則爲屏幕的物理像素。

  3. CSS的問題

    有了上面第二點的一些基礎,還是以iphone6爲例,我們可以知道,其實我們所寫的1px,在iphone6上爲2px的物理像素。所以,最後的,給出一個結論。就是我們寫的1px,在移動端,是邏輯像素的1px,而非物理像素的1px。

三. 使用rem佈局

  1. 簡單說下rem

    rem是根據頁面的根元素的font-size的一個相對的單位,即

    html{
    	font-size: 16px;
    }	

    比如當我們在一個div中,如此寫

    div{
    	width: 2rem;
    }

    那麼我們的width,是16*2 = 32px

  2. rem做到適配不同分辨率

    這個是現在手機淘寶的移動端的解決方案,即使用rem的特性,來對頁面進行佈局。

    下面舉一個例子

    假定設計稿的大小爲750,那麼我們則將整個圖分成100份來看(下面的題外話會說明爲什麼會分成100份來看)

    那麼,我們現在就讓根部元素的font-size爲75px

    html{
    	font-size: 75px;
    }

    那麼,我們現在就可以比對設計稿,比如設計稿中,有一個div元素,寬度,高度都爲75px,那麼我們這樣寫即可

    div{
    	height: 1rem;
    	width: 1rem;
    }

    可能看到這裏,一些人還是不明白怎麼用rem做到適配不同的分辨率,那麼我們再來

    現在,我們換設備了,不用這個設備是一個width爲640的手機

    那麼這個時候,我們的rem單位就起到作用了。

    我們的rem全是根據html的font-size來改變的,所以說,這個時候,我們只需要把html下的font-size改成64px。那麼,我們之前的div,因爲是根據html下的font-size動態變化的,那麼。此時也就變成了寬度和高度都爲64px的東西了。這樣,就可以做到適配不同的屏幕分辨率了。(其實就是個等比縮放)

    總結一下,我們的解決方案,其實就是 設計稿的像素/html的font-size = 用來代替px的rem。

    這一個步驟,我們需要通過JS來進行操作。

    對於js的操作在下面會提到。

  3. DPR的問題

    視覺姐姐給了我們設計稿,並交由我們實現,那麼,我們應該去認真的實現:-)(試想你做了一張圖,而前端很多地方並沒有按照你所想的,你所給的去做,而是私自改變了很多東西,你肯定會不高興的)

    那麼1px會出現什麼問題呢。

    還記得我們第二大點講的,我們的設備,是有物理像素和邏輯像素的。而假設我們的設計稿是750的,同時還是以iphone6爲例,此時如果我們的viewport是這樣的

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

    之前說過,在不做任何縮放的條件下,iphone6獲取到的viewport爲375px。

    然後我們的頁面中有個div,他有一個邊框值,如下

    div{
    	height: 5rem;
    	widht:5rem;
    	border: 1px solid #000
    }

    此時我們寫的1px,實際上是邏輯像素,而我們在iphone6上看到的是物理像素,於是這個時候,我們眼睛所看到的其實是2px(參考第二點第三個問題)

    所以此時我們需要在viewport上做文章了,此時先明確,如果要獲取到真正的1px,那麼我們需要這麼做,將viewport改爲

    <meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

    即對屏幕做0.5倍的縮放。這樣,我們就能得到實際的1px。

    所以到這裏,我們還要明確一點,viewport的meta標籤,我們這裏也只能通過js來動態生成。

    同時,這樣寫,據說還可以避免比如inline的SVG等元素按照邏輯像素的渲染。避免了整個頁面清晰度的打折(其實我並不能看出來)

  4. 文字適配問題

    最近深深糾結與rem與px做字體單位的問題,還是先分別談下二者吧。

    rem與px的特點:

    • 以rem作爲字體單位:我們可以讓頁面整體的文字,也跟隨着html的font-size來進行改變,這樣,在不同的屏幕下,可以做到文字相對屏幕的比例是一樣的。

    • 以px作爲字體單位: 這個是目前很多網站還是依然採用的方法。因爲以上面所寫的,以rem作爲字體單位。無論在任何屏幕下面,我們的文字都會根據屏幕做一個適應。試想這樣一個場景。你買了一個大屏手機(5.7寸的),而別人用的是4寸的手機。以rem作爲字體單位的話,那大屏手機看到的文字多少和小屏手機確實一樣的了。這樣來做,其實並不符合我們買大屏手機的期待。同時,以rem作爲字體單位,可能會導致出現很多奇怪的字體大小(畢竟是根據html的font-size動態變化的嘛),同時這其中還涉及到了一個點陣尺寸的概念,這個在下面來講。

    字體大小引發的系列問題:

    • 字體大小:我們平時也看過,很多網站,是不以奇數作爲字體大小的。我稍微查了些東西,在知乎上的現在網頁設計中的爲什麼少有人用 11px、13px、15px 等奇數的字體?問題下,有一些比較好的解答,我就不再多說(我也並不能比這個問題說的更多),總的來說,其實就是偶數寬度的字體能夠顯得均衡,以及一個點陣的問題。不過因爲要談及點陣,所以我拿上面回答中的一個內容舉例。

      • 倘若一個字體,只提供了12px,14px,16px的點陣。那麼當你寫13px,15px,17px的時候。就並沒有其字體大小所對應的點陣。那麼這樣就造成了一個問題。他們會使用其相鄰的點陣,比如對應使用了12px,14px,16px的點陣,而導致一個問題,文字佔用的大小確實改變,但點陣卻並沒有改變。

    文字適配的解決方案:

    上面說了這麼多,我們總要有一套解決方案吧

    對於一些標題性的文字,我們依然可以用rem。讓他隨着屏幕來進行縮放,因爲標題性文字一般較大,而較大的文字,點陣對其影響就越小。這樣,即使出現奇怪的尺寸,也能夠讓字體得到很好的渲染。

    對於一些正文內容的文字(即站在使用者的角度,你不希望他進行縮放的文字)。我們採用px來進行處理。

四.安卓與ios不得不說的問題(解決篇)

  1. 在 三.使用rem佈局 裏面,我們給出了各種情況的解決方案,並且,在我舉例的時候,熱衷於使用iphone來舉例,但其實,上面的所有問題,不是僅僅iphone會出現的問題,安卓也是一樣。但是,如果你已經看完了上面,那麼這裏,纔是真正給出我們解決方案的地方,並且,這個解決方案並不完善。

  2. 談談iphone的r屏與安卓的各種屏

    rem佈局也好,用viewport進行縮放也罷,文字的適配問題也是,都是基於我們想對各個不同的設備所進行的匹配。這套方案很好,然而也有其兼顧不到的地方。即安卓和ios的屏幕的一些問題,當然,細的東西我們不談,我們只談dpr。

    • 先談iphone

      • 其實iphone爲開發者考慮到了很多東西,爲了讓開發者便於開發,在6plus出現之前,iphone的dpr始終也就是2(即前面所談的物理像素/邏輯像素=2),即使是6plus出現了,iphone到底其實也就只有2,3這兩個dpr。我們很容易對其做到兼顧。
    • 再談安卓

      • 安卓並沒有對自己的屏幕叫做r屏,但是其原理和iphone的r屏可以說是一樣。r屏做的是什麼,把兩個(三個)物理像素,丟到了一個邏輯像素裏面,讓屏幕展現的更清晰(當然,這是我片面的理解,不過我覺得大體來說並沒有錯,我們也不用去深入探討r屏還有什麼東西,我也並不懂)。而安卓也是一樣,他也同樣把n個物理像素丟到了一個邏輯像素裏面。而這裏的n,也就是dpr值(所以當我看到好多人問安卓爲什麼不採用r屏的時候,我真的也是……醉了?)。而安卓的dpr值,並不像iphone那樣,就只有兩個值。安卓的dpr是千奇百怪的,可能是1.5,2,3,4,2.5等等的都有。(甚至我還看到了1.7之類的,安卓的各個設備商,玩的真尼瑪high啊。怎麼高興怎麼來。)

        所以,對安卓的屏幕的dpr的處理,其實是很頭疼的,因爲,他和我們對字體的處理,有了很大的衝突。這個在下面提及

  3. 首先看看手淘的解決方案

    • rem佈局

      用js獲取到頁面的寬度,然後對其進行寬度/10的處理,再將其寫到html的font-size中。手淘的flexible.js裏面的這一部分,併爲了方便看懂做了些改寫。大體就是這樣的

      function refreshRem(){
       	var docEl = window.document.documentElement;
          var width = docEl.documentElement.getBoundingClientRect().width;
      
          var rootSize = width/10;
          docEl.style.fontSize = rootSize + 'px';
      }
    • dpr的配置

      首先,在引入flexible.js之前,我們可以對dpr進行手動的配置,即使用自定義的meta標籤來配置dpr(看清楚是flexible,而非viewport)

      <meta name="flexible" content="initial-dpr=2,maximum-dpr=3" />

      iniital-dpr是把dpr強制設定爲給定的值,而maximum-dpr則是給出一個最大的dpr限制,然後對其和系統的dpr做一個比較。

      然後依然爲了方便閱讀我把flexble.js這一部分的代碼抽象出來,

          var doc = window.document
          var metaEl = doc.querySelector('meta[name="viewport"]');
      	var flexibleEl = doc.querySelector('meta[name="flexible"]');
      	var dpr = 0;
      	var scale = 0;			//縮放比例
      	//在meta標籤中,已經有了viewport,則使用已有的viewport,並根據meta標籤,對dpr進行設置
      	if (metaEl) {
      		console.warn('將根據已有的meta標籤來設置縮放比例');
      		var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
      		if (match) {
      			scale = parseFloat(match[1]);
      			dpr = parseInt(1 / scale);
      		}
      	//如果在meta標籤中,我們手動配置了flexible,則使用裏面的內容
      	} else if (flexibleEl) {
      		var content = flexibleEl.getAttribute('content');
      		if (content) {
      			var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
      			var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
      			if (initialDpr) {
          			dpr = parseFloat(initialDpr[1]);
          			scale = parseFloat((1 / dpr).toFixed(2));    
      			}

      if (maximumDpr) {
      dpr = parseFloat(maximumDpr[1]);
      scale = parseFloat((1 / dpr).toFixed(2));
      }
      }
      }

      這樣,我們通過flexible的分析與獲取,對dpr進行了書寫。不過其實這裏,是有個問題的。即在書寫maximum的的情況下,其實根本沒有像文檔中給我們的說法一樣,做一個比較,而是做了和initialDpr一樣的一個處理。不過這裏也不對其做一個探討了。

      然後,這套解決方案,然後當我們在meta標籤裏面並沒有對viewport以及flexible兩個的任意一個進行書寫的時候,他也是會自動獲取一個dpr值的

      if (!dpr && !scale) {
      	var isAndroid = window.navigator.appVersion.match(/android/gi);
      	var isIPhone = window.navigator.appVersion.match(/iphone/gi);、
      	//devicePixelRatio這個屬性是可以獲取到設備的dpr的
      	var devicePixelRatio = win.devicePixelRatio;
      	if (isIPhone) {
      	// iOS下,對於2和3的屏,用2倍的方案,其餘的用1倍方案
      	if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                
          	dpr = 3;
      	} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
          	dpr = 2;
      	} else {
          	dpr = 1;
      	}
      } else {
      	// 其他設備下,仍舊使用1倍的方案
      	dpr = 1;
      	}
      	scale = 1 / dpr;
      }

      這裏我們可以看到,手機淘寶並沒有對安卓的dpr進行一個適配,原因之後再講。

      然後到了這裏,我們獲取到了我們需要的dpr值,並根據dpr值獲取到了我們所需要的縮放值(即scale)

      然後我們要做的,就是在並沒有viewport的meta標籤對情況下自己動態將這個標籤寫進我們的header,形式是這樣的

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

      這樣,dpr的配置,也就完成了,當然,安卓設備並沒有對dpr進行一個配置(上面的動態生成就不給出js了)

    • 文字的解決方案

      由於手淘暫時並沒有對安卓做一個處理,所以,這裏,只是對iphone做了一個處理

      即在html上,加入了一個自定義屬性,data-dpr。

      <html data-dpr='dpr'></html>

      還是以750的設計稿爲例(即iphone6)

      假如設計稿上某a標籤是32px,那麼,我們要這麼寫

      a{
      	font-size: 16px
      }
      /*iphone6*/
      [data-dpr='2'] a{
      	font-size: 32px
      }
      /*iphone6plus*/
      [data-dpr='3'] a{
      	font-size: 32px
      }
  4. 現在的一些問題

    正如我們看到的,手淘目前的方案裏面,是沒有考慮到安卓dpr的問題的。即,這套方案,只對於iphone的r屏做了一個處理,而對於安卓,並沒有做dpr的處理。我們來分析下原因吧(個人拙見)。

    我們希望字體能夠以px來展現,同時,我們也希望我們的東西能對dpr做一個適配。對於ios,這自然是可行的,即採用了data-dpr的自定義屬性來調整文字。4到6寫一套字體大小,6p寫一套字體大小,然後在對dpr爲1的屏幕寫一套字體大小。其實這種寫法還是很噁心,不過基於對dpr的適配,這樣寫也算是個解決方案了。

    不過同樣的解決方案到安卓就不行了,安卓的dpr有時候會很亂(比如現在在goole的手機測試裏面可以看到,安卓的dpr,lg的某些設備還採用了1.7那樣的奇怪dpr)。而當1.7dpr這種不規範的數字出現的時候,我們就不能採用之前的解決方案了,比如

    [data-dpr='1.7'] a{
    	font-size: 25px
    }

    這樣的東西是不可能去寫的,那萬一還有2.25,2.5之類的呢?我們都要拿去匹配麼?

    其實現在,因爲我們通過devicePixelRatio可以獲取到安卓的dpr值,即可以做到對安卓設備的dpr一個匹配。但是,文字如果採用px的話,確實是很難做到匹配的。

    即總結一下,就是說,對於安卓的dpr匹配,目前來說,是沒有什麼問題的,但是,對於dpr匹配之後的字體,那肯定是有問題的。

    常見的dpr下的字體,我們依然可以解決,但是不常見的dpr,我們確實很難做到對dpr的解決。那如何解決這些問題呢。目前以我本人這個不太靈光的腦袋,確實也不曉得該如何進行一個處理了,起碼做不到很好的解決。

    不過,還是丟上些個人的觀點吧。

    在之前的對dpr的判斷中,是根據了設備進行判斷,即安卓不對dpr進行改變,僅對ios的設備進行改變。那麼,我們其實可不可以以dpr的值來做一個處理呢?即像這樣寫

    if (!dpr && !scale) {
    	//devicePixelRatio這個屬性是可以獲取到設備的dpr的
    	var devicePixelRatio = win.devicePixelRatio;
    	//判斷dpr是否爲整數
    	var isRegularDpr = devicePixelRatio.toString().match(/^[1-9]\d*$/g)
    	if (isRegularDpr) {
    	// 對於是整數的dpr,對dpr進行操作
     	if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                
        	dpr = 3;
    	} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
        	dpr = 2;
    	} else {
        	dpr = 1;
    	}
    } else {
    	// 對於其他的dpr,人採用dpr爲1的方案
    	dpr = 1;
    	}
    	scale = 1 / dpr;
    }	

    我們對這裏做了一點點修改,即來判斷dpr是否是規則的,也就是是否是我們常見的1,2,3等,然後,我們只對規則的dpr,來進行一個字體的處理。這樣,iphone依然還是用之前的匹配方案。而其實目前安卓,很多的設備還是比較常見的dpr了,所以我們這裏,將之前對設備的判斷,轉變成對dpr是否是整數的一個判斷。其他地方不變,可以解決對安卓dpr的部分匹配。

    同樣,開發的時候,如果並不在乎字體的問題的話,大可以直接使用rem。那樣是可以做到dpr和文字都適配的問題。不過正如我們講到字體的時候所說的,使用rem是很多用戶不希望的(大屏機還是和小屏機看到一樣多的內容),同時,還有點陣的問題。

    好,東西寫到這裏,也將近到了尾聲。第一次寫這麼長的東西,感覺好累啊=_=。嗯還有篇2000字的檢討要寫,默默匿了去寫檢討了。

參考

手機淘寶的flexible設計與實現

題外話:

  1. iphone6plus很有趣的地方

    iphone6plus照理來說的,其實際dpr是2.87左右的,不過,爲了方便開發者來開發,iphone6plus對其做了一個調整,將dpr調整爲3,然後在對屏幕進行了一個縮放。這樣做,自然是方便了開發者前去開發,然而,這樣做,也有了一些性能上的損失。(iphone爲開發者考慮的還是挺周全的,看看隔壁安卓,dpr怎麼爽怎麼來,都特麼自己玩自己的)

  2. 有意思的vh和vw

    vh,vw目前還存在很大程度的兼容性問題,所以還並沒有採用。

    vh,vw有什麼特點呢

    這兩個元素分別會把屏幕上的可視高度(說通俗點就是你手機屏幕那個框框頭裝起的東西),寬度,分成100份來看,比如先前我們用rem來處理的地方,我們需要在html元素下寫上font-size: 75px,然後再在div下寫上width:1rem。而有了vh,vw之後,我們如此處理html的font-size就好。

    html {
    	font-size: 10vw;
    }

    這樣寫,省去了一部js操作的步驟。




發佈了30 篇原創文章 · 獲贊 19 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章