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:
Instantly we can see this div called out as "repaints on scroll". You can then verify that in the experimental Layers panel:
(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:
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
How to Clear/Remove JavaScript Event Handler
How to Add a List of Images to the Document from an Array of Urls
Css3 Keyframe Animations: End and Stay on the Last Frame
Changing Visibility Using JavaScript
Apply Multiple Styles with .Style() Method in D3.Js
Removing Legend on Charts with Chart.Js V2
JavaScript - Changing a Class' Style
Changing CSS Variables via Js in Polymer
Remove CSS Rules by JavaScript
Activate an Element's :Active CSS Pseudo-Class Using JavaScript
JavaScript Click Event Listener on Multiple Elements and Get Target Id
Get the Height of an Element Minus Padding, Margin, Border Widths
Capture/Save/Export an Image with CSS Filter Effects Applied
Detect High Contrast Extension Use in Chrome Browser