• 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>
  • 相关阅读:
    asp.net自动将页面中的所有空间置为不可用以及将所有文本框置空
    在<img src="..." title="..."> 中使title的内容换行的方法
    div 遮罩层 弹窗
    Asp.net工作流workflow实战之工作流持久化(五)
    Asp.net工作流workflow实战之给书签命名(四)
    Asp.net工作流workflow实战之工作流启动与继续(三)
    被废弃的 Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit
    JAVA核心:内存、比较和Final
    redis AOF保存机制
    JAVA CAS原理浅谈
  • 原文地址:https://www.cnblogs.com/gopark/p/9056565.html
Copyright © 2020-2023  润新知