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

萬少發表於2019-07-07

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

img

就目前看來,web的螢幕適配是貫穿整個前端行業的,如常見的PC端,移動端,響應式,小程式等。

1562402019217

PC端

特點

PC端的螢幕具備以下特點:

  1. 螢幕大小一般是大於 13.3英寸
  2. 使用者會經常拖拉瀏覽器的大小

1562399024495

原因

正是因為 PC端上的瀏覽器大小會經常被改變,而且改變的範圍還很大,使用者會全屏瀏覽器,使用者也會縮小瀏覽器到一個很小的值,如600px左右。 所以pc端上如果使用流式佈局(百分比佈局),會導致頁面很難看。

img

解決

所以,PC端上只能通過版心佈局來解決這種情況。

  • 當螢幕大於版心寬度時,版心居中顯示
  • 當螢幕小於版心寬度時,螢幕出現一個橫向的滾動條,這種方案几乎所有的PC端網站都在採用。

案例

img

程式碼

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

<head>
  <meta charset="UTF-8">
  <title>版心佈局</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    html,body{
      height: 100%;
      background-color: #ccc;
    }
    main{
      width: 1200px;
      height: 100%;
      margin: 0 auto;
      font-size: 40px;
      background-color: pink;
    }
    header{
      height: 80px;
      background-color: aqua;
    }
  </style>
</head>

<body>
  <main>
    <header>版心</header>
    <section>內容</section>
  </main>
</body>
</html>
複製程式碼

效果

1562400533725

移動端

特點

移動端下的螢幕存在以下特點:

  • 螢幕相比較於PC端要小
  • 瀏覽器不PC端,隨時各種調整大小

原因

移動端由於螢幕整體比PC端小,而且也不能出現拖動瀏覽器來調整大小的情況,所以在移動端上的佈局是流式佈局最多,其中有些小分支,如固定小版心。

解決

流式佈局,也叫做百分比佈局,指的是頁面上大部分的容器和元素的寬度都不是定死,可能是 百分比單位,也可能是rem單位

案例

2019-04-30090218

程式碼

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

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

淘寶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">
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      background-color: #ccc;
    }



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

    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>
複製程式碼

效果

2019-04-30090218

淘寶flexible + rem

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

這個解決方案是可以和以上的流式佈局搭配使用的,rem的作用是主要是針對字型實現 跟隨螢幕變化而變化

  1. rem css單位,相對長度,它的值等於根標籤的字型大小如

    
       <style>
        html {
          font-size: 100px;
        }
        div {
          /* 相對於 100px */
          font-size: 1rem;
        }
      </style>
      <div>
        rem單位
      </div>
    複製程式碼

    效果

    1562403035527

  2. 淘寶flexible

    1. 是手淘團隊出的一個處理移動端rem設定的js庫
    2. 把根標籤的字型大小改成了 當前螢幕的十分之一大小
    3. 根標籤的字型大小發生改變了,使用了rem單位的元素或者字型大小也跟著改變

流程

1562486744388

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; 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效果

2019-04-30090218

綜合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; 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>
複製程式碼

最終效果

2019-04-30090218

小版心

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

main{
	max-width:540px;
}
複製程式碼

參考

2019-04-30090218

小程式端

小程式端可以理解特殊的移動端,只不過小程式端不存在 rem這個單位,取而代之的是 rpx 這個單位,翻譯就是響應式畫素,功能類似 rem

特點

小程式中不需要引入淘寶flexible這個庫,因為內建的 rpx 單位就是實現了 rem + fleixible 功能。

小程式中,存在 螢幕的寬度 統一為 750 rpx 因此:存在以下關係。

螢幕寬度 換算關係 px 和 rpx
750 px 1 px = 1 rpx
375 px 1px = 2 rpx
any px 1 px = any / 750 rpx

程式碼

如 設計稿為 375px,其中存在一個view 寬度高度均為 100px ,字型大小 為 100px

    view {
      width: 200rpx;
      height: 200rpx;
      font-size: 200rpx;
      background-color: aqua;
    }
    
    <view> 小程式rpx </view>
複製程式碼

vw 和 vh

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

單位 名稱
vw 100vw 等於 視口的寬度
vh 100vh 等於 視口的高度
vMax vw 和 vh 中的較大的那個
vMin vw 和 vh 中的較小的那個

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

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

  1. 375px = 100 vw 那麼 1 px = 100vw / 375
  2. 因此 100px = 100vw * 100 / 375;

程式碼

注意 calc的語法比較嚴格 尤其注意空格

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

響應式佈局

響應式的概念分為兩大類

  1. 一種是後端響應式
  2. 一種是前端響應式

後端響應式

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

前端響應式

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

前端寫好一套程式碼 html + css + javascript ,就可以冬天的根據螢幕的寬度來改變頁面的樣式

這種做法體驗不是最好,但是卻是最小的程式碼實現了 相容pc端和移動端。一般是對頁面要求不高或者小企業使用。

由於還要相容到pc端,所以一般做響應式頁面 不會用太高階的h5 css3 的技術。

案例

如 實現一個 大螢幕下 一行顯示3列,小螢幕下 一行顯示2列。

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    ul {
      overflow: hidden;
    }

    li {
      float: left;
      height: 100px;
      border: 1px solid #000;
      background-color: pink;
    }

    /* 大螢幕 */
    @media screen and (min-width:800px) {
      li {
        width: 33.33%;
      }
    }
    /* 小螢幕 */
    @media screen and (max-width:800px) {
      li {
        width: 50%;
        background-color: lawngreen;
      }
    }
  </style>
</head>

<body>

  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
  </ul>
</body>

</html>
複製程式碼

效果

2019-04-30090218

其他

業內要實現響應式佈局時,一般會使用 推特公司的 bootstrap 框架,好評度很高,而且還針對ie8 做了相容處理。

相關文章