滚动事件侦听器+位置:更改高度的粘性元素会导致抖动无限滚动

时间:2019-02-28 17:17:39

标签: javascript css css3 addeventlistener sticky

我在屏幕顶部有一个position:sticky;元素和一个JS滚动事件监听器,用于在该元素被卡住(滚动Y大于0)时添加一个stuck类。

stuck在粘滞元素内部制作一个元素(具有CSS过渡)以减小高度。

当滚动速度非常慢时,高度的这种变化会使scrollY跳回零并删除stuck类,这将创建一个无限循环的jolty滚动循环,直到您更快地滚动并解决问题为止。 / p>

使用position: sticky时如何使它平滑,您可以在此处看到它:

https://jsfiddle.net/27rzba5v/

1 个答案:

答案 0 :(得分:2)

之所以发生这种情况,是因为您正在更改元素的高度,这会影响盒子模型,从而影响文档的尺寸。一个简单的解决方法是改为在.wrap上使用转换,而不是转换其高度。最好对变形和不透明度进行动画处理,因为它可以handled by the GPU而不是making the browser repaint

var lastScrollY = 0;
var ticking = false;

window.addEventListener('scroll', function(e) {
	lastScrollY = window.scrollY;
	if ( ! ticking ) {
		window.requestAnimationFrame(function() {
			console.log( lastScrollY );
			if ( lastScrollY > 0 ) {
				document.body.classList.add('stuck');
			} else {
				document.body.classList.remove('stuck');
			}
			ticking = false;
		});
		ticking = true;
	}
} );
body {
	margin: 0;
}
.wrap {
	background: #666;
	text-align: center;
	position: sticky;
	top: 0;
  transition: 0.5s; /* Move transition here */
  transform-origin: top left; /* Make sure transition happens from the top left */
}
.block {
	width: 80px;
	height: 80px;
	background: red;
	display: block;
}
.stuck .wrap { /* Transform wrap instead of block */
	transform: scaleY(.5); /* Change scale instead of height */
}
<div class="wrap">
	<span class="block"></span>
</div>

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque ac lorem a metus tincidunt eleifend id in odio. Nam malesuada hendrerit tristique. Pellentesque id ornare elit, ac lobortis metus. Sed iaculis et nisi et consectetur. Proin pellentesque metus mi, quis fringilla mauris pulvinar et. Vivamus pharetra elit ligula, eu consectetur magna consequat nec. Donec sed enim sit amet augue malesuada varius id a libero. Nullam nec ante id justo elementum congue quis in purus. Integer finibus cursus volutpat. Donec non laoreet ipsum.

Maecenas id venenatis velit, eu feugiat dolor. Vestibulum malesuada erat ut turpis mattis vehicula. Vestibulum sem leo, cursus quis lacinia eu, tincidunt eu velit. Nulla odio elit, tristique vel bibendum vitae, placerat nec eros. Proin auctor id leo sed rutrum. Proin convallis erat sit amet neque aliquam vestibulum. Ut sodales vel nisl eu imperdiet.

Donec a porttitor dui, vitae ullamcorper nibh. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam non elit eu elit blandit hendrerit id ut eros. Duis sagittis elementum ligula eu venenatis. Aenean nunc mauris, dignissim ut venenatis ac, pharetra eget magna. Curabitur elementum enim sed pharetra rhoncus. Praesent sodales at ex at consectetur. Curabitur sed dictum mi, ut eleifend arcu. Nam feugiat risus quis congue porttitor. Maecenas vehicula lorem ultrices ante sollicitudin, placerat sollicitudin dolor fermentum. Aliquam arcu turpis, faucibus vel placerat a, molestie vel lectus. Sed condimentum euismod tincidunt. Mauris odio tortor, luctus id eleifend vitae, aliquet ut libero. Vestibulum vitae placerat turpis. Duis nec facilisis eros. Morbi ipsum arcu, tempus ac massa nec, mollis aliquet lacus.

Phasellus maximus eros quis massa maximus, et mattis tellus cursus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras id lacus interdum, cursus diam ut, posuere purus. Duis non vestibulum nulla, vitae egestas elit. Phasellus venenatis libero in nunc lobortis tempor in vel orci. Praesent varius lacus eleifend, pretium lectus ut, pulvinar arcu. Nunc ornare dolor velit, id pulvinar urna semper eget. Aenean finibus dui vitae dolor ullamcorper finibus. Cras consequat viverra tellus, a accumsan sem viverra sed. Nulla felis tortor, laoreet non tincidunt elementum, tempus ac risus. Sed nibh nisl, ultrices vel iaculis in, fringilla at ipsum. Curabitur metus ligula, tincidunt non arcu eget, ultricies pellentesque ligula. Duis id est posuere, molestie urna non, gravida tortor. Praesent lacinia erat ac diam sagittis, quis faucibus nunc blandit.

Fusce aliquet tincidunt turpis, ut consequat metus consectetur at. Nunc volutpat semper enim, ut finibus orci luctus in. Mauris pharetra consectetur arcu sed pulvinar. Sed cursus fermentum velit, mattis varius ante commodo ac. Fusce erat mauris, sagittis quis eros vitae, consectetur venenatis nibh. Fusce porttitor tortor lectus, at efficitur diam dictum et. Quisque et suscipit sem. Mauris vulputate orci tellus, non efficitur eros blandit ut. Donec eget hendrerit elit.

如果必须转换元素的高度,则可以通过使用容器作为缓冲区来抵消尺寸变化的影响。

var lastScrollY = 0;
var ticking = false;

window.addEventListener('scroll', function(e) {
	lastScrollY = window.scrollY;
	if ( ! ticking ) {
		window.requestAnimationFrame(function() {
			console.log( lastScrollY );
			if ( lastScrollY > 0 ) {
				document.body.classList.add('stuck');
			} else {
				document.body.classList.remove('stuck');
			}
			ticking = false;
		});
		ticking = true;
	}
} );
body {
	margin: 0;
}
.wrapoffset { /* Make this element sticky instead */
  height: 80px;
  position: sticky;
  top: 0;
  width: 100%;
}
.wrap {
	background: #666;
	text-align: center;
  width: 100%;
}
.block {
  height: 80px;
	width: 80px;
	background: red;
	display: block;
	transition: 0.5s;
}
.stuck .block {
	height: 40px;
}
<div class="wrapoffset"> <!-- new element -->
  <div class="wrap">
    <span class="block"></span>
  </div>
</div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque ac lorem a metus tincidunt eleifend id in odio. Nam malesuada hendrerit tristique. Pellentesque id ornare elit, ac lobortis metus. Sed iaculis et nisi et consectetur. Proin pellentesque metus mi, quis fringilla mauris pulvinar et. Vivamus pharetra elit ligula, eu consectetur magna consequat nec. Donec sed enim sit amet augue malesuada varius id a libero. Nullam nec ante id justo elementum congue quis in purus. Integer finibus cursus volutpat. Donec non laoreet ipsum.

Maecenas id venenatis velit, eu feugiat dolor. Vestibulum malesuada erat ut turpis mattis vehicula. Vestibulum sem leo, cursus quis lacinia eu, tincidunt eu velit. Nulla odio elit, tristique vel bibendum vitae, placerat nec eros. Proin auctor id leo sed rutrum. Proin convallis erat sit amet neque aliquam vestibulum. Ut sodales vel nisl eu imperdiet.

Donec a porttitor dui, vitae ullamcorper nibh. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam non elit eu elit blandit hendrerit id ut eros. Duis sagittis elementum ligula eu venenatis. Aenean nunc mauris, dignissim ut venenatis ac, pharetra eget magna. Curabitur elementum enim sed pharetra rhoncus. Praesent sodales at ex at consectetur. Curabitur sed dictum mi, ut eleifend arcu. Nam feugiat risus quis congue porttitor. Maecenas vehicula lorem ultrices ante sollicitudin, placerat sollicitudin dolor fermentum. Aliquam arcu turpis, faucibus vel placerat a, molestie vel lectus. Sed condimentum euismod tincidunt. Mauris odio tortor, luctus id eleifend vitae, aliquet ut libero. Vestibulum vitae placerat turpis. Duis nec facilisis eros. Morbi ipsum arcu, tempus ac massa nec, mollis aliquet lacus.

Phasellus maximus eros quis massa maximus, et mattis tellus cursus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras id lacus interdum, cursus diam ut, posuere purus. Duis non vestibulum nulla, vitae egestas elit. Phasellus venenatis libero in nunc lobortis tempor in vel orci. Praesent varius lacus eleifend, pretium lectus ut, pulvinar arcu. Nunc ornare dolor velit, id pulvinar urna semper eget. Aenean finibus dui vitae dolor ullamcorper finibus. Cras consequat viverra tellus, a accumsan sem viverra sed. Nulla felis tortor, laoreet non tincidunt elementum, tempus ac risus. Sed nibh nisl, ultrices vel iaculis in, fringilla at ipsum. Curabitur metus ligula, tincidunt non arcu eget, ultricies pellentesque ligula. Duis id est posuere, molestie urna non, gravida tortor. Praesent lacinia erat ac diam sagittis, quis faucibus nunc blandit.

Fusce aliquet tincidunt turpis, ut consequat metus consectetur at. Nunc volutpat semper enim, ut finibus orci luctus in. Mauris pharetra consectetur arcu sed pulvinar. Sed cursus fermentum velit, mattis varius ante commodo ac. Fusce erat mauris, sagittis quis eros vitae, consectetur venenatis nibh. Fusce porttitor tortor lectus, at efficitur diam dictum et. Quisque et suscipit sem. Mauris vulputate orci tellus, non efficitur eros blandit ut. Donec eget hendrerit elit.

如果您想进一步优化性能,可以考虑将IntersectionObserverpolyfill一起使用,而不是监听滚动事件。