iOS iPad Fixed position breaks when keyboard is opened

Solution 1:

I really like this solution (http://dansajin.com/2012/12/07/fix-position-fixed/). I packaged it up into a little jQuery plugin so I could:

  • Set which parent gets the class
  • Set which elements this applies to (don't forget "textarea" and "select").
  • Set what the parent class name is
  • Allow it to be chained
  • Allow it to be used multiple times

Code example:

$.fn.mobileFix = function (options) {
    var $parent = $(this),

    $(document)
    .on('focus', options.inputElements, function(e) {
        $parent.addClass(options.addClass);
    })
    .on('blur', options.inputElements, function(e) {
        $parent.removeClass(options.addClass);

        // Fix for some scenarios where you need to start scrolling
        setTimeout(function() {
            $(document).scrollTop($(document).scrollTop())
        }, 1);
    });

    return this; // Allowing chaining
};

// Only on touch devices
if (Modernizr.touch) {
    $("body").mobileFix({ // Pass parent to apply to
        inputElements: "input,textarea,select", // Pass activation child elements
        addClass: "fixfixed" // Pass class name
    });
}

EDIT: Removed unnecessary element

Solution 2:

In our case this would fix itself as soon as user scrolls. So this is the fix we've been using to simulate a scroll:

$(document).on('blur', 'input, textarea', function () {
    setTimeout(function () {
        window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
    }, 0);
});

Solution 3:

Based on this good analysis of this issue, I've used this in html and body elements in css:

html,body{
    -webkit-overflow-scrolling : touch !important;
    overflow: auto !important;
    height: 100% !important;
}

it's working great for me.

Solution 4:

Here's a hacky solution using jQuery:

HTML:

<label for="myField">My Field:</label> <input type="text" id="myField" />

<!-- ... other markup here .... -->

<div class="ad_wrapper">my fixed position container</div>

CSS:

.ad_wrapper {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 40px;
    background-color: rgba(0,0,0,0.75);
    color: white;
    text-align: center;
}
.unfixed {
    position: relative;
    left: auto;
    bottom: auto;
}

JS:

$(function () {
    adWrapper = $('.ad_wrapper');

    $(document).on('focusin', 'input, textarea', function() {
        adWrapper.addClass('unfixed');
    })
    .on('focusout', 'input, textarea', function () {
        adWrapper.removeClass('unfixed');
    });
});

Solution 5:

All of the solutions that I've tried so far failed one scenario for me: the fixed top navbar would disappear as soon as the keyboard is displayed on an iPhone. What if you want the fixed element to stay fixed in the same position even when the keyboard is displayed? Below is a simple solution that allows this, with a bonus of keeping the fixed element stuck to the top as you scroll the page while the keyboard is visible (i.e., with the focus still inside the input field).

// Let's assume the fixed top navbar has id="navbar"
// Cache the fixed element
var $navbar = $('#navbar');

function fixFixedPosition() {
  $navbar.css({
    position: 'absolute',
    top: document.body.scrollTop + 'px'
  });
}
function resetFixedPosition() {
  $navbar.css({
    position: 'fixed',
    top: ''
  });
  $(document).off('scroll', updateScrollTop);
}
function updateScrollTop() {
  $navbar.css('top', document.body.scrollTop + 'px');
}

$('input, textarea, [contenteditable=true]').on({
  focus: function() {
    // NOTE: The delay is required.
    setTimeout(fixFixedPosition, 100);
    // Keep the fixed element absolutely positioned at the top
    // when the keyboard is visible
    $(document).scroll(updateScrollTop);
  },
  blur: resetFixedPosition
});

To see a demo, go here on your iPhone:

http://s.codepen.io/thdoan/debug/JWYQeN/gakeYJYOXDPk

Here's a version using requestAnimationFrame, but it didn't appear to perform any better, so I stuck with the first version since it's simpler:

http://s.codepen.io/thdoan/debug/VpvJNX/yYMyLDLBwpRk