36

Imagine this is my page:

<p>hello</p>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<p class="myPara">My Paragraph</p>

How can I alert a message when the user has scrolled down to the paragraph with the class "myPara" and not before then?

Jason
  • 361
  • 1
  • 3
  • 3

5 Answers5

52

How about:

var target = $(".myPara").offset().top;
var interval = setInterval(function() {
    if ($(window).scrollTop() >= target) {
        alert("made it!");
        clearInterval(interval);
    }
}, 250);

Here's an example: http://jsfiddle.net/andrewwhitaker/24M3n/1/

You might be tempted to attach an event handler to the window scroll event, but John Resig advises against it (Scroll down to "Best Practices").

Update: As @AbdulJabbarWebBestow points out, it might be a bad idea to unnecessarily run a function every 250ms. Here's an updated example that only runs once, 250ms after the first time a user scrolls:

var target = $(".mypara").offset().top,
    timeout = null;

$(window).scroll(function () {
    if (!timeout) {
        timeout = setTimeout(function () {
            console.log('scroll');            
            clearTimeout(timeout);
            timeout = null;
            if ($(window).scrollTop() >= target) {
                alert('made it');
            }
        }, 250);
    }
});

Example: http://jsfiddle.net/24M3n/858/

Community
  • 1
  • 1
Andrew Whitaker
  • 119,029
  • 30
  • 276
  • 297
  • Using setInterval is not suitable for this kind of operations. Just use jQuery scroll listener as explained by Reigel's answer – Stefano Pochet Jun 21 '13 at 11:35
  • 2
    @StefanoPochet: Actually, this is the *perfect* time to use `setInterval`. Check out the article I linked to in the answer for why you wouldn't want to attach to `.scroll` directly. – Andrew Whitaker Jun 21 '13 at 12:07
  • Read the article. Good to know this and now I think your answer is correct. But I still would say that a cleaner and more responsive solution in this specific case would be to use onScroll and simply put the selector instruction outside the onScroll block of code. Something like this: var myTargetDivPositionTop = $(".myPara").offset().top; $(window).scroll(function(){ if( $(window).scrollTop() > myTargetDivPositionTop ){ doMyStuff() } } – Stefano Pochet Jun 24 '13 at 13:37
  • 3
    @StefanoPochet **I don't think it is a good answer** because this function is continuesly firing event whilst we are not even scrolling. You can see by putting **console.log('Hello World');** just like this setInterval(function() {console.log('Hello World'); and it is resource consumptive task. – Airy Mar 03 '14 at 15:25
  • @AbdulJabbarWebBestow: If the use of `setInterval` makes you nervous, you could use `setTimeout` instead so that the timer only fires after scrolling. – Andrew Whitaker Mar 03 '14 at 15:30
  • I don't think that it will make any difference but for confirmation I tried what you suggested and now the entire function stops after first execution. Can you update your answer so we can see what's better? Because your current answer is firing event without any need – Airy Mar 03 '14 at 15:46
  • @AbdulJabbarWebBestow: Why would it not make any difference? We're talking about calling a function ever 250 milliseconds vs calling a function once after scrolling. I'll add an example. – Andrew Whitaker Mar 03 '14 at 16:15
  • Well I just tried what you suggested but couldn't find it working with setTimeout. May be you can provide an example with that one because setInterval doesn't seems a good solution. I working with scrollbars so need to find a good solution :) – Airy Mar 03 '14 at 16:19
  • @AbdulJabbarWebBestow: I've updated my answer with another solution that I believe to be a bit better. Let me know what you think, and thanks for the input! – Andrew Whitaker Mar 03 '14 at 16:34
  • Downvoting, because polling using timeout is not a good approach. – Steve McLeod Jul 11 '17 at 08:44
  • 3
    @SteveMcLeod Probably not now. Maybe it was 6.5 years ago though? Maybe it'd be helpful for you to post an answer that's more relevant now. – Andrew Whitaker Jul 11 '17 at 14:18
20
$(window).scroll(function(){
    console.log($('#myPara').offset().top < $(this).height() + $(this).scrollTop());
});
Reigel
  • 61,807
  • 21
  • 115
  • 133
0

I had been thinking about the problem of attaching a scroll event (pointed out by @AndrewWhitaker), and my final thoughts are that there is no need to add a scoll event handler every x seconds, since you can just execute a setInterval and check in the callback whether the alert should be shown or not. e.g:

var showMessageInterval = window.setInterval(showMessageIfNeeded, 500);
// you could adjust the interval to the animation duration of the 
// message showing. In this way, the delay will be more "natural"

The showMessageIfNeeded callback would check the scrollTop value and show the message if needed. If the message is displayed, the setInterval have to be cleared to avoid the next executions:

function showMessageIfNeeded() {
    var scrollTop = $(window).scrollTop();
    var targetTop = $(".myPara").offset().top;
    if (scrollTop > targetTop) {
        alert('Show message');
        window.clearInterval(showMessageInterval);
    }
}
Manolo
  • 16,729
  • 16
  • 67
  • 115
0

You can do this with the scrollspy jquery plugin. https://github.com/thesmart/jquery-scrollspy

$('.myPara').on('scrollSpy:enter', function() {
    console.log('enter:', $(this).attr('id'));
});

$('.myPara').on('scrollSpy:exit', function() {
    console.log('exit:', $(this).attr('id'));
});

$('.tile').scrollSpy();
desbest
  • 4,269
  • 11
  • 45
  • 76
0

Compare the page scroll position to your element top position, than call your function.

jQuery

$(document).on('scroll', function() {
  if ($(this).scrollTop() >= $('.myPara').position().top) {
    console.log('Reached');
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<p>hello</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<p class="myPara">My Paragraph</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

ES6 (Pure JS, no jQuery)

var target = document.querySelector('.myPara');

document.addEventListener('scroll', () => {
  if (window.scrollY >= target.getBoundingClientRect().top) {
    console.log('Reached');
  }
})
<p>hello</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<p class="myPara">My Paragraph</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
Simon Arnold
  • 14,397
  • 6
  • 62
  • 81