iPhone打开键盘时fixed元素getBoundingClientRect的y值为负的原因
iPhone上fixed元素getBoundingClientRect()返回负y值的原因解析
在iPhone设备上,对设置了position: fixed; top: 0、本应始终处于布局视口顶部的元素调用getBoundingClientRect()时,返回的y值会变成负数;但相同场景下安卓设备无此现象。
复现代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width,initial-scale=1"> <style> #position-fixed-el { position: fixed; top: 0; left: 10px; right: 10px; background-color: orange; height: 10px; } [contenteditable]{ height: 100px; border: 1px solid black; margin-top: 80vh; } </style> </head> <body> <div id="position-fixed-el"></div> <div contenteditable="true"></div> <script> const positionFixedEl = document.getElementById("position-fixed-el") visualViewport.addEventListener("resize", () => { console.log(positionFixedEl.getBoundingClientRect().y) }) </script> </body> </html>
原因解析
首先要纠正认知偏差:MDN明确getBoundingClientRect()返回的坐标是相对于视觉视口(visual viewport),而非布局视口(layout viewport)。
在iOS Safari中,当点击页面底部的可编辑区域时,浏览器会自动调整视觉视口:将视觉视口向上偏移,让输入区域对齐到键盘上方,方便用户输入。此时视觉视口的顶部原点(y=0的位置)已经向上移动到布局视口的某个位置,而fixed元素是相对于布局视口固定在顶部的,这就导致fixed元素出现在视觉视口的上方区域,所以getBoundingClientRect().y会返回负数。
安卓设备的浏览器在处理输入场景时,不会对视觉视口做这种偏移调整,视觉视口的原点始终和布局视口顶部对齐,因此fixed元素的y值始终为0。
另外,你监听的visualViewport.resize事件正是在视觉视口尺寸/位置变化时触发,此时获取的坐标自然是基于调整后的视觉视口计算的结果。
内容的提问来源于stack exchange,提问作者justaskin
相关产品推荐
相关产品推荐

