Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

213
Visualizações
Mobile safari - on screen keyboard hiding some elements

I'm building a very simple POC for an HTML chat app, using flexbox. 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:

<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:

Desktop

It also works fine on iOS safari up to a certain number of messages. 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. When selecting an html element Safari thinks it is where it should be, in fact the preceding element is shown:

Mobile

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.

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.

Does anyone know why this is happening and how to prevent it?

I've created a fiddle and also hosted the page on S3

On my phone, adding around 12/13 messages is enough for them to start "hiding" behind the keyboard.

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

I had this exact issue (building a chat UI too) and managed to finally figure out a solution

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.

What was interesting though, is that if i set it to a similar value (like -1), it would jump me to the bottom again.

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
},
about 4 years ago · Juan Pablo Isaza Relatório

0

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:

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>

about 4 years ago · Juan Pablo Isaza Relatório

0

What I usually do is create a div surrounding the entire page. This element get's an height of 100vh and a width of 100vw and a position relative.

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.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda