How to Do Anything About "Repaints on Scroll" Warning in Chrome for "Overflow:Scroll" Div

Can I do anything about repaints on scroll warning in Chrome for overflow:scroll div

You can apply this CSS on the div with overflow: scroll or overflow: auto that create scroll bottlenecks.

transform: translateZ(0);
-webkit-transform: translateZ(0);

That will force the browser to create a new layer to paint this element, and sometimes fix scroll bottlenecks (especially with Webkit).

Reducing scroll jank when using overflow-y: scroll;

I tried out your test page and took a look.

First, with scrolling perf issues I like flipping on a few of the checkboxes in the Rendering pane:

Sample Image

Instantly we can see this div called out as "repaints on scroll". You can then verify that in the experimental Layers panel:

Sample Image

(I right-clicked in the tree and selected "Show internal layers" btw)

Now large "update layer tree" costs are usually caused by LOTS of layers or a few layers that are very large in dimensions. In this case we really have neither. But we do have a scrolling layer that's not getting composited scrolling.

Composited scrolling == fast scrolling == usually the default. But in cases like this we fall back to "main thread scrolling" which is really slow and sucky. On the plus side, crbug.com/381840 is just about to be fixed which should fix this test case automatically. Yay! But we can work around it for now.

The workaround

You did mention you tried will-change and it didn't have an effect, but trying it myself has worked out great. It belongs on the element that has overflow set, in this case its the .map-search__results selector. Add will-change: transform;. Once added, the "repaints on scroll" rect is gone. And measuring with timeline afterwards and it's MUCH better.

Here's a before/after view:


Sample Image
link to viewer

Good luck!

How can I make Chrome scroll to a section including an auto scrolling div?

In finally came up with a solution. It involves scrolling the page manually via jQuery similar to the answer provided here: Anchor <a> tags not working in chrome when using #

$(function() {
$(window).on('hashchange', function () {
let target = $(location.hash);
if (target.length) {
$('body')[0].scrollTop = target.offset().top;
}
});
setTimeout(function () {$(window).trigger('hashchange')}, 150);
});

IFrame scrollbar disappears on chrome when visibility changes

It seems that bug appeared with the update Chrome 52.0.2743.82 (http://googlechromereleases.blogspot.fr/2016/07/stable-channel-update.html)

One possible workaround is to use the attribute visibility with position: absolute instead of display to show or hide the iframe.

A chrome bug ticket exists for this item: https://bugs.chromium.org/p/chromium/issues/detail?id=641881

Choppy/Laggy scroll event on Chrome and IE

Since JavaScript runs in the same thread as the UI, a scroll event callback can block the UI-thread and thus cause lag. You need to throttle the scroll event listener because some browsers fire a lot of them. Especially if you're on OS X with an analog scroll device. Since you do a lot of height calculations in your listener, it will trigger a reflow (very expensive) for every scroll event that is fired.

To throttle the listener, you have to prevent the listener from firing every time. Usually you wait until the browser doesn't trigger an event for x milliseconds, or have a minimum time between calling your callback. Try adjusting the value to see the effect. Even 0 milliseconds can help, since it will delay the execution of the callback until the browser has time (usually 5-40 ms).

It's also a good practice to toggle a class to switch between states (static and fixed position) instead of hard-coding it in JavaScript. Then you have a cleaner separation of concerns and avoid potential extra redraws by mistake (see "Browsers are smart" section). (example on jsfiddle)

Wait for a pause of x ms

// return a throttled function
function waitForPause(ms, callback) {
var timer;

return function() {
var self = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
callback.apply(self, args);
}, ms);
};
}

this.start = function() {
// wrap around your callback
$window.scroll( waitForPause( 30, self.worker ) );
};

Wait at least x ms (jsfiddle)

function throttle(ms, callback) {
var timer, lastCall=0;

return function() {
var now = new Date().getTime(),
diff = now - lastCall;
console.log(diff, now, lastCall);
if (diff >= ms) {
console.log("Call callback!");
lastCall = now;
callback.apply(this, arguments);
}
};
}

this.start = function() {
// wrap around your callback
$window.scroll(throttle(30, self.worker));
};

jQuery Waypoints
Since you're already using jQuery, I would have a look at the jQuery Waypoints plugin which has a simple and elegant solution to your problem. Just define a callback when the user scrolls to a certain waypoint.

Example: (jsfiddle)

$(document).ready(function() {
// throttling is built in, just define ms
$.waypoints.settings.scrollThrottle = 30;

$('#content').waypoint(function(event, direction) {
$(this).toggleClass('sticky', direction === "down");
event.stopPropagation();
}, {
offset: 'bottom-in-view' // checkpoint at bottom of #content
});
});


Related Topics



Leave a reply



Submit