由于移动端的特殊性,屏幕的尺寸碎片化严重,要想很好的适配不同的尺寸的设备,需要我们前端开发相比 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 延迟
- 第四节:文字溢出省略
- 第五节:水平居中和垂直居中
- 第七章:项目案例
- 第一节:美团外卖
- 第一课时:首页
- 第二课时:订单页面
- 第三课时:我的页面
- 第四课时:详情页面
- 第五课时:购物车页