適配方案(一)之移動端適配

移動端

特色

移動端下的屏幕存在如下特色:javascript

  • 屏幕相比較於PC端要小css

  • 瀏覽器不像PC端,隨時各類調整大小html

緣由

移動端因爲屏幕總體比PC端小,並且也不能出現拖動瀏覽器來調整大小的狀況,因此在移動端上的佈局是流式佈局最多,其中有些小分支,如固定小版心。前端

案例

代碼

普通的圖片和容器,寫單位的時候換成 百分比 或者 flex便可。java

對於頁面中的某些元素,如字體大小,可使用 淘寶 flexibile + rem 的解決方案android

1、普通的流式佈局

<!DOCTYPE html>
<html lang="en">css3

<head>
<meta charset="UTF-8">
<title>流式</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
<style>
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }nginx

  body {
    background-color: #ccc;
  }git

  ul {
    list-style: none;
    display: flex;
    height: 100px;
  }github

  li {
    flex: 1;
    border: 1px solid #000;
    background-color: aqua;
  }
</style>
</head>

<body>
  <main>
    <section>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>
    </section>
  </main>
</body>

</html>

效果

2、淘寶flexible + rem

flexible 和flex佈局不要緊 老婆和老婆餅 也沒有關係

這個解決方案是能夠和以上的流式佈局搭配使用的,rem的做用是主要是針對字體實現 跟隨屏幕變化而變化

  • rem css單位,相對長度,它的值等於根標籤的字體大小
  • 淘寶flexible

   是手淘團隊出的一個處理移動端rem設置的js庫

     把根標籤的字體大小改爲了 當前屏幕的十分之一大小

     根標籤的字體大小發生改變了,使用了rem單位的元素或者字體大小也跟着改變

手機淘寶的flexible方案,特色:

1.僅針對iphone生成動態viewport,由於目前iphone的dpr只有1,2,3三種,android的dpr頗有多種,不具備一致性;

2.字體大小不用rem作縮放處理,仍然使用px單位,設置不一樣dpr下對應的字體大小;

3.寬度利用rem等比縮放;

4.容許強制定義dpr;

使用時頁面頭部須要引入flexible.js.

 

流程

flexible代碼

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>版心佈局</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
<script>

(function flexible(window, document) {

  var docEl = document.documentElement;

  // 設備像素比

 

  var dpr = window.devicePixelRatio || 1;

  // 設置body元素字體大小:監聽DOM內容是否加載完畢,完畢後給body設置字體大小

  function setBodyFontSize() {

    if (document.body) {

      document.body.style.fontSize = 12 * dpr + "px";

    } else {    

      document.addEventListener("DOMContentLoaded", setBodyFontSize);

    }

  }

  setBodyFontSize();

  // 更改根元素字體大小:設置根元素字體大小爲屏幕的十分之一

 

  function setRemUnit() {

    var rem = docEl.clientWidth / 10;

    docEl.style.fontSize = rem + "px";

  }

  setRemUnit();

  // 監聽屏幕大小:監聽屏幕大小的變化,有變化調用更改根元素字體大小函數

 

  window.addEventListener("resize", setRemUnit);

  window.addEventListener("pageshow", function (e) {

    if (e.persisted) {

      setRemUnit();

    }

  });

  if (dpr >= 2) {

    var fakeBody = document.createElement("body");

    var testElement = document.createElement("div");

    testElement.style.border = ".5px solid transparent";

    fakeBody.appendChild(testElement);

    docEl.appendChild(fakeBody);

    if (testElement.offsetHeight === 1) {

      docEl.classList.add("hairlines");

    }

    docEl.removeChild(fakeBody);
  }

})(window, document);

</script>
<style>
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
</style>
</head>

<body>
<div>

</div>
<script>
  window.onload = function () {
    setFont();
    window.addEventListener("resize", function () {

      setFont();
    })


    function setFont() {
      var div = document.querySelector("div");
      div.style.fontSize = document.querySelector("html").style.fontSize;
      div.innerHTML = "html的字體大小爲" + document.querySelector("html").style.fontSize;
    }
  }
</script>
</body>

</html>

flexible效果

綜合flexible 和 rem

根據以上的特色

  • flexible根標籤字體大小改成 屏幕的十分之一

  • rem 能夠根據根標籤的字體大小改變而發生改變

得出如下解決方案

  1. 假定設計稿的寬度 是 640px

  2. 根標籤的字體大小爲 64px 也就是 1 rem = 64px => 1px=1/64rem

  3. 原設計稿中的div大小爲100px,字體大小爲100px

  4. 將px單位修改成 rem單位

