Erik McFarland Erik McFarland - 1 year ago 52
jQuery Question

Optimized method to see if element is currently in view while scrolling, JQuery (Working Code + Fiddle)

I currently have working code but it seems to have a lot of overhead. Without using a plugin is there a way to achieve the same effect or clean my code to eliminate as much overhead as possible. I know it's the scroll method causing this but I can't seem to get it working without it.

JS fiddle with working code/example:

Javascript to be optimized

function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
console.log((elemTop <= docViewBottom) && (elemTop >= docViewTop))
return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
var marker = $('.marker');

$(window).scroll(function() {
var result = isScrolledIntoView(marker)
if (result === true) {
} else {

Thank you, I appreciate the help

Answer Source

When you scroll the event fires multiple times, so the best thing you can do is minimize the amount of work done by that function. Here's a neat trick I learned from John Resig (creator of jQuery):

$(window).scroll(function() {
  didScroll = true;

target = $('.target')

setInterval(function() {
  if ( didScroll ) {
    didScroll = false;

    if (isScrolledIntoView(marker) === true) {
    } else {
}, 250);

Basically the only thing that happens on scroll is a global variable gets set to true. The setInterval checks that variable every quarter second, and only when it detects a scroll has occurred, sets the variable back to false and fires off any other functionality that you need to run on scroll.

Secondly, it may be slightly more performant to let CSS handle the showing and hiding of content, so I set the target to display: none by default and use an active class to make it visible:

.target {
  display: none;
} {
  display: block;

Bonus in doing this is that you can add some nicer CSS3 transitions like visiblity+opacity or transitioning in from off-screen rather than just a boring old show/hide.

Demo here: