ด้วยซาฟารี iOS 11 เคอร์เซอร์ของกล่องข้อความอินพุตจะอยู่นอกช่องข้อความอินพุต เราไม่เข้าใจว่าเหตุใดจึงมีปัญหานี้ อย่างที่คุณเห็นกล่องข้อความที่เน้นของฉันคือการป้อนข้อความอีเมล แต่เคอร์เซอร์ของฉันอยู่ด้านนอก สิ่งนี้เกิดขึ้นกับ iOS 11 Safari เท่านั้น
คำตอบ:
ฉันแก้ไขปัญหาโดยการเพิ่ม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 เพิ่ม class inputModalลงในโมดอล
<div class="modal fade inputModal" tabindex="-1" role="dialog">
...
</div>
หมายเหตุ ใต้ฟังก์ชันจาวาสคริปต์ขณะนี้เรียกใช้ด้วยตนเอง
สำหรับ iOS 11.3 ข้อบกพร่องได้รับการแก้ไขแล้ว ไม่จำเป็นต้องทดสอบOS 11_
ในiOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
แต่โปรดระวังเนื่องจาก iOS 11.2 ยังคงใช้กันอย่างแพร่หลาย (ณ เดือนเมษายน 2018) ดู
iOS11 = /OS 11_(\d{1,2})(_{0,1})(\d{1,2})/.test(us);
ios11 = /OS 11_(\d{1,2})/.test(ua);
ปัญหานี้นอกเหนือไปจาก Bootstrap และนอกเหนือจาก Safari เป็นข้อบกพร่องในการแสดงผลแบบเต็มใน iOS 11 ที่เกิดขึ้นในทุกเบราว์เซอร์ การแก้ไขข้างต้นไม่สามารถแก้ไขปัญหานี้ได้ในทุกกรณี
รายงานข้อบกพร่องโดยละเอียดที่นี่:
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 ของคุณเป็น iOS 11.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
mounting
ทำได้โดยใช้YOffset
ค่าที่จับโดยygap
ตัวแปร
จากนั้นมันก็เป็นเพียงเรื่องของการตั้งค่าที่body's
style.top
จะ0
และ reframing มุมมองของผู้ใช้โดยใช้เมื่อ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
ขอบคุณ.
ในกรณีที่ใครก็ตามกำลังมองหาวิธีแก้ไขใน vanilla js ที่ใช้งานได้บน IOS> 11.2 และไม่ต้องการ CSS เพิ่มเติมใด ๆ :
(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
หรือ a textarea
และอยู่ในองค์ประกอบที่มีfixed
ตำแหน่งให้เปลี่ยนตำแหน่งคอนเทนเนอร์เป็นabsolute
while เกี่ยวกับ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 css และเปลี่ยนposition
จากfixed
เป็นabsolute
.modal {
position: absolute !important;
}
เพิ่มในตำแหน่ง #modal: แน่นอนมันแก้ไขปัญหาในอนาคตที่เกี่ยวข้องกับตำแหน่ง: คงที่