div{
  width:100px;
  font-size:100px;
}
修改成
div{
  width:calc( 100rem / 64 );
  font-size:calc( 100rem / 64 );
}

  5.  將設計稿的寬度也抽象出去

div{
  width:calc( 100rem / 十分之一的設計稿寬度 );
  font-size:calc( 100rem / 十分之一的設計稿寬度 );
}

完整代碼

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>版心佈局</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
<script> 

(function flexible(window, document) { 

  var docEl = document.documentElement;

  // 設備像素比

 

  var dpr = window.devicePixelRatio || 1;

  // 設置body元素字體大小:監聽DOM內容是否加載完畢,完畢後給body設置字體大小

  function setBodyFontSize() { 

    if (document.body) { 

      document.body.style.fontSize = 12 * dpr + "px"; 

    } else {     

      document.addEventListener("DOMContentLoaded", setBodyFontSize); 

    } 

  } 

  setBodyFontSize();

  // 更改根元素字體大小:設置根元素字體大小爲屏幕的十分之一

 

  function setRemUnit() { 

    var rem = docEl.clientWidth / 10; 

    docEl.style.fontSize = rem + "px";

  }

  setRemUnit();

  // 監聽屏幕大小:監聽屏幕大小的變化,有變化調用更改根元素字體大小函數

 

  window.addEventListener("resize", setRemUnit); 

  window.addEventListener("pageshow", function (e) {

    if (e.persisted) { 

      setRemUnit(); 

    } 

  }); 

  if (dpr >= 2) { 

    var fakeBody = document.createElement("body"); 

    var testElement = document.createElement("div"); 

    testElement.style.border = ".5px solid transparent"; 

    fakeBody.appendChild(testElement); 

    docEl.appendChild(fakeBody);

    if (testElement.offsetHeight === 1) {

      docEl.classList.add("hairlines"); 

    } 

    docEl.removeChild(fakeBody); 
  } 

})(window, document); 

</script>
<style>
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  div {
    width: calc(100rem / 64);
    height: calc(100rem / 64);
    font-size: calc(100rem / 64);
    background-color: aqua;
  }

</style>
</head>

<body>
<div>

</div>
<script>
  window.onload = function () {
    setFont();
    window.addEventListener("resize", function () {

      setFont();
    })


    function setFont() {
      var div = document.querySelector("div");
      div.style.fontSize = document.querySelector("html").style.fontSize;
      div.innerHTML = "html的字體大小爲" + document.querySelector("html").style.fontSize;
    }
  }
</script>
</body>

</html>

最終效果

3、小版心

小板心的作法其實也是流式佈局中的一種,只不過對最外層容器加了一個最大寬度的設置如

main{
  max-width:540px;
}

參考

4、vw 和 vh

在移動端中,還存在如下單位,也很好用,能夠很方便解決問題。

以上單位 在移動端中,或者在小程序中都支持。

設計稿爲 375px,存在一個大小爲100pxdiv,字體大小也爲100px

  • 375px = 100 vw 那麼 1 px = 100vw / 375

  • 所以 100px = 100vw * 100 / 375;

代碼

main {
  background-color: pink;
  width: calc(100vw * 100 / 375);
  height: calc(100vw * 100 / 375);
  font-size: calc(100vw * 100 / 375);
}

詳細介紹

老版常規作法

方案一:Meida Queries媒體查詢

meida queries 主要是經過查詢設備的寬度來執行不一樣的 css 代碼,最終達到界面的配置。核心語法是:

@media screen and (max-width: 600px) { /*當屏幕尺寸小於600px時,應用下面的CSS樣式*/ /*你的css代碼*/ }

須要添加meta設置

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

width=device-width :表示寬度是設備屏幕的寬度

initial-scale=1.0:表示初始的縮放比例

minimum-scale=1.0:表示最小的縮放比例

maximum-scale=1.0:表示最大的縮放比例

user-scalable=no:表示用戶是否能夠調整縮放比例

這個標籤能夠保證在移動端設備中,頁面的寬度與屏幕寬度相同。

方案二:px + viewport縮放

以最小的Iphone4/5的寬度(320px)爲基準,還原視覺稿。

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0 />

而後對不一樣屏幕分辨率的手機進行簡單粗暴的等比例縮放設置。 例如:iphone8(375px)initial-scale = 375 / 320 = 1.18

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.18 />

initial-scale愈來愈大,頁面內容也就被拉伸也越厲害,致使頁面內容會變得模糊,這個方法已經被摒棄了。

高度定死,寬度自適應,元素都採用px作單位。

隨着屏幕寬度變化,頁面也會跟着變化,效果就和PC頁面的流體佈局差很少,在哪一個寬度須要調整的時候使用響應式佈局調調就行(好比網易新聞),這樣就實現了『適配』

