移動端滾動穿透問題 ==> 移動端彈出fixed彈窗的話,在彈窗上滑動會導致下層的頁面跟着滾動,這個叫“滾動穿透”
1.在彈出層的touchstart事件中調用preventDefault
這種方法不可取,至少有3個缺點: 1.如果彈出層本身是有滾動(條)的話,將會導致彈出層無法滾動,此時用這種方法無於飲鴆止渴。 2.一個很常見的場景,點擊彈出層,彈出層消失掉,此時也無法觸發彈出層的點擊回調事。 3.彈出層內的任何事件都執行不了了。
2.彈出層touchmove + preventDefault
// 1.彈出層里不能有需要滾動的內容 // 2.如大段文字需要固定高度,顯示滾動條也會被阻止 modal.addEventListener('touchmove', function(e) { e.preventDefault(); }, false);
3.設置 html,body{overflow:hidden;}
在PC和移動端都能禁止掉下層的滾動。
4.最好的解決方案 ==> 在body元素上設置position: fixed
body.modal-open { position: fixed; width: 100%; }
如果只是上面的 css,滾動條的位置同樣會丟失,所以如果需要保持滾動條的位置需要用 js 保存滾動條位置關閉的時候還原滾動位置
var ModalHelper = (function(bodyCls) { var scrollTop, doc, reg; var bodyClassName = ""; var bodyEle = document.body; return { afterOpen: function() { doc = document.documentElement.scrollTop ? document.documentElement : bodyEle; scrollTop = doc.scrollTop; if(bodyEle.classList){ bodyEle.classList.add(bodyCls) }else{ bodyEle.className += " " + bodyCls; } bodyEle.style.top = -scrollTop + 'px'; bodyClassName = bodyEle.className; }, beforeClose: function() { if(bodyEle.classList){ bodyEle.classList.remove(bodyCls) }else{ reg = new RegExp("\\b" + bodyCls + "\\b", "g", "gi"); if(reg.test(bodyClassName)){ bodyClassName = bodyClassName.replace(reg, ""); bodyEle.className = bodyClassName; } } bodyEle.style.top = ""; doc.scrollTop = scrollTop; } }; })('modal-open');
5.延伸: document.scrollingElement ==> 新標准瀏覽器獲取和設置 scrollTop
console.log(document.scrollingElement.scrollTop);