五月综合缴情婷婷六月,色94色欧美sute亚洲线路二,日韩制服国产精品一区,色噜噜一区二区三区,香港三级午夜理伦三级三

您現(xiàn)在的位置: 365建站網(wǎng) > 365文章 > Web移動端Fixed固定布局bug

Web移動端Fixed固定布局bug

文章來源:365jz.com     點擊數(shù):1149    更新時間:2020-11-14 18:38   參與評論

Web移動端Fixed固定布局bug:移動端使用固定定位會出現(xiàn)很多莫名其妙的問題,特別是在ios上,當(dāng)軟鍵盤喚起時,fixed元素被擠到屏幕中央,導(dǎo)致布局錯亂的想象。

特別是最新的ios11的系統(tǒng),會出現(xiàn)fixed兼容的問題。

1、fixed在某些情況下可能導(dǎo)致容器內(nèi)的子元素的1px邊框線消失,即使使用z-index也無法解決。
解決方法:可以使用translateZ屬性來解決
2、fixed定位的容器內(nèi)不能帶有input,這是常見的bug。
解決方法: 在input聚焦的時候去掉fixed定位狀態(tài),改為absolute,絕對定位 然后通過JS 跟著屏幕滾動而滾動 達到固定定位的效果。
3、fixed+可滾動的容器內(nèi)會導(dǎo)致fixed定位的子元素在滾動時定位失效,滾動完成后才正?;氐絝ixed的位置。
解決方法:盡量不要在可滾動的容器內(nèi)包含fixed定位的子元素。
4、ios不支持onresize事件

PC端項目:

父級設(shè)置了transform: translate(0, 0);后,子級的固定定位會失效:

(解決辦法,去除父級的transform: translate(0, 0); 即可)

html:

 <div class="guding">
        <div class="fixed-box"></div>
  </div>
.guding{
            // transform: translate(0, 0);//這行代碼一旦打開,.fixed-box中設(shè)置的固定定位將失效。
        }
//固定定位
.fixed-box{
    position: fixed;//固定定位,常用作浮動的導(dǎo)航
    width: 100px;
    height: 100px;
    background-color: lightgreen;
    z-index: 1;//可以結(jié)合z-index提升層級
}

手機端項目:

只要父元素的 -webkit-overflow-scrolling 屬性值為 touch,子元素的 position: fixed 屬性就無效。:

css:

-webkit-overflow-scrolling: touch; /* 當(dāng)手指從觸摸屏上移開,會保持一段時間的滾動 */
 
-webkit-overflow-scrolling: auto; /* 當(dāng)手指從觸摸屏上移開,滾動會立即停止 */


解決方案

解決方案不是很優(yōu)雅,因為項目本身已經(jīng)比較穩(wěn)定,影響頁面眾多,只能暫時針對 iPhone X 進行修復(fù)。


當(dāng)動態(tài)向頁面增加 fixed 蒙層時,將主要內(nèi)容節(jié)點(一個很長的容器)改成position: absolute,計算內(nèi)容的scrollTop,作為marginTop賦值給它,以此實現(xiàn)用戶基本無感知后面的內(nèi)容頁面被改動了(實際上在不同 webview 內(nèi)會有不同程度的一個閃爍)。


更好的解決方案

更好的解決方案,即是如標(biāo)題所述,盡量避免在移動端開發(fā)中使用position: fixed,而是更多使用更現(xiàn)代的布局方式和position: absolute來實現(xiàn)類似需求。


iOS下的 Fixed + Input BUG現(xiàn)象

讓我們先舉個栗子,最直觀的說明一下這個 BUG 的現(xiàn)象。 常規(guī)的 fixed 布局,可能使用如下布局(以下僅示意代碼):

<body class="layout-fixed">
   <!-- fixed定位的頭部 -->
   <header>
       
   </header>
   
   <!-- 可以滾動的區(qū)域 -->
   <main>
       <!-- 內(nèi)容在這里... -->
   </main>
   
   <!-- fixed定位的底部 -->
   <footer>
       <input type="text" placeholder="Footer..."/>
       <button class="submit">提交</button>
   </footer>
</body>

對應(yīng)的樣式如下:

header, footer, main {
   display: block;
}

header {
   position: fixed;
   height: 50px;
   left: 0;
   right: 0;
   top: 0;
}

footer {
   position: fixed;
   height: 34px;
   left: 0;
   right: 0;
   bottom: 0;
}

main {
   margin-top: 50px;
   margin-bottom: 34px;
   height: 2000px
}

然后看起來就是下面這個樣子。拖動頁面時 header 和 footer 已經(jīng)定位在了對應(yīng)的位置,目測沒問題了。

fixed定位

fixed定位

但接下來問題就來了!如果底部輸入框軟鍵盤被喚起以后,再次滑動頁面,就會看到如下圖所示:

fixed定位 fixed定位

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

這是為什么呢?簡單解釋下: > 軟鍵盤喚起后,頁面的 fixed 元素將失效(即無法浮動,也可以理解為變成了 absolute 定位),所以當(dāng)頁面超過一屏且滾動時,失效的 fixed 元素就會跟隨滾動了。

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


雖然 isScroll.js 可以很好的解決 fixed 定位滾動的問題,但是不在萬不得已的情況下,我們盡量嘗試一下不依賴第三方庫的布局方案,以簡化實現(xiàn)方式。這里拋磚引玉作為參考。

解決思路:

既然在 iOS 下由于軟鍵盤喚出后,頁面 fixed 元素會失效,導(dǎo)致跟隨頁面一起滾動,那么假如——頁面不會過長出現(xiàn)滾動,那么即便 fixed 元素失效,也無法跟隨頁面滾動,也就不會出現(xiàn)上面的問題了。

那么按照這個思路,如果使 fixed 元素的父級不出現(xiàn)滾動,而將原 body 滾動的區(qū)域域移到 main 內(nèi)部,而 header 和 footer 的樣式不變,代碼如下:

<body class="layout-scroll-fixed">
   <!-- fixed定位的頭部 -->
   <header>
       
   </header>
   
   <!-- 可以滾動的區(qū)域 -->
   <main>
       <div class="content">
       <!-- 內(nèi)容在這里... -->
       </div>
   </main>
   
   <!-- fixed定位的底部 -->
   <footer>
       <input type="text" placeholder="Footer..."/>
       <button class="submit">提交</button>
   </footer>
</body>
header, footer, main {
   display: block;
}

header {
   position: fixed;
   height: 50px;
   left: 0;
   right: 0;
   top: 0;
}

footer {
   position: fixed;
   height: 34px;
   left: 0;
   right: 0;
   bottom: 0;
}

main {
   /* main絕對定位,進行內(nèi)部滾動 */
   position: absolute;
   top: 50px;
   bottom: 34px;
   /* 使之可以滾動 */
   overflow-y: scroll;
}

main .content {
   height: 2000px;
}

這樣再來看一下:

fixed定位

fixed定位

在原始輸入法下, fixed 元素可以定位在頁面的正確位置。滾動頁面時,由于滾動的是 main 內(nèi)部的 div,因此 footer 沒有跟隨頁面滾動。

上面貌似解決了問題,但是如果在手機上實際測試一下,會發(fā)現(xiàn) main 元素內(nèi)的滾動非常不流暢,滑動的手指松開后,滾動立刻停止,失去了原本的流暢滾動特性。百度一下彈性滾動的問題,發(fā)現(xiàn)在 webkit 中,下面的屬性可以恢復(fù)彈性滾動。

-webkit-overflow-scrolling: touch;

在 main 元素上加上該屬性,嗯,絲般順滑的感覺又回來了!

main {
   /* main絕對定位,進行內(nèi)部滾動 */
   position: absolute;
   top: 50px;
   bottom: 34px;
   /* 使之可以滾動 */
   overflow-y: scroll;
   /* 增加該屬性,可以增加彈性 */
   -webkit-overflow-scrolling: touch;
}

另外,這里的 header 和 footer 使用的是 fixed 定位,如果考慮到更老一些的 iOS 系統(tǒng)不支持 fixed 元素,完全可以把 fixed 替換成 absolute 。測試后效果是一樣的。

至此一個不依賴第三方庫的 fixed 布局就完成了。


Android 下布局

談到了 iOS ,也來簡單說一下 Android 下的布局吧。

在 Android2.3+ 中,因為不支持 overflow-scrolling ,因此部分瀏覽器內(nèi)滾動會有不流暢的卡頓。但是目前發(fā)現(xiàn)在 body 上的滾動還是很流暢的,因此使用第一種在 iOS 出現(xiàn)問題的 fixed 定位的布局就可以了。