方案三:響應式佈局

響應式的概念分爲兩大類

  • 一種是後端響應式

  • 一種是前端響應式

後端響應式

後臺服務器根據前端瀏覽器的User-Agent來判斷來源請求是PC端仍是移動端,而後服務器動態返回PC端頁面或者移動端頁面。nginx中很容易就出現該功能。京東,天貓,淘寶也是這樣子的。

前端響應式

主要是指經過媒體查詢來實現。

前端寫好一套代碼 html + css + javascript ,就能夠冬天的根據屏幕的寬度來改變頁面的樣式

這種作法體驗不是最好,可是倒是最小的代碼實現了 兼容pc端和移動端。通常是對頁面要求不高或者小企業使用。

因爲還要兼容到pc端,因此通常作響應式頁面 不會用過高級的h5 css3 的技術。

新作法

方案四:rem + viewport縮放

須要添加meta設置

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

 

換句話說,當咱們指定一個元素的font-size爲2rem的時候,也就說這個元素的字體大小爲根元素<html>字體大小的兩倍,若是html的font-size爲12px,那麼這個2rem的元素font-size就是24px。同理當該元素爲3rem時,那麼其實際

font-size就是36px

html {font-size: 12px;}

h1 { font-size: 2rem; } /* 2 × 12px = 24px */

p { font-size: 1.5rem;} /* 1.5 × 12px = 18px */

div {width: 20rem;} /* 20 * 12px = 240px*/

看到這裏你應該就會發現,只要咱們根據不一樣屏幕設定好根元素<html>的font-size,其餘已經使用了rem單位的元素就會自適應顯示相應的尺寸了。 

rem計算

咱們使用rem單位事先須要作的一件事情就是設置根元素<html>的font-size,一般有兩種作法

方法一:JS計算

經過JavaScript讀取屏幕寬度,而後根據寬度計算出對應的尺寸並設置根元素的font-size。

const oHtml = document.getElementsByTagName('html')[0]

const width = oHtml.clientWidth;

// 320px的屏幕基準像素爲12px

oHtml.style.fontSize = 12 * (width / 320) + "px";

這樣iphone8(375px)下html的font-size 就是14.0625px,iphone8p下font-size就是15.525px。

若是在iphone8(375px)下設置元素font-size爲 1.7066rem, 效果跟設置其font-size爲 24px 是同樣的(24 / 14.0625 = 1.7066)。

使用JS來獲取屏幕寬度的好處在於能夠100%適配全部的機型寬度,由於其<html>元素的基準尺寸是直接算出來的。既然是JS代碼,爲了不形成由於動態設置<html>元素的font-size而形成頁面抖動,通常這部分代碼咱們放在header

底部去加載,並內聯到html文檔裏面。

方法二:媒體查詢

既然只是爲了根據屏幕寬度來設置<html>元素的字體大小,那咱們徹底也能夠經過css3媒體查詢來完成這部分工做。

@media screen and (min-width: 375px){

   html { font-size: 14.0625px; }

}

@media screen and (min-width: 360px){

  html { font-size: 13.5px; }

}

@media screen and (min-width: 320px){

html { font-size: 12px; }

}

html { font-size: 16px; }

rem存在的問題

rem做爲一種簡單粗暴解決不一樣屏幕下視圖的區別的一種方案,它能夠解決本文出現的問題以及絕大多數移動端適配屏幕尺寸的問題。可是既然它並非一個完美的解決方案,那就有其侷限性所在。

大屏智能機時代確實幾乎徹底替代了我十年前紙質化閱讀的習慣。從2011年至今,手上的手機屏幕寬度一直在提高,可是使用的看小說軟件的顯示字號幾乎是不變的。使用rem會在必定程度上打破用戶的文字內容閱讀習慣,特別是在大篇

幅的內容時。

iOS與Android平臺的適配方式背後隱藏的設計哲學是這樣的:閱讀文字時,可讀性較好的文字字號行距等絕對尺寸數值組合與文字所在媒介的絕對尺寸關係不大。(能夠這樣簡單理解:A4大小的報紙和A3大小甚至更大的報紙,溫馨的閱

讀字號絕對尺寸是同樣的,由於他們都須要拿在手裏閱讀,在手機也是上同理);在看圖片視頻時,圖片、視頻的比例應該是固定的,不該該出現拉伸變形的狀況。而rem用在字號時,使字號在不一樣屏幕上的絕對尺寸不一致,違背了設計

哲學。

方案五:vw + vh

參考

簡單粗暴的移動端適配方案 - REM

阿里巴巴TXD移動端適配總結(viewport講的不錯)

淺談-web屏幕適配的解決方案

相關文章
相關標籤/搜索