Reputation: 456
I'm trying to create an effect where a div in a list within a certain area of the page will become larger, without flickering upon crossing the transition point (prominent problem in Chrome, maybe other browsers as well).
Here's a jsfiddle of my current situation.
I've pretty much accomplished what I need, thanks to a great jsfiddle contribution here on Stackoverflow – but when I add my own scale effect it kind of flickers if you scroll too slow over the transition border. This is obviously because the scale transition (or normal height/width change) causes the shrink back inside the border once it has already passed the transition point, and vice versa of course.
Is there a method of making this work with a CSS method, or do I need to alter the script – and in that case (since I'm not that familiar with this kind of math equations) how?
$(document).ready(function () {
$(window).on('scroll', function () {
var windowHeight = $(window).height(),
gridTop = windowHeight * .3,
gridBottom = windowHeight * .6;
$('ul li').each(function () {
var thisTop = $(this).offset().top - $(window).scrollTop();
if (thisTop > gridTop && (thisTop + $(this).height()) < gridBottom) {
// $(this).css('background', 'red');
$(this).addClass('in_zone');
} else {
//$(this).css('background', 'silver');
$(this).removeClass('in_zone');
}
});
});
$(window).trigger('scroll');
});
Upvotes: 2
Views: 247
Reputation: 337580
The issue is due to your check of the bottom of the element being outside the bottom of the area. When the element is enlarged, the next time scroll
fires it will revert back to the smaller state as the bottom of the element is outside the area. Then next scroll it will be made large again as the smaller element is now wholly inside the area, and so on.
To fix this you would need to only base the check on the top of the element being within the area, like this:
if (thisTop > gridTop && thisTop < gridBottom) {
$(this).addClass('in_zone');
} else {
$(this).removeClass('in_zone');
}
// Note that you can also re-write this logic with a single call to `toggleClass()`:
$(this).toggleClass('in_zone', thisTop > gridTop && thisTop < gridBottom);
You would also need to ensure that the CSS scaling origin point is at the top of the element, so that the top
position is a static value. You can do that using transform-origin
(and it's vendor prefix equivalents):
transform-origin: 50% 0%;
Or alternatively, you would need to make the 'large' state smaller, or the hit area taller, but that would suffer from the same issue when the elements are near the boundaries of the detection area.
Upvotes: 4