モバイルサファリには固定要素に関する多くのバグがあることを理解していますが、ほとんどの場合、下部の固定ナビゲーションに必要なテキスト入力を追加するまでレイアウトを正しく機能させることができました。ユーザーがテキスト入力要素に焦点を合わせて仮想キーボードが表示されると、ナビゲーションはページの下部に常に固定されますが、ページの中央にある本当に奇妙な場所にジャンプします。
この投稿にコードの一部を追加しますが、どこから始めればいいのかわかりません。そのナビゲーションは下部に固定され、左と下の0、および100%の幅に配置されます。そこから、私は何が起こっているのかわかりません。モバイルサファリのバグであるとしか思えません。
また、テキスト入力要素にフォーカスがあり、仮想キーボードが開いている間のみ、固定された位置を失い、相対的になります。
http://dansajin.com/2012/12/07/fix-position-fixed/ これは提案された解決策の1つです。一撃の価値があるようだ。
つまり、入力がfixed
edの場合はfocus
要素をposition:absolute
に設定し、その要素がblur
redの場合はリセットします
.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');
});
}
一番上の解決策は、問題を解決するためのいくつかの方法ですが、cssクラスを追加するか、modernizを使用すると事態が複雑になると思います。
より単純なソリューションが必要な場合は、non-modernizrnon-extra-css but pure jquery solutionとすべてのプロジェクトでこの修正プログラムを使用するすべてのデバイスとブラウザーで動作します
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', '');
});
}
私は同様の問題を抱えていましたが、次のcssクラスを入力フォーカスのbody要素に追加し、非フォーカスのときに再び削除することで回避策を見つけました。
.u-oh {
overflow: hidden;
height: 100%;
width: 100%;
position: fixed;
}
Sylowgreenが行ったことから判断すると、キーはbody
の入力時にinput
を修正することです。副<文>この[前述の事実の]結果として、それ故に、従って、だから◆【同】consequently; therefore <文>このような方法で、このようにして、こんなふうに、上に述べたように◆【同】in this manner <文>そのような程度まで<文> AひいてはB◆【用法】A and thus B <文>例えば◆【同】for example; as an example:
$("#myInput").on("focus", function () {
$("body").css("position", "fixed");
});
$("#myInput").on("blur", function () {
$("body").css("position", "static");
});
次のような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/
このjQueryスクリプトを使用します。
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;
}
});
私にぴったりです。
focusin
イベントとfocusout
イベントは、前の要素がルート要素にバブルアップするため、focus
イベントとblur
イベントよりもこの問題に適しているようです。 SOで this answer を参照してください。
個人的には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;
});
}
});
注:これがモバイルSafariの場合、このスクリプトを条件付きで実行しています。
ng-class
私のnavbarの属性:
<div class="navbar navbar-default navbar-fixed-top" ng-class="{'navbar-absolute': inputOverlay}">
次のCSSを使用します。
.navbar-absolute {
position: absolute !important;
}
上記のソリューションが本当に気に入っています。それを小さなjQueryプラグインにパッケージ化したので、次のことができました。
コード例:
$.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
});
}
私の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));
要件: startsrollおよびstopscroll関数が機能するには、JQuery mobileが必要です。
デバウンスは、スティッキ要素によって作成された遅延を滑らかにするために含まれています。
IOS10でテスト済み。
これをテストしてください。できます。ただテストします。
$(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);
});