如何防止iOS键盘使用CSS或JS将视图推离屏幕

时间:2016-07-27 17:38:34

标签: javascript css responsive

我有一个响应式网页,当您点按一个按钮时会打开一个模态。当模态打开时,它被设置为使用固定定位占据页面的整个宽度和高度。模态中还有一个输入字段。

在iOS设备上,当输入字段被聚焦时,键盘会打开。但是,当它打开时,它实际上将整个文档推出,使得我的页面的一半超出视口的顶部。我可以确认实际的html标签本身已被推高以补偿键盘并且它没有通过CSS或JavaScript发生。

有没有人见过这个,如果有的话,有没有办法防止它,或者在键盘打开后重新定位?这是一个问题,因为我需要用户能够在模式的顶部看到内容,同时,我想要自动对焦输入字段。

6 个答案:

答案 0 :(得分:13)

  

首先

<script type="text/javascript">
 $(document).ready(function() {
     document.ontouchmove = function(e){
          e.preventDefault();
          }
 });

  

然后这个

input.onfocus = function () {
    window.scrollTo(0, 0);
    document.body.scrollTop = 0;
}

答案 1 :(得分:0)

在某些情况下,可以通过重新定位输入元素来缓解此问题。

input.onfocus = function () {
  this.blur();
  this.focus();
}

答案 2 :(得分:0)

对于在React中绊脚石的任何人,我都设法通过@ankurJos解决方案来解决它,如下所示:

const inputElement = useRef(null);

useEffect(() => {
  inputElement.current.onfocus = () => {
    window.scrollTo(0, 0);
    document.body.scrollTop = 0;
  };
});

<input ref={inputElement} />

答案 3 :(得分:0)

如果您不想滚动到顶部(0,0)

,也可以执行此操作
window.scrollBy(0, 0)

答案 4 :(得分:0)

我为此苦了一段时间,找不到适合我的东西。

我最终做了一些JavaScript黑客工作,以使其正常工作。

我发现,如果输入元素位于屏幕的上半部分,Safari不会推送视口。那是我的小技巧:

我在输入对象上拦截焦点事件,而是将焦点重定向到不可见的对象(通过transform: translateX(-9999px))。然后,一旦键盘出现在屏幕上(通常为200毫秒左右),我就会在屏幕上显示动画的原始元素上触发焦点事件。

这是一种复杂的交互,但效果很好。

function ensureOffScreenInput() {
  let elem = document.querySelector("#__fake_input");
  if (!elem) {
    elem = document.createElement("input");
    elem.style.position = "fixed";
    elem.style.top = "0px";
    elem.style.opacity = "0.1";
    elem.style.width = "10px";
    elem.style.height = "10px";
    elem.style.transform = "translateX(-1000px)";
    elem.type = "text";
    elem.id = "__fake_input";
    document.body.appendChild(elem);
  }
  return elem;
}

var node = document.querySelector('#real-input')
var fakeInput = ensureOffScreenInput();

function handleFocus(event) {
  fakeInput.focus();

  let last = event.target.getBoundingClientRect().top;

  setTimeout(() => {
    function detectMovement() {
      const now = event.target.getBoundingClientRect().top;
      const dist = Math.abs(last - now);

      // Once any animations have stabilized, do your thing
      if (dist > 0.01) {
        requestAnimationFrame(detectMovement);
        last = now;
      } else {
        event.target.focus();
        event.target.addEventListener("focus", handleFocus, { once: true });
      }
    }
    requestAnimationFrame(detectMovement);
  }, 50);
}

node.addEventListener("focus", handleFocus, { once: true });

我个人在Svelte动作中使用此代码,并且在我的Apple Maps的Svelte PWA克隆中确实很好用。

Video of it working in a PWA clone of Apple Maps

您会在视频中注意到,视口上半部分的输入动画稳定后,自动完成功能会发生变化。那是焦点切换发生了。

此黑客的唯一缺点是,原始实现上的焦点处理程序将运行两次,但是有一些方法可以用元数据来解决这个问题。

答案 5 :(得分:-2)

对于在页面加载后发生的input.focus(),IOS8和Safari bowsers的行为相同。它们都缩放到元素并调出键盘。(不太确定这是否会有所帮助,但是你尝试过使用这样的东西吗?)

HTML IS

<input autofocus>

JS

for (var i = 0; i < 5; i++) {
document.write("<br><button onclick='alert(this.innerHTML)'>" + i + "</button>");
}

//document.querySelector('input').focus();

CSS

button {
width: 300px;
height: 40px;
}
  

此外,您必须使用用户代理解决方法,您可以将其用于所有IOS版本

if (!/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
element.focus();
}