Ich verstehe, dass Mobile Safari eine Menge Fehler in Bezug auf feste Elemente aufweist, aber zum größten Teil habe ich es geschafft, mein Layout korrekt zu gestalten, bis ich der festen Navigation unten eine dringend benötigte Texteingabe hinzugefügt habe. Wenn sich der Benutzer auf das Texteingabeelement konzentriert und die virtuelle Tastatur angezeigt wird, springt meine Navigation, die ansonsten immer am unteren Rand der Seite festgelegt ist, zu einer wirklich seltsamen Stelle in der Mitte der Seite.
Ich würde diesem Beitrag einen Teil meines Codes hinzufügen, wäre mir aber nicht sicher, wo ich anfangen soll. Diese Navigation ist unten fixiert und links und unten 0 und 100% breit positioniert. Von dort weiß ich nicht, was los ist, ich kann nur davon ausgehen, dass es sich um einen mobilen Safari-Bug handelt.
Es scheint auch seine feste Position zu verlieren und relativ zu werden, nur wenn das Texteingabeelement aktiviert und die virtuelle Tastatur geöffnet ist.
http://dansajin.com/2012/12/07/fix-position-fixed/ Dies ist eine der vorgeschlagenen Lösungen. Scheint einen Versuch wert.
Kurz gesagt: Setze fixed
Elemente auf position:absolute
, wenn eine Eingabe focus
ed ist, und setzen Sie sie zurück, wenn dieses Element blur
red ist
.header {
position: fixed;
}
.footer {
position: fixed;
}
.fixfixed .header,
.fixfixed .footer {
position: absolute;
}
und
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');
});
}
Die Lösungen auf der Oberseite sind einige Möglichkeiten, das Problem zu beheben, aber ich denke, zusätzliche CSS-Klasse hinzuzufügen oder Moderniz zu verwenden, erschweren die Dinge.
Wenn Sie eine einfachere Lösung wünschen, ist hier ein non-modernizrnon-extra-css aber reines jquery solution und Arbeit auf jedem Gerät und jedem Browser Ich verwende diesen Fix für alle meine Projekte
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', '');
});
}
Ich hatte ein ähnliches Problem, aber ich fand eine Problemumgehung, indem ich die folgende CSS-Klasse zum body-Element beim Eingabefokus hinzufügte und sie dann beim Unfokus wieder entfernte:
.u-oh {
overflow: hidden;
height: 100%;
width: 100%;
position: fixed;
}
Ausgehend von dem, was sylowgreen getan hat, besteht der Schlüssel darin, das body
bei der Eingabe des input
zu korrigieren. Somit:
$("#myInput").on("focus", function () {
$("body").css("position", "fixed");
});
$("#myInput").on("blur", function () {
$("body").css("position", "static");
});
Fügen Sie Javascript wie folgt hinzu:
$(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);
});
}
});
und füge eine Klasse wie diese hinzu:
.fixfixed header{
position: absolute;
}
sie können auf diesen Artikel verweisen: http://dansajin.com/2012/12/07/fix-position-fixed/
Ich benutze dieses jQuery-Skript:
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;
}
});
Funktioniert perfekt für mich.
Die Ereignisse focusin
und focusout
scheinen für dieses Problem besser geeignet zu sein als die Ereignisse focus
und blur
, da sich die erste Blase bis zum Stammelement erstreckt. Siehe diese Antwort auf SO.
Ich persönlich benutze AngularJS und habe es folgendermaßen implementiert:
$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;
});
}
});
Hinweis: Ich führe dieses Skript unter bestimmten Bedingungen aus, wenn es sich um eine mobile Safari handelt.
Ich habe ein ng-class
Attribut auf meiner Navigationsleiste:
<div class="navbar navbar-default navbar-fixed-top" ng-class="{'navbar-absolute': inputOverlay}">
mit dem folgenden CSS:
.navbar-absolute {
position: absolute !important;
}
Ich mag die Lösung oben wirklich. Ich habe es in ein kleines jQuery-Plugin gepackt, damit ich:
Codebeispiel:
$.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
});
}
Keine dieser Lösungen hat für mich funktioniert, da mein DOM kompliziert ist und ich dynamische unendliche Bildlaufseiten habe, sodass ich meine eigenen erstellen musste.
Background: Ich verwende eine feste Kopfzeile und ein Element weiter unten, das darunter haftet, sobald der Benutzer so weit nach unten scrollt. Dieses Element hat ein Suchfeld. Außerdem habe ich dynamische Seiten hinzugefügt, während ich vorwärts und rückwärts scrolle.
Problem: Unter iOS scrollte der Browser jedes Mal, wenn der Benutzer auf die Eingabe im festen Element klickte, ganz nach oben. Dies verursachte nicht nur unerwünschtes Verhalten, sondern löste auch das Hinzufügen meiner dynamischen Seite oben auf der Seite aus.
Erwartete Lösung: Kein Bildlauf in iOS (überhaupt kein Bildlauf), wenn der Benutzer auf die Eingabe im Sticky-Element klickt.
Lösung:
/*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));
Anforderungen: JQuery Mobile ist erforderlich, damit die Startsroll- und Stoppscroll-Funktionen funktionieren.
Debounce ist enthalten, um Verzögerungen auszugleichen, die durch das klebrige Element verursacht werden.
Getestet in iOS10.
Testen Sie diesen. Es klappt. Ich teste es einfach.
$(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);
});