This post is about the time when I realized how much I hate frontend web development for iOS. If you are not interested in background, just scroll down to the solution.

About 1,5 years ago we were redesigning the chat feature on Career Accelerator and I chose a task to change an input. It should have been a small task: change the submit button and, input size, also on submit input should slide out and than slide in again for another question and we are good to go. After 1 hour of work everything matched the design, and behaved quite well on Android. Then I tested it on iOS… and here is the point when everything went wrong. The input was not possible to control, it was jumping to the top of the screen when the keyboard was open and disappearing to somewhere invisible when the keyboard was closed. Sometimes messages in the chat were also not visible. Chat on iOS was not usable without an Ibuprofen. In my defense, I have to say that it was not much worse than before my changes.

Searching the web for help was not successful. All I could find was unanswered Stack Overflow posts and pseudo solutions that didn’t work. After reading some articles I realized the problem was with the viewport. When one opens the keyboard on Android, the viewport changes size vertically to compensate for the now-visible keyboard. iOS does not change the viewport size when the keyboard opens, meaning the keyboard instead blocks part of the viewport that would otherwise be visible. Therefore, when one tries to fix something at the bottom of the screen, it actually is at the bottom of the screen but this is behind the keyboard and not visible. In summary, position: fixed; does not always work as expected on iOS.

Of course, I couldn’t meet my deadline, because I didn’t expect that stupid input would take so much time. Nonetheless, I still was not ready to give up because at that time I thought that it was crazy that we provide an AI-based tool yet are not able to control an input in the chat. Searching for a solution, I registered on every web platform I could think of that had a similar chat feature. I tried Tinder, Instagram, Telegram, different bots, and support chats on online stores. I connected MacBook to my phone and debugged everything. Amazingly, all chats had the same problem – an input that you couldn’t control and it was super annoying. Have you ever noticed how bad web chats are on iOS? For me it was a big realization that no one had yet been able to fix an input at the bottom!

In the end I found one application that was almost perfect. It was a Russian social network, VKontakte.They were using some framework and there were so many event listeners and JavaScript manipulations on every move that it was not possible to track how they did the magic. Attempts to find their developer and ask for a solution failed.

By then I had already spent 1,5 desperate weeks trying everything I could possibly find to make it work. I finally came to the solution with one trick, that makes everything look not so bad.

Here is a example code of the solution :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
      .container {
        display: flex;
        flex-direction: column;
        height: 100%;
        width: 100%;
        }
      .messages-container {
        /*reserve 50px for input*/
        height: calc(100% - 50px);
        display: flex;
        flex-direction: column;
        width: 100%;
        overflow-x: hidden;
        overflow-y: auto;
        flex-flow: column nowrap;
      }
      .fixed-container {
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        height: 50px;
        position: fixed;
        bottom: 0;
        right: 0;
        width: 100%;
        margin-top: 0;
        z-index: 100;
      }
      .relative-container {
        position: relative;
        opacity: 1;
      }
      form {
        background-color: white;
      }
      input {
        background-color: white;
      }
    </style>
  
  </head>
<body>
  <div class="container">
    <div class="messages-container">
        Here we display all messages from users and from the bot
    </div>
    <div class="fixed-container">
        <div class="relative-container">
            <form action="">
                <input type="text"/>
            </form>
        </div>
    </div>
  </div>
</body>
</html>
  • Make main flex container to put everything inside (.container)
  • Make two containers on the page. First one will contain messages (.messages-container), and the second one will be reserved for the input itself (.fixed-container).
  • Inside the .fixed-container put .relative-container. This makes it easier to control the items inside.
  • Create a form with the input inside.

The code above fixes input’s jumping and disappearing, but, the input still doesn’t look fixed bottom and is not really stable. Here is where the trick comes in. We need a bit of the JavaScript to first detect that user uses iOS and second to listen to focus and focusout events.

      const getMobileOperatingSystem = () => {
        const userAgent = navigator.userAgent || navigator.vendor || window.opera;
        // Windows Phone must come first because its UA also contains "Android"
        if (/windows phone/i.test(userAgent)) {
            return 'windows';
        } else if (/android/i.test(userAgent)) {
            return 'android';
        } else if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
            return 'ios';
        } else {
            return 'unknown';
        }
    };
      document.addEventListener('DOMContentLoaded', () => {
        'use strict';
        const input = document.querySelector('input');
        const inputColor = 'white';
        const backgroundColor = 'black';
    
        if (input) {
          if (getMobileOperatingSystem() === 'ios') {
          input.addEventListener('focus', () => {
            document.body.style.backgroundColor = inputColor;
          }, false);
    
          input.addEventListener('focusout', () => {
             document.body.style.backgroundColor = backgroundColor;
         }, false);
       }
      }
    });

We need to change background of the body in a way, that if it resizes too much, and the input goes too far up, the input doesn’t look strange and everything still appears to be one input without empty space underneath even though it’s not.

So here you go! If you want to have a beautiful chat that behaves as you expect on all systems, it is still better to make a native application. But, if you still want to have it on the web, this trick is very easy to do and looks and behaves nice in 90% of cases.

Here is the chat itself if you want to try it out.