position:sticky的兼容性嘗試


問題

在這里主要介紹下關於css3草案的position:sticky屬性的兼容。

目前前端的h5有個需求,就是“當頁面上的若干個標題被拖動到視口的頂部時,則顯示一個被定位到視口的頂部的tab標簽,可對這個tab標簽進行點擊導航,並在某個特殊的情況下隱藏”。最簡單粗暴的做法就是針對document.body做scroll偵聽,在函數中遍歷所有的標題並計算出getBoundingClientRect計算出距離適口的頂部距離,決定是否顯示tab欄或者活動標簽,但是在這里可能會出現一些性能問題:
+ 在瀏覽器端和安卓設備上,scroll事件連續觸發,如果在偵聽函數中做過於復雜的判斷,肯定會暫時阻塞ui(主)線程的渲染,造成卡頓
+ 每次在偵聽函數中都執行一次getBoundingClientRect函數,都會導致ui線程刷新渲染隊列,進行一次layout和repaint,有可能造成卡頓
+ 在ios設備中,scroll事件在上下滑動的過程中js不會連續執行,只在滑動結束的時刻執行一次,並且不支持左右滑動事件的觸發

針對上述問題進行修復,其實並不困難:
+ 針對scroll做throttle節流,避免每次滑動都執行,可以設置時間間隔,如50ms
+ 在偵聽函數中計算元素的layout屬性,可用setTimeout在定時器隊列尾插入任務,異步渲染
+ ios設備實現了一個屬性-position:sticky,可以不用js來完成粘性布局

深入

針對sticky布局的兼容性,我們很容易兼容大多數移動端瀏覽器。在pc和安卓的chrome中並未實現該屬性,而在pc和iOS 的safari中全部兼容該屬性,因此針對iOS可以單獨使用sticky完成兼容。
sticky布局有着幾個條件:
+ 元素並不會脫離文檔流,當元素被粘在視口的頂部時,原來在文檔流中的位置仍然占據,這點類似relative定位
+ 元素相對於其最近可滾動的祖先元素“粘性定位”,如果其祖先元素都不能滾動,則相對於適口定位
+ 元素最近的祖先元素overflow設置為非默認值visible時,則元素相對於該祖先元素進行sticky定位。若最近的祖先元素設置為overflow:hidden,則元素不會sticky定位
因此解決ios的代碼可以這樣:

// sticky類為粘性布局的樣式設置 if (gtIOS6) { // 大於等於iOS6版本使用sticky $tab.addClass('sticky'); } .sticky { position: -webkit-sticky; position: sticky; top: 0; }

示例代碼:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <title>positionSticky</title>
    <style>
        * {margin: 0;padding: 0;}
        .header {width: 100%;height: 100px;background: red;}
        .container {width: 100%;height: 1000px;background: #ccc;}
        .liveDiv {top: 0;width: 100%;height: 50px;background: green;}
        .sticky {position: -webkit-sticky;position: -moz-sticky;position: -ms-sticky;position: -o-sticky;position: sticky;}
        .scale {transform: scale(0.5);transform-origin: 0% 0%;}
    </style>
    <script src="http://apps.bdimg.com/libs/jquery/1.11.3/jquery.js"></script>
</head>
<body>
<div class="header"></div>
<div class="container">
    <div class="liveDiv"></div>
</div>  
<script>
/*
 * 菜單移動到頂部后定位在頂部
 * message[菜單的id名或者class類名]
 * height[菜單距離頂部的距離]
 */
function navChangeArea(message, height) {
    var liveDiv = $("#" + message).length ? $("#" + message) : $("." + message);
    if(/android/i.test(navigator.userAgent)){
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        if (scrollTop < height) {
            liveDiv.css("position", "relative");
        } else {
            liveDiv.css("position", "fixed");
        }
    }
    if(/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){
        liveDiv.addClass("sticky");
    }
}
$(window).bind("scroll", function() {
    navChangeArea("liveDiv", 100);
});
$(window).bind("touchmove", function() {
    navChangeArea("liveDiv", 100);
});
</script> 
</body>
</html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM