20

In a web page I have an input field and a div that is fixed to the bottom of the window (with these CSS properties: position:fixed; and bottom:0;

I made a Codepen to show what I'm talking about: https://codepen.io/anon/pen/xpQWbb/

Chrome on Android keeps the div visible even when the soft keyboard is open:

enter image description here

However, Safari on iOS seems to draw the soft keyboard over the fixed element:

enter image description here

(I should mention I'm testing on the iOS simulator on my Macbook, because I don't have a working iPhone)

Is there a way to make iOS Safari keep the element visible even when the soft keyboard is open, like how Chrome does it?

3
  • How about making the body as high as the viewport.
    – Mr Lister
    Commented Jan 18, 2018 at 11:44
  • did you try "position: sticky"?
    – jilykate
    Commented Jan 25, 2018 at 15:54
  • @jilykate Yes. It doesn't work. Commented Feb 25, 2020 at 12:36

5 Answers 5

1

I recently ran in to this problem when creating a chat input that should stay fixed at the bottom of the page. Naturally the iOS keyboard displayed on top of the chat input. Knowing the exact keyboard height seems more or less impossible. I embarked on a quest to find a solid value to base my calculations on so i can manually position the chat input container above the keyboard. I wanted to find the actual "innerHeight" value, in other words the currently visible area of the webpage. Due to how the iOS keyboard works, the only way to get that value with the keyboard open seems to be to scroll to the very bottom of the page, and then take a sample of "window.innerHeight".

So, i set up an event listener on my input field on 'click' (since on 'focus' caused a lot of issues for me). This opens the keyboard, which takes a while, so after i set a timeout for 1000ms to make sure (hopefully) that my keyboard is fully open. After 1000ms i quickly scroll to the bottom of the page with javascript, save the value of "window.innerHeight" in this state, and scroll back to where i was. This gives me the actual height of the visible area on the screen.

It seems like the browser window is placed behind the keyboard until you scroll to the very bottom, in which case the whole window 'scrolls up' and the bottom is placed at the top of the keyboard view.

Once i have this value i use currently scrolled value (window.scrollY) plus the value i saved minus the height of my absolute positioned element to determine where to place it. I opted to also hide the input while scrolling since it's flicking around quite a bit. Another downside to this is that you get a quick flick of the page when it does the measurement at the bottom.

Another thing i couldn't solve was the variable height of the address bar. I just made the input a bit higher than i needed so it would have some "padding" at the bottom.

var correctInnerHeight = window.innerHeight;
var isFocused = false;
var docHeight = $(document).height();
var input = $('.myInput');
input.click(function(e){
  isFocused = true;
  input.css('position', 'absolute');
  // Wait for the keyboard to open
  setTimeout(function(){
    docHeight = $(document).height();
    var lastScrollPos = $(document).scrollTop();
    // Scroll to the bottom
    window.scroll(0, $(document).height());
    // Give it a millisecond to get there
    setTimeout(function(){
      // Save the innerHeight in this state
      correctInnerHeight = window.innerHeight;
      console.log(correctInnerHeight);
      // Now scroll back to where you were, or wish to be.
      window.scroll(0, lastScrollPos);
      fixInputPosition();
      // Make sure the input is focused
      input.focus();
    }, 1);
  }, 1000);
});

input.on('blur', function(){
  input.css('position', 'fixed');
  input.css('top', 'auto');
  input.css('bottom', '');
  isFocused = false;
});

$(window).scroll(function(){
  fixInputPosition();
});

function fixInputPosition(){
  if(isFocused){
    var offsetTop = ($(window).scrollTop() + correctInnerHeight) - input.height();
    offsetTop = Math.min(docHeight, offsetTop);
    input.css('top', offsetTop);
    input.css('bottom', 'auto');
  }
};
body, html{
  margin: 0;
}
html{
  width: 100%;
  height: 2000px;
}
.myInput{
  position: fixed;
  height: 30px;
  bottom: 0;
  width: 100%;
  border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type='text' class='myInput'>

0

Check out this thread, it talks about a work around that may be more feasible in terms of code. In brief it talks about using the height of the keyboard to move the content into view. All be it a bit hacky it may be difficult to pin down the exact height of the keyboard across devices.

Unfortunately, due to the nature of the IOs Safari keyboard it's not part of the browser viewport so cannot be referenced as you would do typical elements.

@Bhimbim's answer may a good shot too.

Regards, -B

1
  • Thanks. Yeah, I thought about that but I don't think there's a way to reliably know the height of the keyboard.
    – Andreyu
    Commented Jan 26, 2018 at 12:53
0
+50

i experienced this before. What i did back then was :

  1. Make a listener when keyboard is hit.
  2. When keyboard is hit resize you webview's height with screen height - keyboard height.
  3. To do this trick you need to make sure that you html is responsive.

I can show more code in the IOS side, if you're interested i can edit my answer and show you my IOS code. Thank you.

Hi again, sorry, i was mistaken, i thought you were creating apps with webview inside. If you still wanna do this by listening the keyboard i still have work around for you. It may not the perfect way, but i believe this will work if you want to try. Here my suggestion :

  1. You still can have listener from webpage when the keyboard is up. You can put a listener on your textfield by jquery onkeyup or onfocus.
  2. Then you will know when the input is hit and the keyboard will show.
  3. Then you can create a condition in your java script to manipulate your screen.

Hope this give you an insight friend. @Beaniie thank you !.

Hi Andreyu !. Yes correct, we can not know the keyboard height, not like my case with WebView, I can know the keyboard height through IOS code. I have another work around, not so smart, but might work. You can get the screen size and compare to array of IOS device screen size. Then you might narrowed down the keyboard height by surveying through IOS devices. Good luck friend.

5
  • I'm writing a web page, not an app.
    – Andreyu
    Commented Jan 26, 2018 at 10:55
  • No, I meant the question was about a web page, not an app.
    – Andreyu
    Commented Jan 26, 2018 at 12:52
  • i'm sorry, so its different, i tought you're loading a webview like my apps. So in your case there might be a work around. Let me update my answer. @Beaniie thank yoou !.
    – Bhimbim
    Commented Jan 27, 2018 at 5:14
  • Thanks for the updated answer, I've thought about that solution, but the problem is I don't have any way to know how tall the keyboard is.
    – Andreyu
    Commented Jan 27, 2018 at 11:40
  • @Andreyu, I updated my answer, not so smart work around, but might works :).
    – Bhimbim
    Commented Jan 28, 2018 at 20:14
0

My solution (myBottomDiv is a div bottom fixed to make a chat, it contains an input). With Safari on iOS, need to make it absolute and change the position each time the page moves. I hope someday Safari will implement the meta interactive-widget=resizes-content like Chrome.

// Only for Safari on iOS
// (use interactive-widget=resizes-content to fix Chrome)
if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
    if (navigator.userAgent.indexOf('Chrome') === -1 && navigator.userAgent.indexOf('Safari') > -1) {

        // Put the body relative
        document.body.style.position = 'relative';
        let marginTop = parseInt(window.getComputedStyle(document.body).marginTop);
    
        // My toolbar (in my case, a div with an input inside to make a chat)
        myBottomDiv.style.position = 'absolute';
    
        // Events (touchmove on mobile, because the scroll event doesn't work well)
        window.addEventListener("scroll", resizeHandler);
        window.addEventListener("touchmove", resizeHandler);
        window.visualViewport.addEventListener("resize", resizeHandler);
    
        function resizeHandler() {
            myBottomDiv.style.top = (window.scrollY +  window.visualViewport.height - marginTop - myBottomDiv.offsetHeight) + 'px';
        }
    }
}
-1

Try using position:absolute and height:100% for the whole page.

When the system displays the keyboard,it plTaces it on top of the app content. One way is to manage both the keyboard and objects is to embed them inside a UIScrollView object or one of its subclasses, like UITableView. Note that UITableViewController automatically resizes and repositions its table view when there is inline editing of text fields.

When the keyboard is displayed, all you have to do is reset the content area of the scroll view and scroll the desired text object into position. Thus, in response to a UIKeyboardDidShowNotification, your handler method would do the following:

1.Get the size of the keyboard.

2.Adjust the bottom content inset of your scroll view by the keyboard height.

3.Scroll the target text field into view.

Check the Apple developer's guideline to learn more:https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

1
  • 1
    Isn't this is for iOS application, how you detect it in browser ? Commented Jan 24, 2018 at 9:11

Not the answer you're looking for? Browse other questions tagged or ask your own question.