Updated Demo Fiddle no alert -- instead FadeIn() the element
Updated code to check if the element is inside the viewport or not. Thus this works whether you are scrolling up or down adding some rules to the if statement:
var element_position = $('#scroll-to').offset().top;
$(window).on('scroll', function() {
var y_scroll_pos = window.pageYOffset;
var scroll_pos_test = element_position;
if(y_scroll_pos > scroll_pos_test) {
//do stuff
}
});
UPDATE
I've improved the code so that it will trigger when the element is half way up the screen rather than at the very top. It will also trigger the code if the user hits the bottom of the screen and the function hasn't fired yet.
var element_position = $('#scroll-to').offset().top;
var screen_height = $(window).height();
var activation_offset = 0.5;//determines how far up the the page the element needs to be before triggering the function
var activation_point = element_position - (screen_height * activation_offset);
var max_scroll_height = $('body').height() - screen_height - 5;//-5 for a little bit of buffer
//Does something when user scrolls to it OR
//Does it when user has reached the bottom of the page and hasn't triggered the function yet
$(window).on('scroll', function() {
var y_scroll_pos = window.pageYOffset;
var element_in_view = y_scroll_pos > activation_point;
var has_reached_bottom_of_page = max_scroll_height <= y_scroll_pos && !element_in_view;
if(element_in_view || has_reached_bottom_of_page) {
//Do something
}
});
$('div').on('inview', function (event, visible) {
if (visible == true) {
// element is now visible in the viewport
} else {
// element has gone out of viewport
}
});
If you are doing a lot of functionality based on scroll position, Scroll magic (http://scrollmagic.io/) is built entirely for this purpose.
It makes it easy to trigger JS based on when the user reaches certain elements when scrolling. It also integrates with the GSAP animation engine (https://greensock.com/) which is great for parallax scrolling websites
Just a quick modification to DaniP's answer, for anyone dealing with elements that can sometimes extend beyond the bounds of the device's viewport.
Added just a slight conditional - In the case of elements that are bigger than the viewport, the element will be revealed once it's top half has completely filled the viewport.
function elementInView(el) {
// The vertical distance between the top of the page and the top of the element.
var elementOffset = $(el).offset().top;
// The height of the element, including padding and borders.
var elementOuterHeight = $(el).outerHeight();
// Height of the window without margins, padding, borders.
var windowHeight = $(window).height();
// The vertical distance between the top of the page and the top of the viewport.
var scrollOffset = $(this).scrollTop();
if (elementOuterHeight < windowHeight) {
// Element is smaller than viewport.
if (scrollOffset > (elementOffset + elementOuterHeight - windowHeight)) {
// Element is completely inside viewport, reveal the element!
return true;
}
} else {
// Element is larger than the viewport, handle visibility differently.
// Consider it visible as soon as it's top half has filled the viewport.
if (scrollOffset > elementOffset) {
// The top of the viewport has touched the top of the element, reveal the element!
return true;
}
}
return false;
}
I use the same code doing that all the time, so added a simple jquery plugin doing it.
480 bytes long, and fast. Only bound elements analyzed in runtime.
Note: By successful scroll I mean when the user has scrolled to the desired
element or in other words when the desired element is in view
The accepted answer worked 90% for me so I had to tweak it a little to actually fire only once.
$(window).on('scroll',function() {
var hT = $('#comment-box-section').offset().top,
hH = $('#comment-box-section').outerHeight(),
wH = $(window).height(),
wS = $(this).scrollTop();
if (wS > ((hT+hH-wH)-500)){
console.log('comment box section arrived! eh');
// This detaches the scroll so doStuff() won't run more than once
$(window).off('scroll');
doStuff();
}
});
Intersection Observer can be the best thing IMO, without any external library it does a really good job.
const options = {
root: null,
threshold: 0.25, // 0 - 1 this work as a trigger.
rootMargin: '150px'
};
const target = document.querySelector('h1#scroll-to');
const observer = new IntersectionObserver(
entries => { // each entry checks if the element is the view or not and if yes trigger the function accordingly
entries.forEach(() => {
alert('you have scrolled to the h1!')
});
}, options);
observer.observe(target);
If you are looking for a javascript version. You can call this method on scroll event listener.
showScrollTop = () =>{
const currentScrollPosition = window.pageYOffset;
let elementID = 'service-selector'
const elementOffsetTop = document.getElementById(elementID).offsetTop
if ( currentScrollPosition > elementOffsetTop){
// place your logic here
} else {
// place your logic here
}
}
window.addEventListener('scroll', showScrollTop)