window.innerwidth 和 window.innerheight 返回当前视口的宽高(css 像素),含滚动条占用空间、响应缩放,不包含工具栏/地址栏;需监听 resize 事件并节流更新,不支持 ie8 及更早版本。

直接读取 window.innerWidth 和 window.innerHeight 就行,但要注意它们返回的是 CSS 像素,不是设备物理像素
这两个属性在绝大多数现代浏览器中都可用,返回当前视口(即用户可见区域)的宽高,单位是 CSS 像素。比如在桌面浏览器缩放为 125% 时,window.innerWidth 会比实际屏幕宽度小,因为它反映的是“渲染后可见多少个 CSS 像素”,而不是设备像素数。
常见错误现象:
– 在 iOS Safari 横屏旋转后首次读取,值没更新(需监听 resize)
– 误以为它包含滚动条宽度(实际上已扣除垂直滚动条宽度)
– 在 iframe 中调用却忘了上下文:它始终返回**调用者所在窗口**的视口尺寸,不是父页面的
- 不要在页面加载前就取值(如 script 标签放在
且没加defer),DOM 可能未就绪,但window对象已存在,所以通常安全;不过若依赖布局(比如配合getBoundingClientRect),建议等DOMContentLoaded - 移动端注意:Safari 地址栏收起/展开会触发
resize,innerHeight会变化,不能假设它固定 - 不支持 IE8 及更早版本;IE9+ 支持,但 IE9 在怪异模式下可能返回
document.body.clientWidth类似行为,建议强制标准模式
监听视口变化必须用 resize 事件,但别直接绑 window.onresize
resize 触发非常频繁(尤其拖拽窗口时),直接执行重绘逻辑容易卡顿。原生 window.onresize = handler 会被覆盖,也不利于解绑。
- 用
window.addEventListener('resize', handler),便于多次绑定和单独移除 - 务必节流(throttle):哪怕只是简单更新一个
const viewport = { w: window.innerWidth, h: window.innerHeight },也建议用setTimeout或requestAnimationFrame包一层,避免每毫秒都计算 - 在单页应用(SPA)中,路由切换可能不触发
resize,但视口实际没变——这时候不需要重新获取,别为了“保险”而重复读取
innerWidth/Height 和 document.documentElement.clientWidth/clientHeight 的区别在哪
二者常被混淆,关键差异在于是否包含滚动条、是否受 zoom 影响:
-
window.innerWidth/Height:含垂直/水平滚动条占用空间(即已减去滚动条宽度),响应 CSSzoom(但现代 Chrome/Firefox 已弃用zoom,改用transform: scale(),此时它不变) -
document.documentElement.clientWidth/clientHeight:只读取根元素()的内联尺寸,不含滚动条,也不响应zoom;但在某些安卓 WebView 中可能更稳定 - 如果页面有横向滚动(
overflow-x: auto),innerWidth仍等于视口宽度,而clientWidth可能略小(因内容撑开导致滚动条出现)
实际建议:优先用 innerWidth/Height,语义最准确;仅当需要排除滚动条影响做精确定位(如 tooltip 贴边)时,才对比使用 clientWidth。
服务端无法获取 innerWidth,别在 SSR 中硬读
Node.js 环境没有 window,innerWidth 是纯客户端 API。常见错误是在 Next.js / Nuxt 等框架的 getServerSideProps 或 setup() 中直接访问,会报 ReferenceError: window is not defined。
- 判断环境:
typeof window !== 'undefined'是最轻量的守卫,放在读取前即可 - 不要试图“预估”视口尺寸(比如靠 User-Agent 解析设备型号),误差极大;留到客户端首次渲染时再取
- 如果要做响应式降级(如服务端根据 UA 注入 class),只能依赖 HTTP header(如
Sec-CH-UA-Mobile)或客户端 JS 回传,不能靠innerWidth
真正容易被忽略的是:这些值在 Web Components 或 Shadow DOM 内部依然有效,但如果你在 slot 内容里动态计算位置,得确认 offsetParent 是否被 shadow boundary 阻断——innerWidth 本身不受影响,但它的用途可能失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











