IOS和安卓不一樣瀏覽器常見bug

1、IOS自帶safari瀏覽器

一、safari不支持fixed、input輸入框

iOS下的 Fixed + Input 調用鍵盤的時候fixed無效問題html

 拖動頁面時 header 和 footer 已經定位在了對應的位置,目測沒問題了web

但接下來問題就來了!若是底部輸入框軟鍵盤被喚起之後,再次滑動頁面,就會看到以下圖所示:瀏覽器

咱們看到 fixed 定位好的元素跟隨頁面滾動了起來… fixed 屬性失效了!ide

這是爲何呢?簡單解釋下: > 軟鍵盤喚起後,頁面的 fixed 元素將失效(即沒法浮動,也能夠理解爲變成了 absolute 定位),因此當頁面超過一屏且滾動時,失效的 fixed 元素就會跟隨滾動了。函數

這即是 iOS 上 fixed 元素和輸入框的 bug 。其中不只限於 type=text 的輸入框,凡是軟鍵盤(好比時間日期選擇、select 選擇等等)被喚起,都會遇到一樣地問題。佈局

雖然 isScroll.js 能夠很好的解決 fixed 定位滾動的問題,可是不在萬不得已的狀況下,咱們儘可能嘗試一下不依賴第三方庫的佈局方案,以簡化實現方式。這裏拋磚引玉做爲參考。測試

解決思路

既然在 iOS 下因爲軟鍵盤喚出後,頁面 fixed 元素會失效,致使跟隨頁面一塊兒滾動,那麼假如——頁面不會過長出現滾動,那麼即使 fixed 元素失效,也沒法跟隨頁面滾動,也就不會出現上面的問題了。字體

那麼按照這個思路,若是使 fixed 元素的父級不出現滾動,而將原 body 滾動的區域域移到 main 內部,而 header 和 footer 的樣式不變,代碼以下:網站

 1 <body class="layout-scroll-fixed">
 2     <!-- fixed定位的頭部 (absolute絕對定位也能夠)-->
 3     <header>
 4 
 5     </header>
 6 
 7     <!-- 能夠滾動的區域 -->
 8     <main>
 9         <div class="content">
10         <!-- 內容在這裏... -->
11         </div>
12     </main>
13 
14     <!-- fixed定位的底部 (absolute絕對定位也能夠)-->
15     <footer>
16         <input type="text" placeholder="Footer..."/>
17         <button class="submit">提交</button>
18     </footer>
19 </body>
20 header, footer, main {
21     display: block;
22 }
23 
24 header {
25     position: fixed;//或者absolute
26     height: 50px;
27     left: 0;
28     right: 0;
29     top: 0;
30 }
31 
32 footer {
33     position: fixed;//或者寫成absolute
34     height: 34px;
35     left: 0;
36     right: 0;
37     bottom: 0;
38 }
39 
40 main {
41 /* main絕對定位,進行內部滾動 */
42 position: absolute;
43 top: 50px;
44 bottom: 34px;
45 /* 使之能夠滾動 */
46  overflow-y: scroll;
47   /* 增長該屬性,能夠增長彈性,是滑動更加順暢 */
48   -webkit-overflow-scrolling: touch;   
49 }
50 
51 main .content {
52     height: 2000px;
53 }
View Code

另外,這裏的 header 和 footer 使用的是 fixed 定位,若是考慮到更老一些的 iOS 系統不支持 fixed 元素,徹底能夠把 fixed 替換成 absolute 。測試後效果是同樣的。this

按照上面佈局,就不會出現問題了!

二、safari圖片加載失效,默認圖片過大

網站當中常常會遇到圖片加載失敗的問題,img中有地址,可是地址打開是錯誤的。狀況以下:

不一樣瀏覽器處理錯誤圖片是不同的,有的乾脆就顯示差號,例如IE,有的顯示一張破碎的圖片,有的則是給一張高度比較大的默認圖,例如PC端的火狐,IOS中Safari,還有安卓中的UC瀏覽器。這樣在手機中就會致使左右兩側圖片高度不一致!以下圖:

 

解決方案

其實這裏解決很簡單,判斷當圖片加載失敗的時候給一個默認圖就能夠了,不讓瀏覽器使用其自帶的默認圖。

衍生問題

由於圖片加載失敗進入默認圖,那麼默認圖再加載失敗怎麼辦呢?這不是進入一個死循環嗎?

最簡單的一個解決辦法是,onerror中的圖保證能打開,保證比較小!不會出現問題!。這個方法也是最有效的方法!

假如你不能保證,那麼,只能靠函數來解決這個問題了!

思路是:

當圖片加載失敗,進入onerror的時候,判斷onerror的圖片是否是能加載,在onerror中的圖片觸發onerror的時候,設置onerror爲null。

代碼以下:

2、安卓UC瀏覽器

一、安卓UC爲表明的瀏覽器不支持部分CSS3屬性,例如calc等width:90%;width:calc(ssadft)

二、滾動事件不會觸發touchmove事件

3、手機瀏覽器通用問題

一、彈出層touchmove滾動,會觸發touch滾動(出現前提是body中有滾動軸)

手機網站表層div滑動,致使底層body滑動(touchmove的阻止)

body很長,能夠滑動,body頭部有一個模擬下拉的選擇框。下拉選擇有滾動軸,以下圖。

enter image description here

我給body一個overflow:hidden和高度是沒有用的。手機網站上背景仍是能夠滑動,而後我給body一個touchmove的preventdefault()阻止事件,body滑動阻止了,PC上面是能夠了,可是手機上面滑動div仍是會致使底部body的滑動,我給div 一個阻止冒泡的事件stopPropagation(),手機網站上面仍是不能夠。

解決方案

我通過反覆測試,發現滾動軸滾到底部的時候,會觸發body的滑動,那麼我就在事件滾到底部的時候對錶層的div作一個touchmove的阻止。到達滾動軸底部,向下滑動,阻止事件,向上滑動,開啓事件。爲此就要判斷touchmove的方向了。

 1 var startX ,startY;
 2 $("body").on("touchstart", function(e) {
 3     e.preventDefault();
 4     startX = e.originalEvent.changedTouches[0].pageX,
 5     startY = e.originalEvent.changedTouches[0].pageY;
 6 });
 7 $("body").on("touchmove", function(e) {
 8     e.preventDefault();
 9     var moveEndX = e.originalEvent.changedTouches[0].pageX,
10     moveEndY = e.originalEvent.changedTouches[0].pageY,
11     X = moveEndX - startX,
12     Y = moveEndY - startY;
13 
14     if ( Math.abs(X) > Math.abs(Y) && X > 0 ) {
15         alert("left 2 right");
16     }
17     else if ( Math.abs(X) > Math.abs(Y) && X < 0 ) {
18         alert("right 2 left");
19     }
20     else if ( Math.abs(Y) > Math.abs(X) && Y > 0) {
21         alert("top 2 bottom");
22     }
23     else if ( Math.abs(Y) > Math.abs(X) && Y < 0 ) {
24         alert("bottom 2 top");
25     }
26     else{
27         alert("just touch");
28     }
29 });
View Code

上面的方法是判斷touchmove的滑動方向。

除了上面方法判斷手機端手機滑動方向,我這裏再介紹一個方案,就是封裝一個角度函數,經過角度函數來判斷也還不錯!我這裏僅僅把這種方式實現上滑下滑左滑右滑列舉一下!

 1 var startx, starty;
 2     //得到角度
 3     function getAngle(angx, angy) {
 4         return Math.atan2(angy, angx) * 180 / Math.PI;
 5     };
 6 
 7     //根據起點終點返回方向 1向上 2向下 3向左 4向右 0未滑動
 8     function getDirection(startx, starty, endx, endy) {
 9         var angx = endx - startx;
10         var angy = endy - starty;
11         var result = 0;
12 
13         //若是滑動距離過短
14         if (Math.abs(angx) < 2 && Math.abs(angy) < 2) {
15             return result;
16         }
17 
18         var angle = getAngle(angx, angy);
19         if (angle >= -135 && angle <= -45) {
20             result = 1;
21         } else if (angle > 45 && angle < 135) {
22             result = 2;
23         } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
24             result = 3;
25         } else if (angle >= -45 && angle <= 45) {
26             result = 4;
27         }
28 
29         return result;
30     }
31     //手指接觸屏幕
32     document.addEventListener("touchstart", function(e) {
33         startx = e.touches[0].pageX;
34         starty = e.touches[0].pageY;
35     }, false);
36     //手指離開屏幕
37     document.addEventListener("touchend", function(e) {
38         var endx, endy;
39         endx = e.changedTouches[0].pageX;
40         endy = e.changedTouches[0].pageY;
41         var direction = getDirection(startx, starty, endx, endy);
42         switch (direction) {
43             case 0:
44                 alert("未滑動!");
45                 break;
46             case 1:
47                 alert("向上!")
48                 break;
49             case 2:
50                 alert("向下!")
51                 break;
52             case 3:
53                 alert("向左!")
54                 break;
55             case 4:
56                 alert("向右!")
57                 break;
58             default:
59         }
60     }, false);
View Code

知道滑動方向如何判斷,那麼解決這個問題咱們能夠判斷是否滑動到底部或者頂部,假如滑動到底部,再往下滑動,就阻止滑動,往上滑動,就開啓滑動!滑動到頂部一個道理!總結代碼以下:

 1     $('#haorooms底層背景').bind("touchmove", function (e) {
 2             e.preventDefault();
 3         });
 4         $(".滾動的父親").bind("touchstart", function (events) {
 5             startY = events.originalEvent.changedTouches[0].pageY;
 6         });
 7         $(".滾動的父親 ul").bind("touchmove", function (e) {
 8             var ulheight = $(this).height();
 9             var scrollTop = $(this).scrollTop();
10             var scrollheight = $(this)[0].scrollHeight;
11             if (ulheight + scrollTop + 20 >= scrollheight) { //滾到底部20px左右
12                 $(".滾動的父親").bind("touchmove", function (event) {
13                     moveEndY = event.originalEvent.changedTouches[0].pageY,
14                             theY = moveEndY - startY;
15                     if (Math.abs(theY) > Math.abs(theX) && theY > 0) { //用上面的abs()更加準確!這裏是判斷上滑仍是下滑!能夠用角度函數也能夠用上面絕對值方式!
16                         $(".滾動的父親").unbind("touchmove");//滑動到底部再往上滑動,解除阻止!
17                     }
18                     if (Math.abs(theY) > Math.abs(theX) && theY < 0) {
19                         event.preventDefault();//滑動到底部,再往下滑動,阻止滑動!
20                     }
21                 })
22             }
23             if (scrollTop < 20) {//滾到頂部20px左右
24                 $(".滾動的父親").bind("touchmove", function (event) {
25                     moveEndY = event.originalEvent.changedTouches[0].pageY,
26                             theY = moveEndY - startY;
27                     if (Math.abs(theY) > Math.abs(theX) && theY > 0) {
28                         event.preventDefault();
29                     }
30                     if (Math.abs(theY) > Math.abs(theX) && theY < 0) {
31                         $(".滾動的父親").unbind("touchmove");
32                     }
33                 })
34             }
35         });
View Code

以上方法基本上可以阻止body的滾動,可是,有時候仍是會有問題,期待更好的解決方案!

張鑫旭的一種解決辦法

下面是張鑫旭的一個解決辦法,這裏簡單的借用一下!

CSS代碼:

.noscroll, .noscroll body { overflow: hidden; } .noscroll body { position: relative; }

js代碼:

 1 $.smartScroll = function(container, selectorScrollable) {
 2     // 若是沒有滾動容器選擇器,或者已經綁定了滾動時間,忽略
 3     if (!selectorScrollable || container.data('isBindScroll')) {
 4         return;
 5     }
 6 
 7     // 是不是搓瀏覽器
 8     // 本身在這裏添加判斷和篩選
 9     var isSBBrowser;
10 
11     var data = {
12         posY: 0,
13         maxscroll: 0
14     };
15 
16     // 事件處理
17     container.on({
18         touchstart: function (event) {
19             var events = event.touches[0] || event;
20 
21             // 先求得是否是滾動元素或者滾動元素的子元素
22             var elTarget = $(event.target);
23 
24             if (!elTarget.length) {
25                 return;    
26             }
27 
28             var elScroll;
29 
30             // 獲取標記的滾動元素,自身或子元素皆可
31             if (elTarget.is(selectorScrollable)) {
32                 elScroll = elTarget;
33             } else if ((elScroll = elTarget.parents(selectorScrollable)).length == 0) {
34                 elScroll = null;
35             }
36 
37             if (!elScroll) {
38                 return;
39             }
40 
41             // 當前滾動元素標記
42             data.elScroll = elScroll;
43 
44             // 垂直位置標記
45             data.posY = events.pageY;
46             data.scrollY = elScroll.scrollTop();
47             // 是否能夠滾動
48             data.maxscroll = elScroll[0].scrollHeight - elScroll[0].clientHeight;
49         },
50         touchmove: function () {
51             // 若是不足於滾動,則禁止觸發整個窗體元素的滾動
52             if (data.maxscroll <= 0 || isSBBrowser) {
53                 // 禁止滾動
54                 event.preventDefault();
55             }
56             // 滾動元素
57             var elScroll = data.elScroll;
58             // 當前的滾動高度
59             var scrollTop = elScroll.scrollTop();
60 
61             // 如今移動的垂直位置,用來判斷是往上移動仍是往下
62             var events = event.touches[0] || event;
63             // 移動距離
64             var distanceY = events.pageY - data.posY;
65 
66             if (isSBBrowser) {
67                 elScroll.scrollTop(data.scrollY - distanceY);
68                 elScroll.trigger('scroll');
69                 return;
70             }
71 
72             // 上下邊緣檢測
73             if (distanceY > 0 && scrollTop == 0) {
74                 // 往上滑,而且到頭
75                 // 禁止滾動的默認行爲
76                 event.preventDefault();
77                 return;
78             }
79 
80             // 下邊緣檢測
81             if (distanceY < 0 && (scrollTop + 1 >= data.maxscroll)) {
82                 // 往下滑,而且到頭
83                 // 禁止滾動的默認行爲
84                 event.preventDefault();
85                 return;
86             }
87         },
88         touchend: function () {
89             data.maxscroll = 0;
90         }    
91     });
92 
93     // 防止屢次重複綁定
94     container.data('isBindScroll', true);
95 };
JS代碼

html以下:

<aside id="aside" class="aside"> <i class="aside-overlay hideAside"></i> <div class="aside-content"> <div class="module module-filter-list"> <div class="module-main scrollable"> <ul id="filters" class="sort-ul"> ....... </ul> </div> </div> </div> </aside>

使用:

$('#aside').addClass('active'); $.smartScroll($('#aside'), '.scrollable'); $('html').addClass('noscroll');

能夠測試一下!

二、假如整個頁面用rem字體,部分安卓瀏覽器出現字體過大的狀況(給父級加個默認的font-size)

三、部分安卓瀏覽器對margin要求比較苛刻(可以使用padding)

相關文章
相關標籤/搜索