移动端适配基本概念
视口 viewport
一个虚拟的区域, 就是设备上用来显示网页的那一块区域
- 浏览器承载 viewport , viewport 承载网页,
viewport 默认会对网页进行缩放来呈现完整内容
- 可能造成元素太小看不清
布局适口
用来布局的区域
有自己的默认值,可以通过 width=device-width 或 initial-scale 来重新设置
当发生冲突时,取较大的值
- PC 端
- 布局视口默认和视觉视口等大
- 进行网页放大时,布局视口变小;缩小时,布局视口变大(缩放时的是每个像素点的大小)
- 移动端
- 各个设备有自己固定的布局适口大小 (iphone 为 980px)
- 进行缩放时,布局适口不会变化(物理像素值不会变化)
视觉适口
用户能看到的区域
默认情况下是等于设备宽的,只有设置了 initial-scale 才会改变大小
当布局视口的内容超出视觉视口时,才会出现滚动条
- PC 端
- 用户可任意缩放
- 移动端
- 通过 initial-scale 来设置缩放(相对于设备宽)
适配方案要求
网页宽度必须和浏览器保持一致 (防止出现水平滚动条)
默认显示的缩放比例和 PC 端保持一致
不允许用户自行缩放网页
1 | <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0,user-scalable=no"> |
理想适口
让 layout viewport (布局视口)的宽度等于设备宽度
1 | <meta name="viewport" content="width=device-width" /> |
完美视口
同时不让系统对网页进行缩放
默认视觉视口宽度就是等于设备宽度的
设置 initial-scale 是同时在设置布局视口和视觉视口的宽度
当元素超出视觉视口宽度时,就会出现滚动条
1 | <meta name="viewport" content="width=device-width,initial-scale=1.0" /> |
物理像素(屏幕的分辨率)
设备能控制显示的最小单元,可以把物理像素看成是对应的像素点
物理像素是一个抽象单位,我们不能说 1 个物理像素有多大,这还跟设备分辨率有关
- eg 屏幕的分辨率 (1366 x 768 ect.) 可以理解为物理像素
设备分辨率 PPI
设备的分辨率指的是每英寸显示屏上像素点个数
计算公式为 PPI = 物理像素/物理尺寸
1 | // iPhone6 的分辨率为 |
设备独立像素 & css像素
设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用并控制的虚拟像素
- 我们写 CSS 时所用的像素,它是一个抽像的单位
- css 像素是浏览器特有的概念
设备像素比 dpr
设备像素比 = 物理像素 / css 像素
- 在普通屏幕下1个 CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素
dpr & DPI & PPI
dpr —— 设备像素比,物理像素/设备独立像素 = dpr, 一般以 Iphon6 的 dpr 为准 dpr = 2
PPI —— 一英寸显示屏上的像素点个数 (iPhone6 为 326 = √(750^2 + 1334^2) / 4.7)
DPI —— 最早指的是打印机在单位面积上打印的墨点数,墨点越多越清晰
位图像素
1 个位图像素是一个栅格图像上最小的数据单元
移动端适配方案
所谓的移动端适配,就是让页面在不同尺寸的移动设备上展现出理想的视觉效果
参考
viewport 适配
原理
视口默认会对网页内容进行缩放来呈现内容,利用 initial-scale 来设置布局视口和视觉视口的大小后,网页内容再进行缩放;同一个元素在不同设备上的 css 像素是一样的,但是缩放比是不一样的
- 根据设计稿标准(750px 宽度)开发页面,写完后页面及元素自动缩放,适配不同的设备
- 在 initial-scale 上做文章,initial-scale = 设备的宽度 / 设计稿的宽度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<head>
<meta name="viewport" content="initial-scale=1.0">
<script>
// 设计稿尺寸
const WIDTH = 750
const mobileAdapter = () => {
// 为了适配其他屏幕,需要动态的设置 initial-scale 的值
let scale = screen.width / WIDTH
let content = `initial-scale=${scale}, maximum-scale=${scale}, minimum-scale=${scale}`
let 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>
</head>
优点
- 元素尺寸直接按设计稿来
缺点
- 边线问题,不同尺寸下,边线的粗细是不一样的(等比缩放后),全部元素都是等比缩放,实际显示效果可能不太好
vw/wh(部分等比缩放)
原理
浏览器默认将设备宽度分为 100 份,对于不同的设备,每一份的宽度是不一样的,以 vw 为单位的同一个元素在不同设备上的 css 像素也是不一样的
- 开发者拿到设计稿(假设设计稿尺寸为750px,设计稿的元素标注是基于此宽度标注)
- 开始开发,对设计稿的标注进行转换,把 px 换成 vw
- 比如页面元素字体标注的大小是 28px,换成 vw 为 (100/750)*28 vw
- 对于需要等比缩放的元素,CSS 使用转换后的单位 vw
- 对于不需要缩放的元素,比如边框阴影,使用固定单位 px
为了开发方便,利用自定义属性,CSS变量
1 | <head> |
注意此时,meta 里就不要去设置缩放了
业务代码里就可以写
1 | p { |
实现了按需缩放
rem
原理
根据设备宽度给不同的设备设置不同的 rem(根元素字体大小),以 rem 为单位的同一个元素在不同设备上的 css 像素是不一样的
- 开发者拿到设计稿(假设设计稿尺寸为750px,设计稿的元素标是基于此宽度标注)
- 开始开发,对设计稿的标注进行转换
- 对于需要等比缩放的元素,CSS 使用转换后的单位 rem
- 对于不需要缩放的元素,比如边框阴影,使用固定单位 px
根据不同屏幕宽度,设置 html 的 font-size 值
1 | <head> |
对于需要等比缩放的元素,CSS 使用转换后的单位 rem
1 | header { |
对于不需要缩放的元素,比如边框阴影,使用固定单位px
1 | header > span.active { |
⚠️ 以上的三种适配方案,都是等比缩放
- 放到 ipad 上时(设计稿以手机屏幕设计的),页面元素会很大很丑
- 有些场景下,并不需要页面整体缩放(viewport 自动处理的也很好了),所以有时只需要合理的布局即可
rem & less 适配方案
1 | // variables.less |
1 | // mixins.less |
1 | // adapter.less |
1 | // index.less |
弹性盒布局(合理布局)
1 | <meta name="viewport" content="width=device-width,initial-scale=1.0"> |
使用 flex 布局
1 | section { |
对于多列的布局情形非常适合
百分比布局(宽度适配)
只做到了宽度适配
响应式布局(媒体查询)
核心还是利用 媒体查询
- 如果是大项目,自己写响应式代码不现实,尽量利用 Bootstrap
总结
对于更复杂的场景,需要更灵活考虑,没有一种适配方式可以囊括所有场景
1px 细线边框
方式一—— rem + initial-scale
- 所有元素先放大 dpr 倍,再缩放 1/dpr
1 | ... |
1 | .box { |
方式二 —— 伪元素 + transform
1 | .border-1px-bot, |
1 | <div class="border-1px-right"></div> |