轉載:深入研究-webkit-overflow-scrolling:touch及ios滾動

深入研究-webkit-overflow-scrolling:touch及ios滾動
原文章鏈接:https://www.cnblogs.com/xiahj/p/8036419.html
目錄

  1. -webkit-overflow-scrolling:touch是什麼?
  2. 解決safari佈局抖動的例子
    2.1 方案一
    2.2 方案二
  3. 探究-webkit-overflow-scrolling:touch偶爾卡住或不能滑動的bug
    3.1 保證使用了該屬性的元素上沒有設置定位
    3.2 如果添加動態內容頁面不能滾動,讓子元素height+1
    3.3 爲什麼會有卡住不動的這個bug
  4. -webkit-overflow-scrolling:touch的其他坑
    最後的吐槽

一. -webkit-overflow-scrolling:touch是什麼? MDN上是這樣定義的:

-webkit-overflow-scrolling 屬性控制元素在移動設備上是否使用滾動回彈效果.
auto: 使用普通滾動, 當手指從觸摸屏上移開,滾動會立即停止。
touch: 使用具有回彈效果的滾動, 當手指從觸摸屏上移開,內容會繼續保持一段時間的滾動效果。繼續滾動的速度和持續的時間和滾動手勢的強烈程度成正比。同時也會創建一個新的堆棧上下文。

在移動端上,在你用overflow-y:scorll屬性的時候,你會發現滾動的效果很木,很慢,這時候可以使用-webkit-overflow-scrolling:touch這個屬性,讓滾動條產生滾動回彈的效果,就像ios原生的滾動條一樣流暢。

2. 解決safari佈局抖動的例子

在這裏插入圖片描述
想實現一個佈局爲header、main、bottom的佈局,其中頭部和底部通過fixed固定,中間部分通過滾動條滑動。

如果目的是實現只要中間的內容超過屏幕高度時,中間內容會自動滾動的效果的話,main部分加上上下的padding,然後不需要自己添加任何滾動條屬性,當超出高度時,body會自動產生滾動條。這樣我們的目的其實是實現了的。

但是在safari上,當超出高度,頁面往下滑時,瀏覽器底部的工具欄會隨着頁面一起晃動(向下滾動時會拉起底部工具欄),造成了很不好的體驗。所以我們想在中間的main部分加一個獨立的滾動條。

2.1 方案一
在main上使用fixed定位,加上overflow-y屬性。

.main {
    position: fixed;
    top: 50px;
    bottom: 50px;
    overflow-y: scroll;
}

不過不推薦這個fixed方案,因爲頁面偶爾卡住不動,下面說到了這個問題。

2.2 方案二
中間的main不設定位,高度100%,再padding頭部和尾部,

其中頭部和底部的定位設爲absolute會比設爲fixed體驗更好(況且fix佈局在移動端本來就有各種各樣的問題,還是儘量避開:) )。

大致代碼如下,仍是 overflow-y 和-webkit-overflow-scrolling,重點在於中間部分依照文本流佈局。

  html, body {
   height: 100%;
  }
  main {
      padding: 50px 0;
      height: 100%;
      overflow-y: scroll;
      -webkit-overflow-scrolling: touch;
  }
  1. 探究-webkit-overflow-scrolling:touch偶爾卡住或不能滑動的bug
    -webkit-overflow-scrolling:touch這個屬性真的是各種坑,我研究這個屬性已經大半年了,還沒有發現能夠在safari上完美使用無bug的例子。

最常見的例子就是,

在safari上,使用了-webkit-overflow-scrolling:touch之後,頁面偶爾會卡住不動。
在safari上,點擊其他區域,再在滾動區域滑動,滾動條無法滾動的bug。
通過動態添加內容撐開容器,結果根本不能滑動的bug。
在網上也看到了一些人在問這個問題,不過不多,國外倒是討論的更多一點,描述如下。

在這裏插入圖片描述

偶爾卡住的問題,解決方案網上衆說紛紜,遇到了很多相同的說法,比如如果卡住不動的話,就加一個z-index,就能解決該問題的說法。

在試了很多次之後,這種說法沒有一次解決過這個問題。這個說法能夠傳播出來,可能是使用者當時在使用的時候遇到了-webkit-overflow-scrolling:touch點透或者層級的問題。所以該方案不具有適用性。

所以這個東西真的讓我很苦惱了很久,以致於那段時間所有的滾動條不是通過body自己滾動,就是使用iScroll這樣的庫,繁瑣地讓我幾乎想要放棄移動web,擁抱hybrid,不過在stackoverflow潛水了很久之後,總結了以下幾種解決方案:

3.1 保證使用了該屬性的元素上沒有設置定位
如果出現偶爾卡住不動的情況,那麼在使用該屬性的元素上不設置定位或者手動設置定位爲static

position: static

這樣會解決部分因爲定位(relative、fixed、absolute)導致的頁面偶爾不能滾動的bug。

但是滑動到頂部繼續手指往下滑,或者到底部繼續往上滑,還是會觸發卡住的問題(其實是整個頁面上下回彈),說他算bug,其實就是ios8以上的特性,如果滾動區域大一點,用戶不會覺得這是bug,如果小了,用戶會不知道發生了什麼而卡住了。
視頻在這,有梯子的同學可以看一看https://www.youtube.com/watch?v=MkAVYbO_joo。

3.2 如果添加動態內容頁面不能滾動,讓子元素height+1
如果在-webkit-overflow-scrolling:touch屬性的元素上,想通過動態添加內容來撐開容器,觸發滾動,是有bug 的,頁面是會卡住不動的。

國內沒有人討論這個問題,國外倒是很多,例如下面的描述:
在這裏插入圖片描述

收集了很多資料,用了之後,下面的方法真正的解決了我的問題,真是直呼神奇,方案如下圖:

圖一:

在這裏插入圖片描述

圖二:
在這裏插入圖片描述

方法就是在webkit-overflow-scrolling:touch屬性的下一層子元素上,將height加1%或1px。從而主動觸發scrollbar。

main-inner {
    min-height: calc(100% + 1px)
}

你也可以直接加僞元素上:

main:after {
    min-height: calc(100% + 1px)
}

這個方案不得不說真的好用。。

當然還有其他方案,不過要寫js或者jq了,麻煩。

3.3 爲什麼會有卡住不動的這個bug
這個bug產生於ios8以上(不十分肯定,但在ios5~7上需要手動使用translateZ(0)打開硬件加速)

Safari對於overflow-scrolling用了原生控件來實現。對於有-webkit-overflow-scrolling的網頁,會創建一個UIScrollView,提供子layer給渲染模塊使用。

我想說作爲一個苦逼的前端只能解決到這了。

  1. -webkit-overflow-scrolling:touch的其他坑
    除此之外,這個屬性還有很多bug,包括且不限於以下幾種:

滾動中 scrollTop 屬性不會變化
手勢可穿過其他元素觸發元素滾動
滾動時暫停其他 transition
最後的吐槽
想寫這個文章很久了, 本來以爲就我有這個問題,結果看到網站上也有很多人在用這個屬性,我用safari試了下,都能觸發不能滑動的問題,但是網上的文章又很少,不知道大家是不是就視而不見了。

所以目前來看,如果不想那麼費心,直接上iScroll或者better-scroll吧,我覺得better-scroll還是挺好用的。如果你喜歡偷懶,那麼接着用-webkit-overflow-scrolling:touch也沒什麼問題。

畢竟移動端的水太深了,你永遠不知道下一個問題是發生在safari還是x5內核瀏覽器上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章