Turns out that even though I was using transform: translateY()
that you still need to add translateZ(0)
to see the benefit of layers and having it gpu accelerated.
But I did also update my code to use a object literal code style and got rid of the forced synchronous layout
warning in the timeline by reading then writing. This is coupled along with requestAnimationFrame
.
Demo: jsFiddle
var myUtils = {
clamp: function(min, max, value) {
return Math.min(Math.max(value, min), max);
},
getTranslateYFromTransform: function(rawTransform) {
return parseFloat(rawTransform.match(/^matrix\((([+-]?[0-9]*\.?[0-9]*),\s*?){5}([+-]?[0-9]*\.?[0-9]*)\)$/)[3])
}
};
var scrollHeader = {
latestScrollTop: 0,
lastReactedScrollTop: 0,
headerHeight: 0,
headerTransformTranslateY: 0,
ticking: false,
requestTick: function() {
if(!scrollHeader.ticking) {
requestAnimationFrame(function(){
scrollHeader.doHeaderFold();
});
}
scrollHeader.ticking = true;
},
doHeaderFold: function() {
var header = $('header.main-header');
var builtUpScrollTop = scrollHeader.latestScrollTop - scrollHeader.lastReactedScrollTop;
scrollHeader.headerHeight = header.outerHeight();
scrollHeader.headerTransformTranslateY = myUtils.clamp(-parseInt(scrollHeader.headerHeight), 0, (myUtils.getTranslateYFromTransform(header.css('transform')) - builtUpScrollTop));
// Fold the top bar while we are scrolling (lock it to scrolling)
header.css('transform', 'translateY(' + scrollHeader.headerTransformTranslateY + 'px) translateZ(0)');
scrollHeader.headerHeightChange();
scrollHeader.lastReactedScrollTop = scrollHeader.latestScrollTop;
scrollHeader.ticking = false;
},
headerHeightChange: function() {
// We need to update the margin-top for the content so we don't overlap it
$('main.content-area').css('transform', 'translateY(' + (scrollHeader.headerHeight + scrollHeader.headerTransformTranslateY) + 'px) translateZ(0)');
}
};
$(window).on('scroll', function(e) {
//console.log(e);
scrollHeader.latestScrollTop = $(window).scrollTop();
scrollHeader.requestTick();
});
This makes the timeline debugging on ADB (Nexus 7 2013) look like(very smooth):
Also to get rid of a small jump when first scrolling add transform: translateZ(0)
to your element before animating it.