scrollIntoView 介绍
移动端的H5页面,当输入框元素获取焦点时,会吊起软键盘,如果输入框被软键盘遮挡了,则页面会发生滚动使输入框显示在可视区。浏览器这种默认处理机制在元素设置了绝对定位或设置了html,body{height:100%;}
时可能会失效,通常需要手动处理。
防软键盘遮挡的处理思路:
-
IOS系统中,软键盘吊起时,整个 window 往上滚,window的宽高不变,不会触发window.onresize 事件。并且,软键盘始终不会遮挡输入框,所以在ios中不处理。有些版中的微信页面存在页面不回滚的bug,这个需要处理。
-
安卓系统中,软键盘吊起时,window 不滚动,window的高度减小,减少值等于软键盘的高度,会触发 window.onresize 事件。如果输入框被遮挡,可使用 scrollIntoView 方法强制在可视区显示获取焦点的输入框元素。
让当前的元素滚动到浏览器窗口的可视区域内方法。 MDN
scrollIntoView()
浏览器支持度较高(推荐)。
scrollIntoViewIfNeeded()
部分浏览器支持,懒滚动模式。
scrollIntoView()
Element.scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内。
这是一个实验中的功能,浏览器支持:PC端和移动端都支持
语法:
element.scrollIntoView(); // 等同于element.scrollIntoView(true)
element.scrollIntoView(bool); // Boolean型参数
element.scrollIntoView(options); // Object型参数
bool
可选,一个Boolean值:如果为true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。相应的 options: {block: “start”, inline: “nearest”}。这是这个参数的默认值。如果为false,元素的底端将和其所在滚动区的可视区域的底端对齐。相应的options: {block: “end”, inline: “nearest”}。
options
可选, 一个包含下列属性的对象:
behavior 可选,定义动画过渡效果, "auto"或 “smooth” 之一。默认为 “auto”。
block 可选,定义垂直对齐, “start”, “center”, “end”, “nearest”。默认为 “start”。
inline 可选,定义水平对齐, “start”, “center”, “end”, “nearest”。默认为 “nearest”。
var element = document.getElementById("box");
element.scrollIntoView();
element.scrollIntoView(false);
element.scrollIntoView({
block: "end"});
element.scrollIntoView({
behavior: "instant", block: "end", inline: "nearest"});
scrollIntoViewIfNeeded()
Element.scrollIntoViewIfNeeded()方法用来将不在浏览器窗口的可见区域内的元素滚动到浏览器窗口的可见区域。 如果该元素已经在浏览器窗口的可见区域内,则不会发生滚动。 此方法是标准的Element.scrollIntoView()方法的专有变体。
这是一个非标准的功能,浏览器支持:移动端几乎都支持
语法:
element.scrollIntoViewIfNeeded();
// 等同于element.scrollIntoViewIfNeeded(true)
element.scrollIntoViewIfNeeded(false);
element.scrollIntoViewIfNeeded(true);
如果为true,则元素将在其所在滚动区的可视区域中居中对齐。
如果为false,则元素将与其所在滚动区的可视区域最近的边缘对齐。 根据可见区域最靠近元素的哪个边缘,元素的顶部将与可见区域的顶部边缘对准,或者元素的底部边缘将与可见区域的底部边缘对准。
示例:
var element = document.getElementById("child");
element.scrollIntoViewIfNeeded();
element.scrollIntoViewIfNeeded(true);
element.scrollIntoViewIfNeeded(false);
1.利用 scrollIntoView 实现防遮挡
1.针对某个元素单独处理
var inp = document.getElementById('inp');
//安卓中获取焦点时防遮挡
inp.onfocus = function(){
if(this.scrollIntoViewIfNeeded){
//懒滚动,当在可见区时不发生滚动,元素不再可见区时滚动到可见区中部
this.scrollIntoViewIfNeeded(true);
}else{
//无论怎样都会滚动到与可见区底部对齐
this.scrollIntoView(false);
}
}
//ios 中失去焦点时回滚
inp.onblur = function(){
window.scrollTo(0, 0)
}
2.全局处理
//安卓中获取焦点时防遮挡
window.onresize = function () {
if (document.activeElement.scrollIntoViewIfNeeded) {
//懒滚动,当在可见区时不发生滚动,元素不再可见区时滚动到可见区中部
document.activeElement.scrollIntoViewIfNeeded(true);
} else {
//无论怎样都会滚动到与可见区底部对齐
document.activeElement.scrollIntoView(false);
}
}
//ios 中失去焦点时回滚
document.onkeyup = function(e){
var name = e.target.tagName
if (name != 'INPUT' && name != 'SELECT' && name != 'TEXTAREA') {
window.scrollTo(0, 0)
}
}
3.由于上面两种简单处理方式可能存在有些手机不触发等细节问题。推荐用下面这种方式。
<input type="text" onfocus="SV.focus(this)" name="">
<script>
let SV = {
_el:null,
_isFocusNow:false,
_ua:window.navigator.userAgent,
_init:false,
_scroll:function(){
var el = this._el;
if(!el) return false;
if(el.scrollIntoViewIfNeeded){
el.scrollIntoViewIfNeeded(true);
}else{
el.scrollIntoView(false);
}
},
_toTop:function(el){
var _t = this;
_t._isFocusNow = false;
setTimeout