with Imagination: by Dustin Diaz

./with Imagination

A JavaScript, CSS, XHTML web log focusing on usability and accessibility by Dustin Diaz

Detect when an element has scrolled into view

Thursday, July 26th, 2007

A question came up on one of our engineering lists the other day and I think it’s innocent enough to go ahead and share a simple solution I had came up with that solves this particular issue. Needless to say, I believe I’m not breaking the birch of “don’t be evil.” Furthermore, this gives me an excuse to write about something since I haven’t done so in a few months (*cough).

Anyway, the idea is basic. You have an element in the DOM sitting somewhere below the fold (see above the fold), and you’d like to know when it has breached through the bottom threshold of your screen as a user is scrolling down a page. An example of an application that uses this kind of logic would be, for instance, Google reader, where stories are loaded dynamically as the user scrolls more headlines into view. Since there could potentially be hundreds or even thousands of RSS entries from any given feed, we wouldn’t want to load all of them at once.

Le Code

I went ahead and prototyped this out quickly using Y.U.I. to save time on simply proving a concept. The code that come of it essentially looks like this:

JavaScript: scroll element into view

var Event = YAHOO.util.Event;
var Dom = YAHOO.util.Dom;
Event.on(window, 'load', function() {
    var y = Dom.getY('ft');
    Event.on(window, 'scroll', function() {
        var top = (document.documentElement.scrollTop ?
            document.documentElement.scrollTop :
            document.body.scrollTop);
        var vpH = Dom.getViewportHeight();
        var coverage = parseInt(vpH + top);
        if ( coverage >= y ) {
            console.log('in view!!!');
        }
    });
});

What this logic is essentially telling us is that we need three key ingredients to solve for this.

  • The Y coordinate of the target element
  • The viewport height of the users window
  • The amount a user has scrolled from the top

If we add the viewport and the scrolling area, we can calculate our coverage; and then compare that to our Y coordinate. If the coverage is greater than or equal to the Y coordinate, we have passed the threshold. Go ahead and have a look see of our example so far.

Modifications

Since we’ve proven the concept, we can now write a simple interface that allows us to pass any arbitrary element, and then turn it into a custom event. With that in mind, a la Sellsian approach (implement first, API later), we could do something like this:

element viewer implementation

YAHOO.example.ElementViewer('my-element', function(Y) {
    console.log('my-element is in view at:' + Y);
});

Simply pass in an element (id or HTMLElement), then add a callback method which will return the Y coordinate of how far you’ve scrolled to get there. The interface would now simply look like this using YUI’s custom event interface:

JavaScript: Element Viewer API

YAHOO.example.ElementViewer = function(el, callback) {
    var y = Dom.getY(el);
    var o = new YAHOO.util.CustomEvent('element finder',
        null,
        true,
        YAHOO.util.CustomEvent.FLAT
    );
    o.subscribe(callback);
    function f() {
        var top = (document.documentElement.scrollTop ?
            document.documentElement.scrollTop :
            document.body.scrollTop);
        var vpH = Dom.getViewportHeight();
        var view = parseInt(vpH + top);
        if ( view >= y ) {
            o.fire(view);
        }
    }
    Event.on(window, 'scroll', f);
};

And there you have it. This allows us to do the same thing, except now with a fancy interface :). See the demonstration. Cheers.

20 Responses to “Detect when an element has scrolled into view”

  1. Frank Manno

    Hey Dustin,

    Sweet write-up. Short, simple, and to the point. Love it!

  2. Jim A.

    Thanks for the write up Dustin, and good to see you posting. This reminds me of something I wrote for CWM in my earlier JS days: http://www.christian-web-masters.com/articles/web_logging-scrolling-javascript.html

    –Jim

  3. Marc

    Hi Dustin,

    I must be doing something stupid ’cause I’m getting an error in fb’s console:
    ‘console is not defined’ (I just did an update to get the latest version 1.05)

    But other than that, pretty cool! :)

    Marc

  4. Dustin Diaz

    @Frank: Thanks dude. It took me quite a while to develop this style of writing. Over explaining is often the death of my best writings.

    @Jim: The page you linked is not available to unauthorized viewers. Nonetheless, I do remember that article being posted although I had never read it.

    @Marc: It works for me. I think there is a bug in your Firebug installation. There is no reason that ‘console’ should be undefined. console.log is the most commonly used method in Firebug. I find it quite ironic that Firebug itself is reporting that back to you. However, I have had that happen to me before. I would simply try uninstalling then reinstalling Firebug a few times or find an older version.

  5. Jim A.

    Said by Dustin, “Over explaining is often the death of my best writings.”

    Often a problem of mine as well.

    Said by Dustin, “The page you linked is not available to unauthorized viewers. Nonetheless, I do remember that article being posted although I had never read it.”

    Interesting…I didn’t realize that was protected content…and I am hurt you didn’t read it. ;)

    Said by Dustin, “There is no reason that ‘console’ should be undefined.”

    Agreed–it is working for me…

  6. Marc

    I’m getting “Console is not defined” error as well in FF2 on WinXP.

  7. Dustin Diaz

    So clearly, this isn’t working for people named Marc…. I don’t know what to make of it. You can try downloading the code and swapping it out for an alert and watch what happens.

  8. Riddle

    Dustin, I think you should’ve added Firebug Lite to your test, because there are plenty of Firefox people who don’t read descriptions (which is why they report a “bug” to you although they don’t have Firebug installed) and don’t use Firefox at all.

    I know, Firebug is awesome and for example, at my work in developing stage everyone is using console.error|log to debug things. But we shouldn’t rely on this extension, without detecting it first, don’t you think? :>

  9. kentaromiura

    this isn’t working for people named Marc

    :lol:

  10. Pelle

    Nice stuff - will certainly remember this.

    Just for the record - I got errors i Firebug as well using XP and latest of both Firebug and Firefox. Although it usually works I have read somewhere that there may be some bugs regarding Firebug and the latest FF or something and it’s quite a weird bug because now when I tested around a bit it worked randomly among different sites and when I returned to your example it suddenly works.

    Well, well - your examples are wonderfully even if Firebug may be flawed ;)

  11. ...

    I saw a cool demo yesterday of a page the monitored for you to scroll to the bottom of what would normally be a paginated list of results from a search. When the bottom was hit, an AJAX request was triggered for more results to be appended to the document.

  12. Chris Neale

    I get errors from Firebug about console not being defined too

    console is not defined
    http://www.dustindiaz.com/basement/element-in-view2.html
    Line 68

    I’m not called marc or Marc

  13. Schrebergarten

    Dustin: Does not happen with the safari browser …

  14. Daniel

    Nice work … and talk about the simplicity of it !

  15. Not Marc

    Excellent .. (works for me) .. going to give one of my clients a cheap thrill with this .. they have this humungous users manual that we’ve been thunking of various ways to break down in reader-friendly chunks .. you da man ..

  16. MarK

    This also pops up errors for people called Mark. I think it’s something as simple as Firefox does not have “console”… Oh wait, someone allready beat me to that one.

  17. Lance Fisher

    Nice! I like this. The one issue with it is that if the element is in view and you refresh the page the event is not fired until you scroll.

  18. Detect when DOM Element is in viewport | Matt Snider JavaScript Resource

    [...] I just read a good article by Dustin Diaz (formerly of YAHOO) about detecting where elements are in regards to scrolling and the viewport. It is simple and very powerful, so I thought I would share it with you. Also, I am overworked right now and have not had time to write any material of my own :(. element-scroll-into-view posted by admin at 3:49 pm   [...]

  19. fenryr

    Used this in a new project.. works nicely!

  20. ifoh designs » Blog Archive » The best of the best (lots of Web resources)

    [...] Detect when an element has scrolled into view [...]

Get "JavaScript Design Patterns"

"As a web developer, you'll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power waiting to be unlocked--JavaScript is capable of full object-oriented capabilities, and by applying OOP principles, best practices, and design patterns to your code, you can make it more powerful, more efficient, and easier to work with alone or as part of a team."

Buy JS Design Patterns from Amazon.com Buy JS Design Patterns from Apress

All content copyright © 2003 - 2009 under the Creative Commons License.

Archives | Blog Search