如果需要考慮 Android2.3 以下系統(tǒng),因為不支持 fixed 元素,所以依然要需要考慮使用 isScroll.js 來實現(xiàn)內(nèi)部滾動。

其實在 fixed 和輸入框的問題上,基本思路就是: > 由于 fixed 在軟鍵盤喚起后會失效,導(dǎo)致在頁面可以滾動時,會跟隨頁面一起滾動。因此如果頁面無法滾動,那么 fixed 元素即使失效,也不會滾動,也就不會出現(xiàn) bug 了。

所以可以在這個方面去考慮解決問題。


其他的一些細節(jié)處理

在細節(jié)處理上,其實還有很多要注意的,挑幾個實際遇到比較大的問題來說一下:

  1. 有時候輸入框 focus 以后,會出現(xiàn)軟鍵盤遮擋輸入框的情況,這時候可以嘗試 input 元素的 scrollIntoView 進行修復(fù)。

  2. 在 iOS 下使用第三方輸入法時,輸入法在喚起經(jīng)常會蓋住輸入框,只有在輸入了一條文字后,輸入框才會浮出。目前也不知道有什么好的辦法能讓喚起輸入框時正確顯示。這暫時算是 iOS 下的一個坑吧。

  3. 有些第三方瀏覽器底部的工具欄是浮在頁面之上的,因此底部 fixed 定位會被工具欄遮擋。解決辦法也比較簡單粗暴——適配不同的瀏覽器,調(diào)整 fixed 元素距離底部的距離。

  4. 最好將 header 和 footer 元素的 touchmove 事件禁止,以防止?jié)L動在上面觸發(fā)了部分瀏覽器全屏模式切換,而導(dǎo)致頂部地址欄和底部工具欄遮擋住 header 和 footer 元素。

  5. 在頁面滾動到上下邊緣的時候,如果繼續(xù)拖拽會將整個 View 一起拖拽走,導(dǎo)致頁面的"露底"。

    fixed定位

    fixed定位

為了防止頁面露底,可以在頁面拖拽到邊緣的時候,通過判斷拖拽方向以及是否為邊緣來阻止 touchmove 事件,防止頁面繼續(xù)拖拽。

以上面內(nèi)滾動 layout-scroll-fixed 布局為例,給出一段代碼作為參考:

// 防止內(nèi)容區(qū)域滾到底后引起頁面整體的滾動
var content = document.querySelector('main');
var startY;

content.addEventListener('touchstart', function (e) {
   startY = e.touches[0].clientY;
});

content.addEventListener('touchmove', function (e) {
   // 高位表示向上滾動
   // 底位表示向下滾動
   // 1容許 0禁止
   var status = '11';
   var ele = this;

   var currentY = e.touches[0].clientY;

   if (ele.scrollTop === 0) {
       // 如果內(nèi)容小于容器則同時禁止上下滾動
       status = ele.offsetHeight >= ele.scrollHeight ? '00' : '01';
   } else if (ele.scrollTop + ele.offsetHeight >= ele.scrollHeight) {
       // 已經(jīng)滾到底部了只能向上滾動
       status = '10';
   }

   if (status != '11') {
       // 判斷當(dāng)前的滾動方向
       var direction = currentY - startY > 0 ? '10' : '01';
       // 操作方向和當(dāng)前允許狀態(tài)求與運算,運算結(jié)果為0,就說明不允許該方向滾動,則禁止默認(rèn)事件,阻止?jié)L動
       if (!(parseInt(status, 2) & parseInt(direction, 2))) {
           stopEvent(e);
       }
   }
});



如對本文有疑問,請?zhí)峤坏浇涣髡搲瑥V大熱心網(wǎng)友會為你解答??! 點擊進入論壇

發(fā)表評論 (1149人查看0條評論)
請自覺遵守互聯(lián)網(wǎng)相關(guān)的政策法規(guī),嚴(yán)禁發(fā)布色情、暴力、反動的言論。
昵稱:
最新評論
------分隔線----------------------------

其它欄目

· 建站教程
· 365學(xué)習(xí)

業(yè)務(wù)咨詢

· 技術(shù)支持
· 服務(wù)時間:9:00-18:00
365建站網(wǎng)二維碼

Powered by 365建站網(wǎng) RSS地圖 HTML地圖

copyright © 2013-2024 版權(quán)所有 鄂ICP備17013400號