JavaScript不直接适配屏幕,而是通过检测(如clientWidth、visualViewport)、响应(resize/orientationchange事件)和补位(动态改class、canvas像素比)实现;需节流监听、区分CSS/物理像素、配合viewport与dpr处理高清屏。
移动端 JavaScript 本身不直接“适配屏幕尺寸”,真正起作用的是 CSS 媒体查询、视口设置和 DOM 操作逻辑;JavaScript 的角色是检测、响应、补位——比如监听 window.resize、读取 window.innerWidth、动态修改 class 或调整 canvas 像素比。
window.innerWidth 可能不准在 iOS Safari 和部分安卓浏览器中,window.innerWidth 返回的是 CSS 像素宽度(即 viewport 宽度),不是物理像素,也不包含地址栏临时遮挡导致的缩放抖动。更可靠的方式是结合 document.documentElement.clientWidth 和 visualViewport?.width(新 API,兼容性需查)。
window.innerWidth 可能短暂跳变,导致布局闪动orientationchange
visualViewport.width 能获取当前可视区域真实 CSS 宽度(含缩放),但 Chrome 61+、Safari 15.4+ 才支持别只依赖 resize 事件——它在移动端触发频繁且不可靠(尤其快速旋转时)。应组合使用 resize + orientationchange + visualViewport?.addEventListener('resize', ...),并加节流。
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
const width = Math.min(document.documentElement.clientWidth, window.innerWidth);
if (width < 480) {
document.body.classList.add('mobile');
} else {
document.body.classList.remove('mobile');
}
}, 150);
});
// 补充监听 orientationchange(iOS 旧版必需)
window.addEventListener('orientationchange', () => {
setTimeout(() => {
// 强制重读,避免 orientationchange 后 clientWidth 还没更新
document.documentElement.style.fontSize = '1px';
document.documentElement.offsetHeight; // 强制重排
}, 0);
});
如果业务需要禁止双指缩放但允许 JS 动态控制 zoom(如地图、PDF 查看器),不能只靠 锁死,而要用 visualViewport.scale + transform 模拟。
是基础,但会禁用所有缩放,包括 JS 触发的user-scalable=yes,再用 JS 拦截 touchstart/touchmove 控制 visualViewport.scale
visualViewport.scale 是只读属性,只能通过 visualViewport.addEventListener('resize', ...) 监听变化,不能直接设值;实际缩放需靠 element.style.transform = 'scale(1.5)' + transform-origin 配合很多开发者只做 canvas 的 devicePixelRatio 缩放,却忽略 SVG、CSS 单位、字体渲染等场景。
canvas.width/canvas.height(物理
像素)和 canvas.style.width/canvas.style.height(CSS 像素),不会自动响应 dpr;应改用内联 SVG 或用 srcset 提供 2x 版本16px,可基于 window.devicePixelRatio > 1.5 微调行高或字重设备像素比不是越高越好——有些低端安卓机上报 devicePixelRatio=3 但 GPU 性能跟不上,强行提升 canvas 分辨率反而卡顿。