Getting a sticky header to “push up”, like in Instagram's iPhone app using CSS and jQuery

前端 未结 8 1373
[愿得一人]
[愿得一人] 2020-11-30 16:12

The Instagram app has a nice sticky header that pushes the current one up in place of the new one. I found a great tutorial on how to do this natively for Android, but I\'m

8条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-30 16:58

    First off, thanks to @Chris Spittles for his excellent answer.

    I've created a modified version that removes the need to wrap each sticky element, as it simply changes their relative position instead of using fixed positioning.

    var stickyHeaders = (function() {
    
        var $stickies;
    
        var load = function(stickies, target) {
    
            if (typeof stickies === "object" && stickies instanceof jQuery && stickies.length > 0) {
    
                $stickies = stickies.each(function() {
    
                    var $thisSticky = $(this);
    
                    $thisSticky
                        .data('originalPosition', $thisSticky.offset().top)
                        .data('originalHeight', $thisSticky.outerHeight());               
                });
    
                target.off("scroll.stickies").on("scroll.stickies", function(event) {
                     _whenScrolling(event);     
                });
            }
        };
    
        var _whenScrolling = function(event) {
    
            var $scrollTop = $(event.currentTarget).scrollTop();
    
            $stickies.each(function(i) {            
    
                var $thisSticky = $(this),
                    $stickyPosition = $thisSticky.data('originalPosition'),
                    $newPosition,
                    $nextSticky;
    
                if ($stickyPosition <= $scrollTop) {
    
                    $newPosition = Math.max(0, $scrollTop - $stickyPosition);
                    $nextSticky = $stickies.eq(i + 1);
    
                    if($nextSticky.length > 0) {
    
                        $newPosition = Math.min($newPosition, ($nextSticky.data('originalPosition') -  $stickyPosition) - $thisSticky.data('originalHeight'));
                    }
    
                } else {
    
                    $newPosition = 0;
                }
    
                $thisSticky.css('transform', 'translateY(' + $newPosition + 'px)');
    
                //could just as easily use top instead of transform
                //$thisSticky.css('top', $newPosition + 'px');
            });
        };
    
        return {
            load: load
        };
    })();
    
    $(function() {
        stickyHeaders.load($(".followMeBar"), $(window));
    });
    

    The css is simplified to:

    .followMeBar {
        background: #999;
        padding: 10px 20px;
        position: relative;
        z-index: 1;
        color: #fff;
    }
    
    /* For aesthetics only */
    
    body {
        margin: 0;
        font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
    }
    

    http://plnkr.co/edit/wk3h40LfBdN1UFtDLZgY?p=preview

    And here's another example showing how you can have an offset when using a fixed header:

    http://plnkr.co/edit/8YBqdCIKruVKYRXbZnCp?p=preview

提交回复
热议问题