Html 光标外的 iOS 11 Safari 引导模式文本区域
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46339063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS 11 Safari bootstrap modal text area outside of cursor
提问by kekkeme
With iOS 11 safari, input textbox cursor are outside of input textbox. We did not get why it is having this problem. As you can see my focused text box is email text input but my cursor is outside of it. This only happens with iOS 11 Safari
在 iOS 11 safari 中,输入文本框光标位于输入文本框之外。我们不明白为什么它会出现这个问题。正如你所看到的,我的焦点文本框是电子邮件文本输入,但我的光标在它之外。这只发生在 iOS 11 Safari
采纳答案by Nattawat Tarweesripayap
I fixed the issue by adding position:fixed
to the body when opening a modal.
Hope this will help you.
我通过position:fixed
在打开模态时添加到正文来解决这个问题。希望这会帮助你。
回答by micaball
Personally, position: fixed
scroll to top automatically. Quite annoying !
就个人而言,position: fixed
自动滚动到顶部。很烦人!
To avoid penalizing other devices and versionsI apply this fix only to the appropriate versions of iOS.
为避免惩罚其他设备和版本,我仅将此修复程序应用于相应版本的 iOS。
**VERSION 1 - All modals fix**
**版本 1 - 所有模态修复**
For the javascript/jQuery
对于 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");
}
});
For the CSS
对于 CSS
/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
**VERSION 2 - Selected modals only**
**版本 2 - 仅选定的模态**
I modified the function to fire only for selected modals with a class .inputModal
我修改了函数以仅针对具有类的选定模态触发 .inputModal
Only the modals with inputs should be impacted to avoid the scroll to top.
只有带有输入的模态才会受到影响,以避免滚动到顶部。
For the javascript/jQuery
对于 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);
}
});
}
})();
});
For the CSS
对于 CSS
/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
For the HTMLAdd the class inputModalto the modal
对于 HTML将类inputModal添加到模态
<div class="modal fade inputModal" tabindex="-1" role="dialog">
...
</div>
Nota beneThe javascript function is now self-invoking
注意javascript 函数现在是自调用的
**UPDATE iOS 11.3 - Bug corrected **
**更新 iOS 11.3 - 修正错误 **
As of iOS 11.3, the bug has been corrected. There is no need to test for OS 11_
in iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
从 iOS 11.3 开始,该错误已得到纠正。有没有需要测试OS 11_
在iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
But be carefulas iOS 11.2 is still widely used (as of April 2018). See
但要小心,因为 iOS 11.2 仍然被广泛使用(截至 2018 年 4 月)。看
回答by Eric Shawn
This issue goes beyond Bootstrap, and beyond just Safari. It is a full display bug in iOS 11 that occurs in all browsers. The fix above does not fix this issue in all instances.
这个问题超出了 Bootstrap,也超出了 Safari。这是 iOS 11 中所有浏览器都会出现的完整显示错误。上述修复程序并未在所有情况下解决此问题。
The bug is reported in detail here:
该错误在此处详细报告:
https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8
https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8
Supposedly they already reported it to Apple as a bug.
据说他们已经将其作为错误报告给了 Apple。
回答by Scott David Murphy
Frustrating bug, thanks for identifying it. Otherwise, I would be banging my iphone or my head against the wall.
令人沮丧的错误,感谢您识别它。否则,我会用我的 iphone 或我的头撞墙。
The simplest fix is (1 line of code change):
最简单的解决方法是(更改 1 行代码):
Just add the following CSS to the html or to an external css file.
只需将以下 CSS 添加到 html 或外部 css 文件。
<style type="text/css">
.modal-open { position: fixed; }
</style>
Here is a full working example:
这是一个完整的工作示例:
.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>
I submitted an issue here: https://github.com/twbs/bootstrap/issues/24059
我在这里提交了一个问题:https: //github.com/twbs/bootstrap/issues/24059
回答by lfkwtz
Easiest/cleanest solution:
最简单/最干净的解决方案:
body.modal-open { position: fixed; width: 100%; }
回答by Eashan
This issue is no longer reproducible after updating your apple devices to iOS 11.3
将您的 Apple 设备更新到 iOS 11.3 后,此问题不再重现
回答by Anuruk S.
Add position: fixed;
to body
when modal is open.
添加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>
回答by FlavioEscobar
Those solutions using position: fixed
and position correction based on scrollTop
work really well, but some people (including me) got another issue: keyboard caret/cursor not showing when inputs are focused.
那些position: fixed
基于scrollTop
工作的使用和位置校正的解决方案非常好,但有些人(包括我)遇到了另一个问题:键盘插入符号/光标在输入集中时不显示。
I observed that caret/cursor works only when we DON'Tuse position: fixed
on body. So after trying several things, I gave up on using this approach and decided to use position: relative
on body
and use scrollTop
to correct modal's top positioninstead.
我观察到插入符号/光标仅在我们不在position: fixed
身体上使用时才起作用。所以在尝试了几件事之后,我放弃了使用这种方法,并决定使用position: relative
onbody
和 usescrollTop
来纠正模态的顶部位置。
See code below:
见下面的代码:
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);
});
回答by Arman Charan
As previously mentioned: setting the style.position
property
of body
to fixed
solves the iOS cursor misplacement
issue.
如前所述:设置style.position
property
ofbody
来fixed
解决iOS cursor misplacement
问题。
However, this gain comes at the cost of being forcibly scrolled to the top of the page.
但是,这种收益是以强制滚动到页面顶部为代价的。
Fortunately, this new UX
problem can be negated without much overhead by leveraging HTMLElement.style
and window.scrollTo()
.
幸运的是,UX
通过利用HTMLElement.style
和可以在没有太多开销的情况下解决这个新问题window.scrollTo()
。
The basic gist is to counteract the scroll to top
by manipulating the body
element's style.top
when mounting
. This is done using the YOffset
value captured by the ygap
variable.
基本要点是scroll to top
通过操纵body
元素的style.top
when来抵消mounting
。这是使用变量YOffset
捕获的值完成的ygap
。
From there it's simply a matter of resetting the body's
style.top
to 0
and reframing the user's view using window.scrollTo(0, ygap)
when dismounting
.
从那里开始,只需使用when将body's
style.top
to重置为0
并重新构建用户视图即可。window.scrollTo(0, ygap)
dismounting
See below for a practical example.
请参阅下面的实际示例。
// 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)
}
回答by Manuel Otto
Incase anyone is looking for a fix in vanilla js that works on IOS >11.2 and doesnt require any additional CSS:
如果有人正在寻找适用于 IOS > 11.2 并且不需要任何额外 CSS 的 vanilla js 的修复程序:
(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
}
})()
What this does is:
它的作用是:
- Check if the browser is Safari on iOS 11.0.0 - 11.2.5
- Listen for any
focusin
events on the page - If the focused element is an
input
or atextarea
and is contained in an element withfixed
position, change the container position toabsolute
while regardingscrollTop
and the containers original dimensions. - On blur, restore the container's position to
fixed
.
- 检查浏览器是否为 iOS 11.0.0 - 11.2.5 上的 Safari
- 侦听
focusin
页面上的任何事件 - 如果焦点元素是 an
input
或 atextarea
并且包含在具有fixed
位置的元素中,则将容器位置更改为absolute
whilescrollTop
和容器的原始尺寸。 - 在模糊时,将容器的位置恢复到
fixed
。