Figure out which element is scrolled to jQuery
Does what it says on the tin. It takes a set of elements and tries to determine which one is featured most predominantly on the page. Change the $sections selector (line 3) to target the element-set of your choice, or rewrite as a plugin :)
Towards the bottom, the element which is deemed to be in view will be given a 'highlight' class.
Note that we are binding directly to the scroll event which is generally a bad idea. Whether it is a bad idea for you depends upon various factors. If you find it negative impacts performance on your page, factor out the scroll event and call it after a short timer (and cancel the timer on the next scroll).
(function() { "use strict"; var $sections = $('.panel'), $sectionsReversed = $($sections.get().reverse()), $last = $({}); $(window).scroll(function(ev) { var pos = $(document).scrollTop(), $nearest = $sections.eq(0), amount = 0; // amount of the screen occupied // scrolled to extremes - take the top or bottom element as appropriate // There's a little bit of leeway on the bottom scroll detection as // Firefox sometimes seems to lose a pixel. if (pos === 0 && false) $nearest = $sections.eq(0); else if (pos >= $(document).height() - $(window).height() - 10) { $nearest = $sectionsReversed.eq(0); } // otherwise do something a little cleverer else { var windowHeight = $(window).height(), start = pos, end = start + windowHeight; $sections.each(function() { // we're going to try to figure out which element // takes up the important parts of the screen. var $this = $(this), top = $this.offset()? $this.offset().top + $this.outerHeight() : //IE? $this.offset().top, bottom = $this.offset().top + $this.outerHeight(), topVisible = top >= start && top <= end, bottomVisible = bottom >= start && bottom <= end, candidateAmount = 0; if (top <= start && bottom >= end) { // occupies entire screen // we have a winner $nearest = $this; amount = 1; return false; } // no part of the element visible - nope else if (!topVisible && !bottomVisible) return; else if (topVisible && bottomVisible) { // full element is visible. We'll take this one // since it's highest on the screen. amount = (bottom-top)/windowHeight; $nearest = $this; return false; } else if (bottomVisible) { // occupies part of the screen from the top down only candidateAmount = (bottom - start)/windowHeight; } else if (topVisible) { // occupies part of the screen from the bottom up only candidateAmount = (end - top)/windowHeight; } if (candidateAmount > amount) { amount = candidateAmount; $nearest = $this; } }); } if ($last !== $nearest) { $last.removeClass('highlight'); $nearest.addClass('highlight'); $last = $nearest; } }); $(window).trigger('scroll'); })();
Talk is cheap