Sam*_*ron 91 javascript css safari ios ios8
在IOS8 Safari中,有一个新的位置修复错误.
如果您聚焦固定面板中的文本区域,Safari会将您滚动到页面底部.
这使得所有类型的UI都无法使用,因为您无法将文本输入textareas而无需将页面一直向下滚动并丢失位置.
有没有办法干净地解决这个bug?
#a {
height: 10000px;
background: linear-gradient(red, blue);
}
#b {
position: fixed;
bottom: 20px;
left: 10%;
width: 100%;
height: 300px;
}
textarea {
width: 80%;
height: 300px;
}
Run Code Online (Sandbox Code Playgroud)
<html>
<body>
<div id="a"></div>
<div id="b"><textarea></textarea></div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
Moh*_*nna 55
基于对这个问题的这个好分析,我在css中使用了这个html和body元素:
html,body{
-webkit-overflow-scrolling : touch !important;
overflow: auto !important;
height: 100% !important;
}
Run Code Online (Sandbox Code Playgroud)
我觉得它对我很有用.
Ale*_*ara 34
我能想到的最好的解决方案是切换到使用position: absolute;焦点并计算它在使用时的位置position: fixed;.诀窍是focus事件发生得太晚,所以touchstart必须使用.
这个答案中的解决方案非常接近地模仿了iOS 7中的正确行为.
的body元件必须具有定位以确保正确的定位时,元件切换到绝对定位.
body {
position: relative;
}
Run Code Online (Sandbox Code Playgroud)
以下代码是所提供测试用例的基本示例,可以根据您的具体用例进行调整.
//Get the fixed element, and the input element it contains.
var fixed_el = document.getElementById('b');
var input_el = document.querySelector('textarea');
//Listen for touchstart, focus will fire too late.
input_el.addEventListener('touchstart', function() {
//If using a non-px value, you will have to get clever, or just use 0 and live with the temporary jump.
var bottom = parseFloat(window.getComputedStyle(fixed_el).bottom);
//Switch to position absolute.
fixed_el.style.position = 'absolute';
fixed_el.style.bottom = (document.height - (window.scrollY + window.innerHeight) + bottom) + 'px';
//Switch back when focus is lost.
function blured() {
fixed_el.style.position = '';
fixed_el.style.bottom = '';
input_el.removeEventListener('blur', blured);
}
input_el.addEventListener('blur', blured);
});
Run Code Online (Sandbox Code Playgroud)
如果position: fixed;元素具有除定位之外的任何其他父元素body,则切换到position: absolute;可能具有意外行为.由于其性质position: fixed;可能不是主要问题,因为嵌套这样的元素并不常见.
虽然使用该touchstart事件将过滤掉大多数桌面环境,但您可能希望使用用户代理嗅探,以便此代码仅针对损坏的iOS 8运行,而不是针对其他设备(如Android和较旧的iOS版本)运行.不幸的是,我们还不知道Apple何时会在iOS中修复此问题,但如果在下一个主要版本中没有修复它,我会感到惊讶.
我找到了一种无需改变绝对位置即可工作的方法!
完整的未注释代码
var scrollPos = $(document).scrollTop();
$(window).scroll(function(){
scrollPos = $(document).scrollTop();
});
var savedScrollPos = scrollPos;
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;
}
$('input[type=text]').on('touchstart', function(){
if (is_iOS()){
savedScrollPos = scrollPos;
$('body').css({
position: 'relative',
top: -scrollPos
});
$('html').css('overflow','hidden');
}
})
.blur(function(){
if (is_iOS()){
$('body, html').removeAttr('style');
$(document).scrollTop(savedScrollPos);
}
});
Run Code Online (Sandbox Code Playgroud)
打破它
首先,您需要在HTML中将固定输入字段放在页面顶部(这是一个固定元素,因此无论如何它在语义上应该是有意义的):
<!DOCTYPE HTML>
<html>
<head>
<title>Untitled</title>
</head>
<body>
<form class="fixed-element">
<input class="thing-causing-the-issue" type="text" />
</form>
<div class="everything-else">(content)</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
然后,您需要将当前滚动位置保存到全局变量中:
//Always know the current scroll position
var scrollPos = $(document).scrollTop();
$(window).scroll(function(){
scrollPos = $(document).scrollTop();
});
//need to be able to save current scroll pos while keeping actual scroll pos up to date
var savedScrollPos = scrollPos;
Run Code Online (Sandbox Code Playgroud)
然后你需要一种方法来检测iOS设备,这样它就不会影响不需要修复的东西(函数来自/sf/answers/632791981/)
//function for testing if it is an iOS device
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;
}
Run Code Online (Sandbox Code Playgroud)
现在我们拥有了我们需要的一切,这里是修复:)
//when user touches the input
$('input[type=text]').on('touchstart', function(){
//only fire code if it's an iOS device
if (is_iOS()){
//set savedScrollPos to the current scroll position
savedScrollPos = scrollPos;
//shift the body up a number of pixels equal to the current scroll position
$('body').css({
position: 'relative',
top: -scrollPos
});
//Hide all content outside of the top of the visible area
//this essentially chops off the body at the position you are scrolled to so the browser can't scroll up any higher
$('html').css('overflow','hidden');
}
})
//when the user is done and removes focus from the input field
.blur(function(){
//checks if it is an iOS device
if (is_iOS()){
//Removes the custom styling from the body and html attribute
$('body, html').removeAttr('style');
//instantly scrolls the page back down to where you were when you clicked on input field
$(document).scrollTop(savedScrollPos);
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
61710 次 |
| 最近记录: |