iOS 11サファリでは、入力テキストボックスカーソルは入力テキストボックスの外側にあります。なぜこの問題が発生しているのかわかりませんでした。ご覧のとおり、フォーカスされたテキストボックスは電子メールのテキスト入力ですが、カーソルはその外側にあります。これはiOS11Safariでのみ発生します
回答:
position:fixed
モーダルを開くときにボディに追加することで問題を修正しました。これがお役に立てば幸いです。
width:100%
本体の幅をデバイスの幅に制限するために追加する必要がある場合もあります。場合によっては、既存のマークアップによっては、それが問題になる可能性があります。また、@ gentleboy(下記)による解決策が気に入っているので、他のブラウザーに問題なくペナルティを課さないようにしています。本体を固定に設定すると、本体が上にスクロールするため、やや面倒です。
position:fixed
申請書の本文に申請していました。代わりにposition:absolute
、html
要素でそれを変更し、問題を修正しました。ジェンありがとう!
個人的には、position: fixed
自動的に上にスクロールします。かなり迷惑です!
他のデバイスやバージョンにペナルティを課すことを避けるために、私はこの修正をiOSの適切なバージョンにのみ適用します。
javascript / jQueryの場合
$(document).ready(function() {
// Detect ios 11_x_x affected
// NEED TO BE UPDATED if new versions are affected
var ua = navigator.userAgent,
iOS = /iPad|iPhone|iPod/.test(ua),
iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
// ios 11 bug caret position
if ( iOS && iOS11 ) {
// Add CSS class to body
$("body").addClass("iosBugFixCaret");
}
});
CSSの場合
/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
クラスを持つ選択されたモーダルに対してのみ起動するように関数を変更しました .inputModal
上にスクロールしないようにするには、入力のあるモーダルのみに影響を与える必要があります。
javascript / jQueryの場合
$(document).ready(function() {
// Detect ios 11_x_x affected
// NEED TO BE UPDATED if new versions are affected
(function iOS_CaretBug() {
var ua = navigator.userAgent,
scrollTopPosition,
iOS = /iPad|iPhone|iPod/.test(ua),
iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
// ios 11 bug caret position
if ( iOS && iOS11 ) {
$(document.body).on('show.bs.modal', function(e) {
if ( $(e.target).hasClass('inputModal') ) {
// Get scroll position before moving top
scrollTopPosition = $(document).scrollTop();
// Add CSS to body "position: fixed"
$("body").addClass("iosBugFixCaret");
}
});
$(document.body).on('hide.bs.modal', function(e) {
if ( $(e.target).hasClass('inputModal') ) {
// Remove CSS to body "position: fixed"
$("body").removeClass("iosBugFixCaret");
//Go back to initial position in document
$(document).scrollTop(scrollTopPosition);
}
});
}
})();
});
CSSの場合
/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
HTMLの場合 クラスinputModalをモーダルに追加します
<div class="modal fade inputModal" tabindex="-1" role="dialog">
...
</div>
注意 :javascript関数が自己呼び出しするようになりました
iOS 11.3の時点で、バグは修正されています。以下のためのテストする必要はありませんOS 11_
では、iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
ただし、iOS 11.2はまだ広く使用されているので注意してください(2018年4月現在)。見る
iOS11 = /OS 11_(\d{1,2})(_{0,1})(\d{1,2})/.test(us);
ios11 = /OS 11_(\d{1,2})/.test(ua);
この問題は、Bootstrapだけでなく、Safariだけでもありません。これは、すべてのブラウザで発生するiOS11の完全な表示バグです。上記の修正により、すべてのインスタンスでこの問題が修正されるわけではありません。
バグはここで詳細に報告されます:
https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8
おそらく彼らはすでにそれをバグとしてAppleに報告している。
イライラするバグ、それを特定してくれてありがとう。そうでなければ、iPhoneや頭を壁にぶつけてしまうでしょう。
最も簡単な修正は(1行のコード変更)です。
次のCSSをhtmlまたは外部cssファイルに追加するだけです。
<style type="text/css">
.modal-open { position: fixed; }
</style>
これが完全に機能する例です:
.modal-open { position: fixed; }
<link href="https://getbootstrap.com/docs/3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@mdo">Open modal for @mdo</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@fat">Open modal for @fat</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@getbootstrap">Open modal for @getbootstrap</button>
...more buttons...
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="exampleModalLabel">New message</h4>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="recipient-name" class="control-label">Recipient:</label>
<input type="text" class="form-control" id="recipient-name">
</div>
<div class="form-group">
<label for="message-text" class="control-label">Message:</label>
<textarea class="form-control" id="message-text"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Send message</button>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://getbootstrap.com/docs/3.3/dist/js/bootstrap.min.js"></script>
ここで問題を送信しました:https: //github.com/twbs/bootstrap/issues/24059
最も簡単でクリーンなソリューション:
body.modal-open { position: fixed; width: 100%; }
AppleデバイスをiOS11.3に更新した後、この問題は再現できなくなりました
モーダルが開いposition: fixed;
ているbody
ときに追加します。
$(document).ready(function($){
$("#myBtn").click(function(){
$("#myModal").modal("show");
});
$("#myModal").on('show.bs.modal', function () {
$('body').addClass('body-fixed');
});
$("#myModal").on('hide.bs.modal', function () {
$('body').removeClass('body-fixed');
});
});
.body-fixed {
position: fixed;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<button type="button" class="btn btn-info btn-lg" id="myBtn">Open Modal</button>
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Form</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label class="control-label">Input #1</label>
<input type="text" class="form-control">
</div>
<div class="form-group">
<label class="control-label">Input #2</label>
<input type="text" class="form-control">
</div>
<div class="form-group">
<label class="control-label">Input #3</label>
<input type="text" class="form-control">
</div>
<div class="form-group">
<label class="control-label">Input #4</label>
<input type="text" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
を使用したこれらのソリューションposition: fixed
とそれに基づく位置修正はscrollTop
非常にうまく機能しますが、一部の人々(私を含む)は別の問題を抱えていました:入力がフォーカスされているときにキーボードのキャレット/カーソルが表示されません。
私は、キャレット/カーソルは、我々はときにのみ動作することを観察しないでください使用position: fixed
の体に。だから、いくつかのことを試した後、私はこのアプローチを使用してあきらめ、使用することを決めたposition: relative
上でbody
、使用するscrollTop
正しいへのモーダルのトップ位置の代わりに。
以下のコードを参照してください。
var iosScrollPosition = 0;
function isIOS() {
// use any implementation to return true if device is iOS
}
function initModalFixIOS() {
if (isIOS()) {
// Bootstrap's fade animation does not work with this approach
// iOS users won't benefit from animation but everything else should work
jQuery('#myModal').removeClass('fade');
}
}
function onShowModalFixIOS() {
if (isIOS()) {
iosScrollPosition = jQuery(window).scrollTop();
jQuery('body').css({
'position': 'relative', // body is now relative
'top': 0
});
jQuery('#myModal').css({
'position': 'absolute', // modal is now absolute
'height': '100%',
'top': iosScrollPosition // modal position correction
});
jQuery('html, body').css('overflow', 'hidden'); // prevent page scroll
}
}
function onHideModalFixIOS() {
// Restore everything
if (isIOS()) {
jQuery('body').css({
'position': '',
'top': ''
});
jQuery('html, body').scrollTop(iosScrollPosition);
jQuery('html, body').css('overflow', '');
}
}
jQuery(document).ready(function() {
initModalFixIOS();
jQuery('#myModal')
.on('show.bs.modal', onShowModalFixIOS)
.on('hide.bs.modal', onHideModalFixIOS);
});
前述のように、style.position
property
のbody
を設定fixed
するとiOS cursor misplacement
問題が解決します。
ただし、このゲインは、ページの上部に強制的にスクロールされるという犠牲を伴います。
幸い、この新しいUX
問題は、とを活用することでHTMLElement.style
、オーバーヘッドをあまりかけずに打ち消すことができますwindow.scrollTo()
。
基本的な要点はscroll to top
、body
要素のstyle.top
whenを操作することによってを打ち消すことmounting
です。これはYOffset
、ygap
変数によってキャプチャされた値を使用して行われます。
そこから、それは単にリセットの問題だbody's
style.top
に0
して使用してユーザーのビューをリフレーミングwindow.scrollTo(0, ygap)
するときdismounting
。
実用的な例については、以下を参照してください。
// Global Variables (Manage Globally In Scope).
const body = document.querySelector('body') // Body.
let ygap = 0 // Y Offset.
// On Mount (Call When Mounting).
const onModalMount = () => {
// Y Gap.
ygap = window.pageYOffset || document.documentElement.scrollTop
// Fix Body.
body.style.position = 'fixed'
// Apply Y Offset To Body Top.
body.style.top = `${-ygap}px`
}
// On Dismount (Call When Dismounting).
const onModalDismount = () => {
// Unfix Body.
body.style.position = 'relative'
// Reset Top Offset.
body.style.top = '0'
// Reset Scroll.
window.scrollTo(0, ygap)
}
functions
いつmounting
、そして、それらを呼び出すことですdismounting
。ありがとう。
誰かがIOS> 11.2で動作し、追加のCSSを必要としないvanillajsの修正を探している場合:
(function() {
if (!/(iPhone|iPad|iPod).*(OS 11_[0-2]_[0-5])/.test(navigator.userAgent)) return
document.addEventListener('focusin', function(e) {
if (!e.target.tagName == 'INPUT' && !e.target.tagName != 'TEXTAREA') return
var container = getFixedContainer(e.target)
if (!container) return
var org_styles = {};
['position', 'top', 'height'].forEach(function(key) {
org_styles[key] = container.style[key]
})
toAbsolute(container)
e.target.addEventListener('blur', function(v) {
restoreStyles(container, org_styles)
v.target.removeEventListener(v.type, arguments.callee)
})
})
function toAbsolute(modal) {
var rect = modal.getBoundingClientRect()
modal.style.position = 'absolute'
modal.style.top = (document.body.scrollTop + rect.y) + 'px'
modal.style.height = (rect.height) + 'px'
}
function restoreStyles(modal, styles) {
for (var key in styles) {
modal.style[key] = styles[key]
}
}
function getFixedContainer(elem) {
for (; elem && elem !== document; elem = elem.parentNode) {
if (window.getComputedStyle(elem).getPropertyValue('position') === 'fixed') return elem
}
return null
}
})()
これは何をしますか:
focusin
ページ上のイベントを聞くinput
、またはtextarea
とを持つ要素に含まれるfixed
位置に容器の位置を変更absolute
に関するながらscrollTop
とコンテナ元の寸法。fixed
ます。このソリューションは私にとってはうまくいき、iOS上のすべてのブラウザでうまく機能しました。
.safari-nav-force{
/* Allows content to fill the viewport and go beyond the bottom */
height: 100%;
overflow-y: scroll;
/* To smooth any scrolling behavior */
-webkit-overflow-scrolling: touch;
}
JavsScript
var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
$('.modal').on('shown.bs.modal', function () {
if (iOS && $('.modal').hasClass('in')){
$('html,body').addClass('safari-nav-force');
}
});
$('.modal').on('hidden.bs.modal', function () {
if (iOS && !$('.modal').hasClass('in')){
$('html,body').removeClass('safari-nav-force');
}
});
メタビューポートのviewport-fit = coverを試してみましたか。
これを見てください:https://ayogo.com/blog/ios11-viewport/
#modal position:absoluteに追加して、positionに関連する将来の問題を修正します:fixed