移动端开发
01 基本概念
1.1 分辨率相关
- 屏幕分辨率:屏幕的物理像素点数,如
1200x2670
(不可修改) - 显示分辨率:可通过操作系统调节屏幕的显示分辨率
- 屏幕密度
PPI
:单位英寸的像素数,计算对角线上的像素数量
1.2 像素相关
- 物理像素:对应屏幕分辨(不可修改)
- 设备独立像素:由屏幕厂商指定当前屏幕的设备独立像素数,用于解决高清屏上显示过小的问题;chrome 浏览器中显示的即为设备独立像素(无法修改)
- CSS 像素:也叫逻辑像素,可以理解为程序员像素,也就是开发中代码里面的 px 单位
设备像素比
DPR
: 物理像素/设备独立像素window.devicePixelRatio
💬 举个例子:
假设有一款手机的屏幕分辨率为 1920x1080
,设备像素比为 2。这意味着:
- 物理像素: 屏幕上实际有 1920 个水平像素点和 1080 个垂直像素点。
- 逻辑像素: 在 CSS 中,我们只需要写 1920/2 = 960px 宽和 1080/2 = 540px 高,就可以让元素铺满屏幕
- 该手机的物理像素值为 1920x1080;设备独立像素值为 960x540
🎯 注意:
- 编写样式时的 CSS 像素首先被设备独立像素接管
- 普通屏幕:一个设备独立像素对应一个物理像素
- 高清屏幕:一个设备独立像素对应多个物理像素(假如 DPR 为 2,则一个设备独立像素对应两个物理像素,当代码中写到 1px 的边框时,会点亮 2px 的物理像素)
- 在无缩放的情况下:1 CSS 像素 = 1 设备独立像素 (在无缩放的情况下,代码中书写的逻辑像素对应的就是设备独立像素)
1.3 视口相关
- 布局视口
viewport
:浏览器在渲染网页时所参考的虚拟的窗口,这个窗口的宽度决定了网页上的内容如何在屏幕上显示- 在以前,布局视口通常比移动设备的屏幕尺寸(设备独立像素)大,一般设为 980px,它允许浏览器以一个较大的尺寸来渲染网页,然后通过缩放和滚动等方式让用户看到网页的不同部分
- 后来有了理想视口,移动端适配等概念,一般不再使用 980px 了,而是开启理想视口
- 视觉视口:用户实际看到的网页区域,在不缩放的时候,也就是设备屏幕的宽度(移动端缩放时会导致视觉视口发生变化)
- 理想视口:与屏幕(设备独立像素)等宽的布局视口称为理想视口
通过
meta
标签调整布局视口的宽度为设备独立像素的宽度,用来开启理想视口
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
iPhone 3 | iPhone 4 | |
---|---|---|
分辨率 | 320 * 480 | 640 * 960 |
设备独立像素 | 320 * 480 | 320 * 480 |
02 缩放
2.1 PC 端缩放
影响网页中元素的排列位置
放大:布局视口变小,每个 css 的像素所占面积变大
缩小:布局视口变大,每个 css 的像素所占面积变小
2.2 移动端缩放
不改变网页中元素的排列位置
放大:布局视口不变,视觉视口变小
缩小:布局视口不变,视觉视口变大
布局视口不变,则不会影响页面中元素的排列;视觉视口变小,相当于同一物理宽度的屏幕去看一个更小的页面区域,自然变大了
03 移动端适配
设计师在出移动端项目设计稿时,会按照某个固定屏幕宽度进行设计,但实际上移动端屏幕宽度五花八门,不同屏幕设备的布局视口不一样大,因此需要做适配,适配的原则就是等比
并不是所有的元素都需要等比适配,一般只有与布局相关的尺寸才需要等比,而字体大小,边框宽度等这些其实不需要等比缩放
3.1 viewport 适配
直接在 meta 标签中将 viewport 的宽度设置为设计稿的宽度 <meta name="viewport" content="width=375">
,在写代码时直接按照设计稿的尺寸书写即可。
相当于强制统一所有屏幕的布局视口宽度,无论屏幕的实际宽度为多少
这样存在的问题是会导致所有尺寸值全部被强制适配,比如边框宽度也会被强制拉伸,图片失真等问题
3.2 rem 适配
em 单位:相对于当前元素的父元素的字体大小的单位
rem 单位:相对于根元素(html
元素)的字体大小的单位
下面提到的“设备宽度”指的都是“设备独立像素”宽度
- 方案一
- 将根字体设为
(device-width * 100) / ui-width px
(如果设备宽度等于设计稿宽度,相当于将根字体设为了 100px ) - 编写样式时,直接以 rem 为单位,值为设计稿值/100;假如设计稿盒子宽度 320px,直接在样式中写 3.2rem 即可
- 可以灵活控制哪些适配哪些不适配,适配的写 rem 单位,不适配的写 px 单位
function adapter() { // 获取布局视口宽度,即设备独立像素值 const dpWidth = document.documentElement.clientWidth; // 计算根字体大小 const rootFontSize = (dpWidth * 100) / 375px; // 375 是设计稿宽度 // 设置根字体大小 document.documentElement.style.fontSize = rootFontSize + 'px'; }; adapter(); window.onresize = adapter; // 窗口大小发生变化时触发
- 将根字体设为
- 方案二(推荐)
- 将根字体设为
device-width / 10 px
- 假如设备宽度为 375px,则根字体为 37.5px
- 假如设计稿中一个盒子为 345px,只需要在代码中写 345 / (375 / 10)rem 即可
- 编码时比较麻烦,但是可以通过打包工具中的 px2rem 插件来解决
<script> function adapter() { // 获取布局视口宽度,即设备独立像素值 const dpWidth = document.documentElement.clientWidth; // 计算根字体大小 const rootFontSize = dpWidth / 10; // 设置根字体大小 document.documentElement.style.fontSize = rootFontSize + "px"; } adapter(); window.onresize = adapter; // 窗口大小发生变化时触发 </script> <style> @font: 375/10rem #demo { width: 345 / @font; // 9.2rem height: 150 / @font; margin-top: 15 / @font; } </style>
- 将根字体设为
3.3 vw 适配
vw 是 CSS 中的相对长度单位,表示相对于视口(viewport)宽度的百分比。1vw 等于视口宽度的 1%。
04 1px
的物理像素边框
边框是否参与适配要根据设计师的设计意图来
因为 dpr 为 2,当程序员写下 1px 的 border 时,实际会显示为 2px
有时候希望能够实现 1px 的物理像素边框,就需要根据 dpr 来调整实际的书写的 css 像素
假如 dpr 为 2,要实现 1px 的物理像素边框,就需要在代码中写 0.5px 的边框
不过为了规避边框的问题,目前大家习惯不加边框,或者通过 div 之间的间隔来模拟边框
05 移动端事件
- touchstart
- touchmove
- touchend
- touchcancel
06 touch 与 click
touch 事件结束后会默认触发元素的 click 事件,如果没有设置理想视口,则事件触发的时间间隔在 300ms 左右,开启理想视口后,时间间隔在 50ms 左右。
因为早期为了实现网页中双击屏幕缩放,所以添加 300ms 的间隔,用于检测是否有第二次点击;开启理想视口后,不再需要双击缩放,直接双指滑动放大缩小即可
事件的顺序
touchstart -> mouseover -> mousemove(一次) ->mousedown -> mouseup -> click ->touchend
07 点击穿透问题
出现的条件:
- 绑定了移动端的 touch 事件
- 在事件的回调中引起了发生事件的元素的消失
- 元素消失后其下方还有别的元素可以响应 click 事件
解决方案:
- 阻止默认事件
event.preventDafault()
- 触发完 touch 事件后会默认触发 click 事件,直接阻止这个默认行为即可
- 最正统的解决方案,剩下的都是噱头
- 使背后的元素不响应 click 事件,使用 touch 事件代替
- 使背后的元素暂时失去 click 事件,300ms 后再恢复
pointer-events: none
- 让隐藏的元素延迟 300ms 再隐藏
其他适配方案
postcss-pxtorem 插件
https://www.npmjs.com/package/postcss-pxtorem
该插件属于 PostCSS,是一个用于处理 CSS 的工具,之后可以在 postcss.config.js
配置文件中进行插件配置
该插件用于将书写在样式文件中的 px
单位转换为 rem
单位
px
单位需为小写,大写的无法转换;行内样式无法转换