简体   繁体   中英

How to get rid of flicker during scrolling for artificially fixed elements?

This is a very simple example of sticking an element at the top of another element's visible area. When .container is scrolled, .fixed stays at the top.

<div class="container">
    <div class="fixed">fixed content</div>
    <div class="content">regular content<br/>regular content<br/>regular content<br/>regular content<br/>regular content</div>
</div>

<style type="text/css">
.container {
    position: relative;
    border: 1px solid blue;
    overflow: auto;
    width: 250px;
    height: 250px;
}
.content {
    height: 500px;
    width: 500px;
}
.fixed {
    position: absolute;
    width: 500px;
    margin-top: 2rem;
    border 1px solid red;
}
</style>

<script type="text/javascript">
    $('.container').scroll(function () {
        var top = $('.container').prop('scrollTop');
        console.log(top);
        $('.fixed').css('top', top);
    });
</script>

The problem with this is that if the browser is not fast enough, the .fixed element flickers when I scroll. It lags behind the scroll (compare the position of the text in .fixed to the text in .content as you're scrolling). On my desktop it works flawlessly, but when I try running this in Chromium in a virtual machine, I can see the flicker.

Is there any other way to catch the scroll event and set the position of my .fixed element before the browser renders the page?

edit Updated example to include horizontal scrolling. The fixed element should only be fixed vertically.

Use a double container:

<div class="container-wrapper">
    <div class="fixed">fixed content</div>
    <div class="container">
        <div class="content">regular content<br/>regular content<br/>regular content<br/>regular content<br/>regular content</div>
    </div>
</div>

With the CSS:

.container-wrapper {
    position: relative;
    border: 1px solid blue;
    overflow: hidden;
    width: 250px;
    height: 250px;
}
.container {
    overflow: auto;
    width: 100%;
    height: 100%;
}
.content {
    height: 500px;
}
.fixed {
    position: absolute;
    top: 0px;
    left: 0px;
    width: 245px;
    border 1px solid red;
    z-index: 10;
}

This way you won't need jQuery to reposition the .fixed div when you scroll, and it won't flicker.

EDIT To address the horizontal scrolling...

$('.container').on('scroll', function() {
    var left = this.scrollLeft;
    $('.fixed').css('left', -left + 'px');
});

This should move the .fixed div without flickering. In your solution, the flickering was caused because the browser moved your div while scrolling, and the event handler then moved it again. Now it will only move once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM