Как остановить мою фиксированную навигацию, например, при открытии виртуальной клавиатуры в Mobile Safari?

Я понимаю, что в мобильном сафари много ошибок по фиксированным элементам, но по большей части мне удалось правильно работать с моим макетом, пока я не добавил очень необходимый текстовый ввод в фиксированную навигацию внизу. Теперь, когда пользователь фокусируется на элементе ввода текста и появляется виртуальная клавиатура, моя навигационная система, которая в любом случае всегда фиксируется в нижней части страницы, перескакивает в очень странное место посередине страницы.

enter image description here

Я бы добавил часть моего кода к этому сообщению, но я не был бы уверен, с чего начать. Эта навигация фиксируется внизу и позиционируется слева и внизу 0 и шириной 100%. Оттуда я не знаю, что происходит, я могу только предположить, что это ошибка мобильного сафари.

Он также потеряет фиксированную позицию и станет относительной, только когда элемент ввода текста сфокусирован и виртуальная клавиатура открыта.

Ответ 1

http://dansajin.com/2012/12/07/fix-position-fixed/ это одно из предлагаемых решений. Кажется, стоит сделать снимок.

Вкратце: установите fixed элементы на position:absolute, когда любой вход focus ed и reset их, когда этот элемент blur красный

.header { 
    position: fixed; 
} 
.footer { 
    position: fixed; 
} 
.fixfixed .header, 
.fixfixed .footer { 
    position: absolute; 
} 

и

if ('ontouchstart' in window) {
    /* cache dom references */ 
    var $body = $('body'); 

    /* bind events */
    $(document)
    .on('focus', 'input', function() {
        $body.addClass('fixfixed');
    })
    .on('blur', 'input', function() {
        $body.removeClass('fixfixed');
    });
}

Ответ 2

Решения на вершине - это некоторые способы решения проблемы, но я думаю, что добавление дополнительного класса css или использование moderniz усложняют ситуацию.

Если вы хотите более простое решение, non-modernizr не-extra-css, но только jquery solution и работайте над каждым устройством и браузерами. Я использую это исправление для всех моих проектов. p >

if ('ontouchstart' in window) {
    $(document).on('focus', 'textarea,input,select', function() {
        $('.navbar.navbar-fixed-top').css('position', 'absolute');
    }).on('blur', 'textarea,input,select', function() {
        $('.navbar.navbar-fixed-top').css('position', '');
    });
}

Ответ 3

У меня была аналогичная проблема, но я нашел обходное решение, добавив следующий класс css к элементу body на фокусе ввода, а затем снова удалив его снова:

.u-oh {
    overflow: hidden;
    height: 100%;
    width: 100%;
    position: fixed;
}

Ответ 4

Взяв из того, что сделал sylowgreen, ключ должен зафиксировать body при входе в input. Таким образом:

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

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

Ответ 5

Добавьте javascript следующим образом:

$(function() {
  var $body;
  if ('ontouchstart' in window) {
    $body = $("body");
    document.addEventListener('focusin', function() {
      return $body.addClass("fixfixed");
    });
    return document.addEventListener('focusout', function() {
      $body.removeClass("fixfixed");
      return setTimeout(function() {
        return $(window).scrollLeft(0);
      }, 20);
    });
  }
});

и добавьте класс следующим образом:

.fixfixed header{ 
    position: absolute; 
} 

вы можете ссылаться на эту статью: http://dansajin.com/2012/12/07/fix-position-fixed/

Ответ 6

Мне действительно нравится решение выше. Я упаковал его в маленький плагин jQuery, чтобы я мог:

  • Установить родительский класс
  • Задайте, к каким элементам это относится (не забудьте "textarea" и "select" ).
  • Укажите имя родительского класса
  • Позволить ему быть скованным
  • Позволяет использовать его несколько раз

Пример кода:

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

    $(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
    });
}

Ответ 7

Я использую этот jQuery script:

var focus = 0;
var yourInput = $(".yourInputClass");
yourInput.focusin(function(){
    if(!focus) {
        yourInput.blur();
        $("html, body").scrollTop($(document).height());
        focus = 1;
    }
    if(focus) {
        yourInput.focus();
        focus = 0;
    }
});

Отлично работает для меня.

Ответ 8

События focusin и focusout кажутся более подходящими для этой проблемы, чем события focus и blur, поскольку первый пузырь до корневого элемента. См. этот ответ на SO.

Лично я использую AngularJS, поэтому я реализовал его следующим образом:

$window.document.body.addEventListener('focusin', function(event) {
    var element = event.target;
    var tagName = element.tagName.toLowerCase();
    if(!$rootScope.inputOverlay && (tagName === 'input' || tagName === 'textarea' || tagName === 'select')) {
        $rootScope.$apply(function() {
            $rootScope.inputOverlay = true;
        });
    }
});
$window.document.body.addEventListener('focusout', function() {
    if($rootScope.inputOverlay) {
        $rootScope.$apply(function() {
            $rootScope.inputOverlay = false;
        });
    }
});

Примечание. Я условно запускаю этот script, если это мобильный Safari.

Я положил атрибут ng-class на свой навигатор:

<div class="navbar navbar-default navbar-fixed-top" ng-class="{'navbar-absolute': inputOverlay}">

используя следующий CSS:

.navbar-absolute {
    position: absolute !important;
}

Подробнее о focusin здесь и focusout .

Ответ 9

Проверьте это. Оно работает. Я просто проверяю его.

$(document).on('focus','input', function() {
    setTimeout(function() {
        $('#footer1').css('position', 'absolute');
        $('#header1').css('position', 'absolute');
    }, 0);
});
$(document).on('blur','input', function() {
    setTimeout(function() {
        $('#footer1').css('position', 'fixed');
        $('#header1').css('position', 'fixed');
    }, 800);
});

Ответ 10

Ни одно из этих решений не работало для меня, потому что мой DOM сложный, и у меня есть динамические бесконечные страницы прокрутки, поэтому я должен был создать свой собственный.

Фон: Я использую фиксированный заголовок и элемент, расположенный ниже, который находится ниже него, когда пользователь прокручивает это далеко вниз. Этот элемент имеет поле ввода поиска. Кроме того, у меня есть динамические страницы, добавленные во время прокрутки вперед и назад.

Проблема: В iOS, в любое время, когда пользователь нажал на вход в фиксированном элементе, браузер прокрутит весь путь до верхней части страницы. Это не только вызвало нежелательное поведение, но и вызвало добавление моей динамической страницы вверху страницы.

Ожидаемое решение: Нет прокрутки в iOS (вообще нет), когда пользователь нажимает на ввод в липком элементе.

Решение:

     /*Returns a function, that, as long as it continues to be invoked, will not
    be triggered. The function will be called after it stops being called for
    N milliseconds. If `immediate` is passed, trigger the function on the
    leading edge, instead of the trailing.*/
    function debounce(func, wait, immediate) {
        var timeout;
        return function () {
            var context = this, args = arguments;
            var later = function () {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };

     function is_iOS() {
        var iDevices = [
          'iPad Simulator',
          'iPhone Simulator',
          'iPod Simulator',
          'iPad',
          'iPhone',
          'iPod'
        ];
        while (iDevices.length) {
            if (navigator.platform === iDevices.pop()) { return true; }
        }
        return false;
    }

    $(document).on("scrollstop", debounce(function () {
        //console.log("Stopped scrolling!");
        if (is_iOS()) {
            var yScrollPos = $(document).scrollTop();
            if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
                $('#searchBarDiv').css('position', 'absolute');
                $('#searchBarDiv').css('top', yScrollPos + 50 + 'px'); //50 for fixed header
            }
            else {
                $('#searchBarDiv').css('position', 'inherit');
            }
        }
    },250,true));

    $(document).on("scrollstart", debounce(function () {
        //console.log("Started scrolling!");
        if (is_iOS()) {
            var yScrollPos = $(document).scrollTop();
            if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
                $('#searchBarDiv').css('position', 'fixed');
                $('#searchBarDiv').css('width', '100%');
                $('#searchBarDiv').css('top', '50px'); //50 for fixed header
            }
        }
    },250,true));

Требования: JQuery mobile необходим для работы функций запуска и остановки.

Отладка включена для сглаживания любого запаздывания, созданного липким элементом.

Протестировано в iOS10.

Ответ 11

Мне не повезло с решением, предложенным Дэном Саджином. Возможно, ошибка изменилась с тех пор, как он написал это сообщение в блоге, но на iOS 7.1 ошибка всегда будет отображаться, когда позиция будет изменена на фиксированную, после того, как вход будет размытым, даже если вы задержите до тех пор, пока программная клавиатура не будет полностью скрыта. Решение, к которому я пришел, включает в себя ожидание события touchstart, а не событие blur, так как фиксированный элемент всегда возвращается в правильное положение, когда страница прокручивается.

if (Modernizr.touch) {
  var $el, focused;
  $el = $('body');
  focused = false;
  $(document).on('focus', 'input, textarea, select', function() {
    focused = true;
    $el.addClass('u-fixedFix');
  }).on('touchstart', 'input, textarea, select', function() {
    // always execute this function after the `focus` handler:
    setTimeout(function() {
      if (focused) {
        return $el.removeClass('u-fixedFix');
      }
    }, 1);
  });
}

НТН