由于移動端的特殊性,屏幕的尺寸碎片化嚴重,要想很好的適配不同的尺寸的設備,需要我們前端開發相比 PC 端要做一些基層的適配方案。
## 一、常見的適配方案
### 1、viewport 適配方案
* 按照設計稿上標注的尺寸進行開發
* 頁面剛開始渲染的時候設置 meta,將渲染的頁面的寬度設為設計稿的寬度
* 將頁面整體縮放,縮放比例為**當前屏幕的獨立像素寬度/設計稿寬度**
```
// 放在頁面頭部
<script>
var WIDTH = 750 // 設計稿寬度
var mobileAdapter = function() {
var scale = screen.width/WIDTH // 縮放比
var content = 'width=' + WIDTH +', initial-scale=' + scale +
', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=0'
var meta = document.querySelector('meta[name=viewport]')
if(!meta) {
meta = document.createElement('meta')
meta.setAttribute('name', 'viewport')
document.head.appendChild(meta)
}
meta.setAttribute('content', content)
}
mobileAdapter()
window.onorientationchange = mobileAdapter // 監聽屏幕旋轉
</script>
```
* 優點:方便開發,不用計算,一切元素的寬高按設計稿來即可
* 缺點:邊框等不需要縮放的元素,也會跟著縮放
### 2、vw 適配方案
為了解決 viewport 適配方案的缺點(無法對部分縮放,部分不縮放),出現了vw 適配。
* 將設計稿(假設750px)上需要適配的尺寸轉換成 vw,比如頁面元素字體標注的大小是 32px,換成 vw 為 32/(750/100) vw
* 對于需要等比縮放的元素,CSS 使用轉換后的單位
* 對于不需要縮放的元素,比如邊框陰影,使用固定單位 px
* viewport 設置把 layout viewport 寬度設置為設備寬度,不需要縮放
* 用 js 定義 css 的自定義屬性 --width,表示每 vw 對應的像素數
* 根據設計稿標注設置樣式,比如標注稿里元素寬度為 20px。這里設置 calc(20vw / var(--width))
```
// HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>viewport縮放實戰</title>
<meta name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1">
<script>
var WIDTH = 750
document.documentElement.style.setProperty('--width', (WIDTH/100));
</script>
</head>
// CSS
header {
font-size: calc(20vw / var(--width));
}
```
* 優點:可以對需要縮放的元素進行縮放,保留不需縮放的元素
* 缺點:書寫復雜,需要用 calc 計算
### 3、rem 適配方案
為了改良 vw 適配書寫復雜的缺點,出現了 rem 適配。rem 是根元素字體的大小,我們只需要在根元素確定一個 px 字號,則可以來算出元素的寬高。
假設設計稿寬度為 750px,手機端寬度為 320px,上面字體標注為32px,則字體在手機端應該設為 32 \* (320 / 750) px。將 1rem 設為 320/750,則字體大小可直接表示為 32rem。
但是瀏覽器字體大小有限制,不能小于 12px。所需將 html 的 font-size 設為 (移動端設備寬度/設計稿寬度) \* 100。
* 拿到設計稿(假設設計稿尺寸為750px,設計稿的元素標是基于此寬度標注)
* 對設計稿的標注進行轉換
* 對于需要等比縮放的元素,CSS 使用轉換后的單位
* 對于不需要縮放的元素,比如邊框陰影,使用固定單位 px
```
// 假設,640px 的設備 1 rem = 100px
// 公式: 1 rem = document.clientWidth / 640 * 100px;
(function(doc, win) {
var docEle = doc.documentElement,
evt = "onorientationchange" in window ? "orientationchange" : "resize",
fn = function() {
var width = docEle.clientWidth;
width = width < 320 ? 320 : width;
width = width > 640 ? 640 : width;
width && (docEle.style.fontSize = 100 * (width / 640) + "px");
};
win.addEventListener(evt, fn, false);
doc.addEventListener("DOMContentLoaded", fn, false);
}(document, window));
// CSS
body {
font-size: .27rem; // 設計稿上寬度為32px
}
```
- 第一章:移動開發入門
- 第一節:概述
- 第二節:基礎概念
- 第一課時:像素
- 第二課時:視口
- 第二章:Flex 布局
- 第一節:概述
- 第二節:容器屬性
- 第一課時:flex-direction 屬性
- 第二課時:flex-wrap 屬性
- 第三課時:flex-flow 屬性
- 第四課時:justify-content 屬性
- 第五課時:align-items 屬性
- 第六課時:align-content 屬性
- 第三節:項目屬性
- 第一課時:order 屬性
- 第二課時:flex-grow 屬性
- 第三課時:flex-shrink 屬性
- 第四課時:flex-basis 屬性
- 第五課時:flex 屬性
- 第六課時:align-self 屬性
- 第四節:Flex 實例
- 第一課時:常見頁面布局
- 第三章:響應式布局
- 第一節:概述
- 第二節:媒體查詢
- 第一課時:概述
- 第二課時:響應式設計
- 第三節:柵格系統
- 第一課時:概述
- 第二課時:案例分析
- 第三課時:Bootstrap 簡介
- 第四節:響應式案例
- 第一課時:三星首頁
- 第四章:移動端適配
- 第五章:移動端事件
- 第一節:概述
- 第二節:touch 事件
- 第三節:觸摸事件對象
- 第四節:其他事件
- 第五節:移動端幻燈片
- 第六章:移動端常見問題
- 第一節:瀏覽器兼容性
- 第二節:移動端動畫
- 第三節:300ms 延遲
- 第四節:文字溢出省略
- 第五節:水平居中和垂直居中
- 第七章:項目案例
- 第一節:美團外賣
- 第一課時:首頁
- 第二課時:訂單頁面
- 第三課時:我的頁面
- 第四課時:詳情頁面
- 第五課時:購物車頁