Search code examples
jquerysafarikeyboardresizeviewport

resize window safari with jquery when keyboard shows


First of all, i know that there are many questions asked about this topic. I have been searching for a couple weeks right now but i cant find an answer that works for me.

I have a website with an input field at the bottom. The site has a very simple design.

  • Header
  • Content (dynamic height)
  • Footer with input field

The problem is simple yet annoying. When the user clicks/ taps on the input field in a pc webbrowser everything works fine. When the input field is tapped in a mobile webbrowser, all except safari, will decrease the height of the content div.

When you tap it in safari, because the input field is a the bottom, the whole page will scroll up, where the user loses a part of the header and content (overflow).

How can i solve this? Can i instruct safari to recalculate the layout when the keyboard is opend? I have tried so many things like fixed layout (pain for me), fire event when input field is triggerd, resize the height of the content div (but there are different keyboards on different devices), resize the height of the document, body and container div (where all else is inside).

Image that shows the problem exactly [source] Also on that source there are a couple workarounds, tricks. But i cant get them work for me. I want to achieve that footer and header stay fixed, and content decreases size. Even if i do change the height via jquery/css of the content div, there will be an empty space below the footer when the keyboard shows.

I read a lot of posts, code, articles like medium, old stack overflow posts and jquery code on different websites, but i cant get it right.

Is there a simple yet effective way around this? If possible without any code which makes things unnecessarily complicated. My best guess is that i can instruct safari to recalculate the viewport height and let css do its thing when the keyboard appears?

If code example is needed, i'm glad to giva ya.

Thanks in advance.

Things i tried:

  • reading articles
  • googling for like weeks
  • test many jquery, css and plugins form different sources
  • build a small example to find the source of the problem
  • test in different browser across different devices and os/s

Solution

  • Ok after lots of thinking I found a viable solution so i post here instead other people want to use it.

    First of all: If you want to disable the scrolling when an input field gets focus and the keyboard comes up:

    input[type=text]:focus {
      animation: DisableScrollingWhenKeyboard 0.01s;
    }
    
    @keyframes DisableScrollingWhenKeyboard {
      0% { opacity: 0; }
      100% { opacity: 1; }
    }
    

    Does NOT work together with the code below because innerheight never changes.

    What it does is simple, it changes the opacity so safari doesnt see an input box when it checks for it; therefor safari doesnt scroll the page. But now things can get behind the keyboard. So this wasn't suitable for me. Found this code here. To important not to mention.

    What I do now is actually written here, but with a few changes.

    First of all, check if it is safari (i know there are better alternatives for this one but for now i'm happy with it)

    var is_safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
    

    When you do have that piece of ... browser detected

    1. Get the original Height of the inner Window
    2. Get the Height of the body
    3. Check again when the keyboard is all the way up (takes around 200ms) and see if there is a difference. When there is a difference:
    4. Get the difference. The difference is the height of the keyboard that is now up. e.g: the height was 1000px, with keyboard up the new height of the screen is 700px. The height of the keyboard is 300px.
    5. Set the body to the new height (originalHeight - newHeight)
    6. Scroll the page back up

    Yes it gives a bit of a flash and blinky situation when the keyboard comes up, but i'm happy with it. It works on different screens and keyboard because the height is calculated.

    function resizeHandler() {       
      var OriginalviewportHeight = window.innerHeight
      var OriginalBodyHeight =  $('body').height();       
      setTimeout(function() {
        if (OriginalviewportHeight != window.innerHeight) {
          KeyboardHeight = OriginalviewportHeight - window.innerHeight;             
          $('body').css("height", + (OriginalBodyHeight - KeyboardHeight) +"px");
          $(window).scrollTop(0);
        }            
      },200); 
    }
    

    All of this is done when the inputfield gets focus (and the check in difference of screenheight doesn't let it fire on computerscreens or with physical keyboards in safari).

    $("#userInputField").focus(function() {
      if (is_safari){
        resizeHandler();
      }            
    });
    

    When we lose focus again, reset the body height again:

    $("#userInputField").on("focusout", function() {
      if (is_safari) {
        $('body').css("height", "100%");
      }    
    });
    

    I know this isnt the most perfect solution, but for now it works around the problem of scrolling when an input field gets focus, and only in safari mobile/tablet. So the smooth UX for chrome, android, firefox, etc isnt ruined.

    Any ideas to improve, please share. I hope this can help somebody or point in the right direction.