简体   繁体   English

Mobile safari - 在屏幕键盘上隐藏一些元素

[英]Mobile safari - on screen keyboard hiding some elements

I'm building a very simple POC for an HTML chat app, using flexbox.我正在使用 flexbox 为 HTML 聊天应用程序构建一个非常简单的 POC。 The idea is to have chat messages which start at the bottom of the message window.这个想法是让聊天消息从消息窗口的底部开始。 Typical stuff.典型的东西。

I did this by using a nested flexbox with an inner div set to flex-direction: column and an outer div set to flex-direction: column-reverse and overflow-y: auto:我通过使用一个嵌套的 flexbox 来做到这一点,其中一个内部 div 设置为 flex-direction: column 和一个外部 div 设置为 flex-direction: column-reverse 和 overflow-y: auto:

<div class="outer">
    <div id="messages" class="inner">
        <div class="message">hello</div>
    </div>
</div>
.outer {
    flex-grow: 1;
    display: flex;
    flex-direction: column-reverse;
    overflow-y: auto;
}

.inner {
    display: flex;
    flex-direction: column;
}

It works well for desktop browsers:它适用于桌面浏览器:

桌面

It also works fine on iOS safari up to a certain number of messages.它在 iOS Safari 上也可以正常工作,最多可以收到一定数量的消息。 However at some point the new messages get hidden behind the onscreen keyboard and the only way to see them is either to manually scroll down or close the on screen keyboard.但是在某些时候,新消息会隐藏在屏幕键盘后面,查看它们的唯一方法是手动向下滚动或关闭屏幕键盘。 Note: opening the keyboard again will no longer hide the messages, closing the keyboard seems to reset the scroll.注意:再次打开键盘将不再隐藏消息,关闭键盘似乎重置滚动。

Opening Safari dev tools reveals something interesting.打开 Safari 开发工具会发现一些有趣的东西。 When selecting an html element Safari thinks it is where it should be, in fact the preceding element is shown: When selecting an html element Safari thinks it is where it should be, in fact the preceding element is shown:

移动的

Notice how I selected the last element "Two" but dev tools highlights message "One"请注意我如何选择最后一个元素“二”,但开发工具突出显示消息“一”

Something else I noticed.我注意到了别的东西。 Changing the outer div's overflow-y to hidden solves the problem, but obviously I can no longer scroll through the messages.将外部 div 的溢出-y 更改为隐藏可以解决问题,但显然我不能再滚动浏览消息。

I'm guessing the issue is related to having two sets of scroll bars, one for the div and one for the page itself which is shifted by the keyboard.我猜这个问题与有两组滚动条有关,一组用于 div,另一组用于由键盘移动的页面本身。

Does anyone know why this is happening and how to prevent it?有谁知道为什么会发生这种情况以及如何防止它?

I've created a fiddle and also hosted the page on S3我创建了一个小提琴并在S3上托管了页面

On my phone, adding around 12/13 messages is enough for them to start "hiding" behind the keyboard.在我的手机上,添加大约 12/13 条消息足以让他们开始“隐藏”在键盘后面。

This iOS behavior may be desired since it prevents sudden jumps when opening the keyboard, but if you want to override that, try adding to your code:可能需要这种 iOS 行为,因为它可以防止打开键盘时突然跳转,但如果您想覆盖它,请尝试添加到您的代码中:

const outer = document.querySelector(".outer")

const scrollToBottom = () => {
  outer.scrollTop = 0
}

input.addEventListener("focus", scrollToBottom)

 const messages = document.getElementById("messages"); const input = document.getElementById("messageInput"); const target = document.getElementById("send"); const template = document.getElementById("messageTemplate"); const pushMessage = () => { const clone = template.content.cloneNode(true); clone.querySelector("div.message").innerText = input.value; messages.appendChild(clone); } const keyUpHandler = (e) => { if (e.key === 'Enter') pushMessage() } target.addEventListener("click", pushMessage) input.addEventListener("keyup", keyUpHandler) const outer = document.querySelector('.outer'); const scrollToBottom = () => { outer.scrollTop = 0; } input.addEventListener("focus", scrollToBottom)
 .page { position: fixed; top: 0; left: 0; width: 100%; display: flex; flex-direction: column; height: 100%; } .header, .footer { padding: 1rem; background-color: lightgrey; display: flex; flex-direction: row; } .outer { flex-grow: 1; display: flex; flex-direction: column-reverse; overflow-y: auto; /*overflow-y: hidden;*/ } .inner { display: flex; flex-direction: column; } .message { padding: 1rem; }
 <div class="page"> <div class="header"> header </div> <div class="outer"> <div id="messages" class="inner"> <div class="message">hello</div> </div> </div> <div class="footer"> <input id="messageInput" type="text" placeholder="Enter your message" /> <button id="send">send</button> </div> </div> <template id="messageTemplate"> <div class="message"></div> </template>

What I usually do is create a div surrounding the entire page.我通常做的是围绕整个页面创建一个 div。 This element get's an height of 100vh and a width of 100vw and a position relative.这个元素的高度为 100vh,宽度为 100vw 以及相对位置。

This way you have one scrollable element which on focus you can scroll to the bottom.这样你就有了一个可滚动的元素,你可以在焦点上滚动到底部。

Also if you for example try to stick (position absolute) something to the bottom of the page it will actually be above the keyboard.此外,例如,如果您尝试将某些东西粘贴(绝对定位)到页面底部,它实际上将位于键盘上方。

I had this exact issue (building a chat UI too) and managed to finally figure out a solution我遇到了这个确切的问题(也构建了聊天 UI)并设法最终找到了解决方案

After playing around in the Safari console, I realised that if I set scrollTop to 0 it would correctly jump me to the bottom of the thread, but if I then sent another message, that message would hide behind the input.在 Safari 控制台中玩耍后,我意识到如果我将scrollTop设置为0 ,它会正确地将我跳到线程的底部,但是如果我随后发送另一条消息,则消息将隐藏在输入后面。

What was interesting though, is that if i set it to a similar value (like -1 ), it would jump me to the bottom again.不过有趣的是,如果我将它设置为类似的值(如-1 ),它会再次将我跳到底部。

With this insight, I tried to combine it, and found a solution that works!有了这种见解,我尝试将其结合起来,并找到了一个可行的解决方案!

This is what I ended up with:这就是我最终的结果:

 scrollNewMessage() {
  const scrollTop = this.$refs["message-thread-wrapper"].scrollTop

  // iOS Safari refuses to update scrollTop if the given value is the same as its
  // current value. That would be fine, except that the current value is _incorrect_
  // when the keyboard is open
  // This was resulting in messages hiding behind the message compose box
  // Ensuring the value is always different fixes it
  this.$refs["message-thread-wrapper"].scrollTop = scrollTop === 0 ? -1 : 0
},

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM