CSS Snap Scroll 不允许 jQuery 滚动函数添加或移除类。

huangapple go评论62阅读模式
英文:

CSS Snap Scroll does not allow for jQuery scroll function to add or remove classes

问题

以下是您要翻译的内容:

所以我在我的 jQuery 文件中实现了这个功能,用于检测特定的 div 区域是否在视口中。

jQuery.fn.isInViewport = function($) {
	var elementTop = jQuery(this).offset().top;
	var elementBottom = elementTop + jQuery(this).outerHeight() / 2;
	var viewportTop = jQuery(window).scrollTop();
	var viewportHalf = viewportTop + jQuery(window).height() / 2;
	return elementBottom > viewportTop && elementTop < viewportHalf;
};

jQuery(window).on('load resize scroll', function($) {
	jQuery('.snappy').each(function() {
		var snapID = jQuery(this).attr('id');
		if (jQuery(this).isInViewport()) {
			jQuery('.sidenavitem').find("." + snapID).addClass("active");
			jQuery(this).addClass("in-view");		
		} else {
			jQuery('.sidenavitem').find("." + snapID).removeClass("active");
			jQuery(this).removeClass("in-view");
		}
	});
});

独立使用 .on('load resize scroll') 函数能够正常工作,并且会添加和移除活动类,但是当我添加这个 CSS 样式时,滚动函数停止工作,只在第一个元素上工作,因为有 load 属性。

#main {
	overflow-y: scroll;
	height: 100vh;
	scroll-snap-type: y proximity;
}

.snappy {
	scroll-snap-align: start;
    scroll-snap-stop: always;
	height: 100vh;
}

我不确定是我的 CSS 还是我的 jQuery 中存在问题。

任何帮助将不胜感激。

这是我实施这个功能的链接:
https://dev.staging.idgadvertising.com/genesistint/

英文:

So I have this implemented within my jquery file to detect if a certain div section is in viewport.

jQuery.fn.isInViewport = function($) {
	var elementTop = jQuery(this).offset().top;
	var elementBottom = elementTop + jQuery(this).outerHeight() / 2;
	var viewportTop = jQuery(window).scrollTop();
	var viewportHalf = viewportTop + jQuery(window).height() / 2;
	return elementBottom &gt; viewportTop &amp;&amp; elementTop &lt; viewportHalf;
};

jQuery(window).on(&#39;load resize scroll&#39;, function($) {
	jQuery(&#39;.snappy&#39;).each(function() {
		var snapID = jQuery(this).attr(&#39;id&#39;);
		if (jQuery(this).isInViewport()) {
			jQuery(&#39;.sidenavitem&#39;).find(&quot;.&quot;+snapID).addClass(&quot;active&quot;);
			jQuery(this).addClass(&quot;in-view&quot;);		
		} else {
			jQuery(&#39;.sidenavitem&#39;).find(&quot;.&quot;+snapID).removeClass(&quot;active&quot;);
			jQuery(this).removeClass(&quot;in-view&quot;);
		}
	});
});

By itself, the .on(&#39;load resize scroll&#39;) function works and the active class gets added and removed but when I add this CSS style, the scroll function stops working and only works on the first one since there is load property

#main {
overflow-y: scroll;
  height: 100vh;
  
  scroll-snap-type: y proximity;
}

.snappy {
	scroll-snap-align: start;
    scroll-snap-stop: always;
	height: 100vh;
}

I am unsure if it's something within my CSS or my jQuery.

Any help would be greatly appreciated.

Here is a link to where I have implemented this:
https://dev.staging.idgadvertising.com/genesistint/

答案1

得分: 1

好的,以下是翻译好的内容:


问题似乎出在 #main 元素的 CSS 属性上。max-height: 100vh 似乎与 overflow-y: scroll 不兼容。

通过设置 max-height: 100vh,你基本上在说 #main 元素只能与视口高度一样高。然后通过设置 overflow-y: scroll,你明确地告诉浏览器始终显示垂直滚动条,无论内容是否溢出。

这会导致冲突,使得 jQuery(window).on('load resize scroll', function($) 在用户滚动 window 时不会触发回调函数。

因此,正确的 CSS 可以是:

#main {
  max-height: 100vh;
  scroll-snap-type: y proximity;
}

或者(我认为这个更好):

#main {
  scroll-snap-type: y proximity;
}

在这里你不需要 overflow-y: scroll;,因为页面似乎总是比视口高,所以窗口的滚动条会自动显示。


自助调试指南:

首先,我会优化 JS 代码以便更好地进行调试。创建一个名为 handleSideNav 的单独函数,专门用于处理侧边导航。之后,在窗口加载时应用该函数,然后在有人滚动或调整窗口大小时也应用相同的函数。

请注意 console.log('Triggered event:', event); 这一行用于调试 - 现在你可以看到触发了哪个事件,如果根本没有触发任何事件的话。在测试完成后删除此行。

jQuery.fn.isInViewport = function($) {
    var elementTop = jQuery(this).offset().top;
    var elementBottom = elementTop + jQuery(this).outerHeight() / 2;
    var viewportTop = jQuery(window).scrollTop();
    var viewportHalf = viewportTop + jQuery(window).height() / 2;
    return elementBottom > viewportTop && elementTop < viewportHalf;
};

function handleSideNav(event) {
    console.log('触发事件:', event);
    jQuery('.snappy').each(function() {
          var snapID = jQuery(this).attr('id');
          if (jQuery(this).isInViewport()) {
              jQuery('.sidenavitem').find("." + snapID).addClass("active");
              jQuery(this).addClass("in-view");       
          } else {
              jQuery('.sidenavitem').find("." + snapID).removeClass("active");
              jQuery(this).removeClass("in-view");
          }
      });
}

jQuery(window).on('load', handleSideNav);

jQuery(window).on('resize scroll', handleSideNav);

现在你可以刷新页面并滚动页面,看看是否有任何事件被触发。使用你的原始 CSS,你可以在浏览器控制台中看到,当你滚动页面时,scroll 事件不会被触发。这表明虽然你在滚动,但浏览器并未将其注册为 window 的滚动,因此问题可能出在你的 CSS 上。

英文:

Shortly, the problem seems to be with the CSS properties for the #main element. The max-height: 100vh doesn't seem to play well with overflow-y: scroll.

By setting max-height: 100vh you are basically saying the #main element can only be as tall as the viewport height. And then by setting overflow-y: scroll you are explicitly instructing the browser to always show a vertical scrollbar, regardless of whether there is content overflowing or not.

This causes a conflict which results in jQuery(window).on(&#39;load resize scroll&#39;, function($) not triggering the callback function when the users scrolls the window.

Thus, the correct CSS could be either:

#main {
  max-height: 100vh;
  scroll-snap-type: y proximity;
}

or (I think this one is better):

#main {
  scroll-snap-type: y proximity;
}

You don't need overflow-y: scroll; in there since the page seems to be always taller then viewport height, so the window's scrollbar is always displayed automatically.


DIY DEBUGGING GUIDE:

Firstly, I would optimize the JS code for better debugging. Create a separate function named handleSideNav just for handling the side navigation. After that, u could apply that function when the window loads, then apply the same function when somebody scrolls or resizes the window.

Notice the console.log(&#39;Triggered event:&#39;, event); line which is for debugging - now u can see which event was triggered, if any event was triggered at all. Delete this line after you are done testing.

jQuery.fn.isInViewport = function($) {
    var elementTop = jQuery(this).offset().top;
    var elementBottom = elementTop + jQuery(this).outerHeight() / 2;
    var viewportTop = jQuery(window).scrollTop();
    var viewportHalf = viewportTop + jQuery(window).height() / 2;
    return elementBottom &gt; viewportTop &amp;&amp; elementTop &lt; viewportHalf;
};

function handleSideNav(event) {
    console.log(&#39;Triggered event:&#39;, event);
    jQuery(&#39;.snappy&#39;).each(function() {
          var snapID = jQuery(this).attr(&#39;id&#39;);
          if (jQuery(this).isInViewport()) {
              jQuery(&#39;.sidenavitem&#39;).find(&quot;.&quot;+snapID).addClass(&quot;active&quot;);
              jQuery(this).addClass(&quot;in-view&quot;);       
          } else {
              jQuery(&#39;.sidenavitem&#39;).find(&quot;.&quot;+snapID).removeClass(&quot;active&quot;);
              jQuery(this).removeClass(&quot;in-view&quot;);
          }
      });
}

jQuery(window).on(&#39;load&#39;, handleSideNav);

jQuery(window).on(&#39;resize scroll&#39;, handleSideNav);

Now u can refresh and scroll the page and see if any events are being triggered. With your original CSS, you can see in the browser console, that the scroll event won't trigger when you scroll the page. That indicates the even though u are scrolling, the browser doesn't register that as window scrolling, thus the problem might be with your CSS.

huangapple
  • 本文由 发表于 2023年5月17日 08:17:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76267816.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定