iOS iPad Fixed position breaks when keyboard is opened

SafariMobile Safari

Safari Problem Overview


Fixed position breaks on header when I click on the "Search Form" text box field. It simply detaches from the top of the page (as it's fixed up there) and starts floating middle of the page when the virtual keyboard opens up.

Normal:

enter image description here

Broken:

enter image description here

Safari Solutions


Solution 1 - Safari

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

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

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

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

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

Solution 6 - Safari

What you need to do is set the position of the body to fixed while the user is editing text and then restore it to static when the user is done. You can do this either on focus/blur (shown below), or if a user is opening a modal, you can do it on modal open/close.

$("#myInput").on("focus", function () {
    $("body").css("position", "fixed");
});

$("#myInput").on("blur", function () {
    $("body").css("position", "static");
});

Solution 7 - Safari

Fixed - Did a hack around to push the header back to relative fix position once Search text box was entered. This is a bug in iOS virtual keyboard implementation as it breaks fixed positions on text fields IF page is scrollable. If overflow is hidden / page not scrollable, then it won't break fixed positions when virtual keyboard is executed.

Cheers.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioncoldblooded01View Question on Stackoverflow
Solution 1 - SafarimartinedwardsView Answer on Stackoverflow
Solution 2 - SafaribasaratView Answer on Stackoverflow
Solution 3 - Safariprashanth padalaView Answer on Stackoverflow
Solution 4 - SafariSilksterView Answer on Stackoverflow
Solution 5 - SafarithdoanView Answer on Stackoverflow
Solution 6 - SafariScott SemyanView Answer on Stackoverflow
Solution 7 - Safaricoldblooded01View Answer on Stackoverflow