原文出自:http://www.cnblogs.com/zml-mary/p/7816495.htmlcss
qa測試手機升級之後彈框輸入光標出現錯位現象,前兩天因爲時間緊迫,一直沒有找到好的解決方案,今天一天都在解決這個bug問題,臨近下班終於算比較好的解決這個問題,以爲有必要理理~html
引發緣由:彈框的定位採起position:fixed,而ios(safari)對定位屬性position:fixed的解析不一致致使。ios
解決方案:app
方案一iphone
一開始上網找解決方案,找到以下處理方式。但存在當頁面出現滾動條時,彈框彈出後,頁面回滾至頂部。在不改變原有彈框代碼的狀況下,有效地解決光標錯位問題,但嚴重影響用戶使用,只能忍痛捨去~佈局
//彈框彈出後執行以下代碼 $('body').css({'position': 'fixed', 'width': '100%'}); //彈框關閉後執行以下代碼 $('body').css({'position': 'relative'});
方案二測試
嘗試多種方式後,只能從源頭解決,不使用position:fixed。重寫彈框定位,但問題是,這個彈框涉及全部頁面,後臺開發用這彈框作了不少操做,彈框中間內容因爲能夠自定義,因此是牽一髮而動全身,不敢輕易改,就連上傳圖片的進度條顯示都是用這個彈框作的(就是爲了套用彈框的一個遮罩效果)spa
解決思路:code
1.彈框(#pop )採用position:absolute定位,遮罩(#shadow)採用fixed定位(原先採用absolute定位的,因爲有些頁面內容是根據用戶滾動進行動態加載,致使原先的遮罩不能徹底遮住全部內容,固然也能夠對某些元素定高進行加載內容,避免此類問題出現,但此次的修改要考慮通用性,後臺開發有時候根本無論你這些,關鍵目前系統不少頁面都已經出現這問題了)htm
2.彈框採用absolute定位後,關鍵是top值的肯定(ios10.3 Safari 輸入鍵盤彈出時,若頁面底部被擠壓上去,則關閉彈框會復原到頁面滾動到底部時的狀態,若底部沒被擠壓上去,每彈出一次鍵盤,頁面都會上去必定距離,且不復原)
var initTopH = function() { var tempH = $('#pop').height(); //彈框高度 var screenH = $(window).height();//手機屏幕高度 var scrollH = $(document).scrollTop();//文檔內容滾動高度 var topH = scrollH + (screenH - tempH) / 2;//top值高度
//解決當輸入鍵盤未手動關閉時,彈窗的定位問題
if ($(document).height() - scrollH < screenH) {
topH = $(document).height() - screenH + (screenH - tempH) / 2;
}
return topH; };
3.覺得這樣就能夠解決問題,但新的問題出現,當輸入框得到焦點時,移動端會彈出鍵盤擠壓彈框上移,關閉鍵盤後,彈框不會恢復原位,因此須要對彈框失焦後在進行從新定位執行initTopH()
$("#pop input,textarea").off('blur').on('blur', function() { //這裏只是對input和textarea處理 $('#pop').css({'top':initTopH()}); });
4. 要成功解決一個問題,就會引起更多的問題須要解決,成功操做1-3的操做後,當彈框彈出後,若頁面存在滾動條,此時滾動頁面,彈框是不會跟着頁面下移的,由於top是寫死的。想固然是監聽頁面滾動(scroll)事件,實時改變top值,但問題是效果太差,抖動、彈跳太明顯,qa確定會提bug的~
另外一途徑就是彈出彈框後禁止頁面滾動,覺得設置body頁面overflow:hidden就行了,然而pc端模擬測試有效果,真實環境仍然不起做用。覺得沒有給body定高,就都設置html,body標籤的高度爲100%;但然並卵,反而出現 $(document).scrollTop() 取值有問題(用$('body').scrollTop()替換仍沒用,關鍵pc端模擬都有效果,一到真實環境就出問題),影響前面彈框定位。煩~煩~煩~,反覆測試,都沒有實質性的進展~
前面一直糾結於給body定高,但想一想仍是不妥,不少頁面開發者給各自頁面都會從新定義樣式,我這麼暴力地修改,擔憂影響其餘頁面佈局,因此果斷放棄這條路子~
如何在不影響大局的狀況下從新佈局呢?忽然想到了阻止默認事件 e.preventDefault() ,可是新問題又來了,使用這個能夠很好的解決頁面滾動問題,但也會阻止彈框裏內容滾動。糾結ing~
5.冥思苦想,採起總體除去局部的思想來監聽touchmove事件,方法以下,當觸摸對象不是彈框時,阻止默認事件,當觸摸對象是彈框時,雖然滾動彈框裏的內容出現底部頁面也滾動的狀況,但觸摸結束之後恢復原始的滾動高度,經測試效果還不錯,也不以爲突兀~
$('#pop').show(); var sh;//記錄初始滾動高度 $(document).off('touchstart').on('touchstart', function(e) { sh = $(document).scrollTop(); }); $(document).off('touchmove').on('touchmove', function(e) { if (e.target.id === "shadow") {//除去#pop e.preventDefault(); } }); $(document).off('touchend').on('touchend', function(e) { $(document).scrollTop(sh); });
總結:雖然可能會有更好的解決方案,但這是我目前以爲比較好的處理方式,每一個人所處的開發環境不同,考慮的東西也不一樣,因此此方法並不必定都適應,能夠借鑑參考。一天都在解決這個bug問題,找資料,嘗試各類方法,雖然問題已解決,但仍是想好好理順下思路,故寫下這篇隨筆~啦~啦~啦~啦,下班啦~
ps:領導說能夠看下其餘應用的彈框是否有此類問題,看下人家是怎麼解決的,但我和小夥伴看了全部app,都沒找到相似彈出須要輸入文字的彈框(除iphone手機彈出用戶輸入id密碼外),大都是新開一個頁面讓用戶填寫,看來產品仍是要往用戶習慣上靠~