Infinite scrolling in both directions - Up and down - javascript

I am trying to create a page that is an endless scrolling loop both up and down.
At the moment I am using jquery to relocate content from the top of the page to the bottom. This creates a nice seemless loop when you scroll down but I would like it to work when the user scrolls up too.
The problem seems to be that even if content is positioned in negative vertical space on the page the scroll will not extend to that space. As far as I am aware there is no way to override this so I am looking for some type of work around.
I have thoughts of using javascript to disable the scrolling and using the scroll event to reposition the elements but there are already lots of absolute positioned elements and animation happening on the page so I'm concerned about performance taking that route.
Any other leads?

OK... I worked it out.
I adapted this script which instantly relocates the scroll location to the top of the page when you get to the bottom and to the bottom when you reach the top.
$(window).scroll(function() {
if ( $(window).scrollTop() >= 18830 ) {
$(window).scrollTop(201);
}
else if ( $(window).scrollTop() == 0 ) {
$(window).scrollTop(18629);
}
});
And then I made sure that the content at the bottom and the top of the page was identical. I thought that there would be a flash or something when this relocation happened but it's smooth!

The solution I like the best is this one (code), because it adds elements at the bottom before the bottom is reached, making sure that scrolling remains continuous (even with smooth scrolling on). However, it doesn't work that well on mobile phones where scrolling can happen pretty quickly. I recommend Marijn Haverbeke's wonderful article on fake scrollbars in CodeMirror where he deals with similar issues.
I leave you with some snippets.
First, some background. Why would we want to fake a scrollbar to begin with?
In order to remain responsive when huge documents are loaded in, CodeMirror does not render the whole document, but only the part of it that is currently scrolled into view. This means that the amount of DOM nodes it creates is limited by the size of the viewport, and the browser relayouts triggered by changes to the text are relatively cheap.
And further down...
Then, it listens to wheel events, but never calls preventDefault on them or does scrolling in response to them. Instead, it responds by setting a timeout to observe the amount of pixels that the wheel event did scroll the content, and uses that to tweak its delta-to-pixel rate at run-time.

Clone your HTML body two (or three) times (in javascript or otherwise). Start the page in the middle copy instead of the top, and then you can handle scrolling however you like.

Any other leads?
Seen these?
5 jQuery infinite Scrolling Demos
jsfiddle that I cannot find origin of. (I didn't write and don't know who did)

As many have suggested, if your page doesn't look exactly the same at the top and at the bottom you’ll need to clone your content to make it look like it does. I’ve made an example using this technique that works pretty smooth:
/*
Ininite looping scroll.
Tested and works well in latest Chrome, Safari and Firefox.
*/
(function (window) {
'use strict';
var doc = document,
body = doc.body,
html = doc.documentElement,
startElement = doc.getElementsByClassName('is-start')[0],
clones = doc.getElementsByClassName('is-clone'),
disableScroll = false,
docHeight,
scrollPos,
clonesHeight,
i;
function getScrollPos() {
return (window.pageYOffset || html.scrollTop) - (html.clientTop || 0);
}
function getDocHeight() {
return Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
}
function getClonesHeight() {
i = 0;
clonesHeight = 0;
for (i; i < clones.length; i += 1) {
clonesHeight = clonesHeight + clones[i].offsetHeight;
}
return clonesHeight;
}
docHeight = getDocHeight();
clonesHeight = getClonesHeight();
window.addEventListener('resize', function () {
scrollPos = getScrollPos();
docHeight = getDocHeight();
clonesHeight = getClonesHeight();
if (scrollPos <= 0) {
window.scroll(0, 1); // Scroll 1 pixel to allow upwards scrolling.
}
}, false);
window.addEventListener('scroll', function () {
if (disableScroll === false) {
scrollPos = getScrollPos();
if (clonesHeight + scrollPos >= docHeight) {
// Scroll to the top when you’ve reached the bottom
window.scroll(0, 1); // Scroll 1 pixel to allow upwards scrolling.
disableScroll = true;
} else if (scrollPos <= 0) {
// Scroll to the top of the clones when you reach the top.
window.scroll(0, docHeight - clonesHeight);
disableScroll = true;
}
if (disableScroll) {
// Disable scroll-repositioning for a while to avoid flickering.
window.setTimeout(function () {
disableScroll = false;
}, 100);
}
}
}, false);
// Needs a small delay in some browsers.
window.setTimeout(function () {
if (startElement) {
// Start at the middle of the starting block.
window.scroll(0, Math.round(startElement.getBoundingClientRect().top + document.body.scrollTop - (window.innerHeight - startElement.offsetHeight) / 2));
} else {
// Scroll 1 pixel to allow upwards scrolling.
window.scroll(0, 1);
}
});
}(this));
section {
position: relative;
text-align: center;
height: 80vh;
}
.red {
background: #FF4136;
}
.green {
background: #2ECC40;
}
.blue {
background: #0074D9;
}
.orange {
background: rebeccapurple;
}
h1 {
margin: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 100%;
font-size: 5vw;
color: #fff;
text-transform: uppercase;
}
body {
font-family: "Avenir Next", Montserrat, Helvetica, sans-serif;
font-weight: normal;
font-size: 100%;
}
::scrollbar {
display: none;
}
<section class="green">
<h1>One</h1>
</section>
<section class="red">
<h1>For</h1>
</section>
<section class="blue">
<h1>All</h1>
</section>
<section class="orange">
<h1>And</h1>
</section>
<section class="blue">
<h1>All</h1>
</section>
<section class="red">
<h1>For</h1>
</section>
<!--
These following blocks are the same as the first blocks to get that looping illusion going. You need to add clones to fill out a full viewport height.
-->
<section class="green is-clone is-start">
<h1>One</h1>
</section>
<section class="red is-clone">
<h1>For</h1>
</section>

Building up on Mahmoud's answer, I hacked up this in a few minutes.
It works somewhat (at least on Firefox) when scrolling either with keys or with mouse wheel, but it gets all glitchy when dragging the scrollbar. Depending on how the div heights relate to the viewport height, all kinds of fireworks can happen too.
Still, I hope this can help you get on the right direction.
function onScroll(){
var SAFETY_MARGIN = 50,
scrollPos = $(this).scrollTop(),
docHeight = $(document.body).height(),
winHeight = $(window).height(),
firstDiv = $('body>div:first-child')[0],
lastDiv = $('body>div:last-child')[0],
lowerLimit = SAFETY_MARGIN,
higherLimit = docHeight - SAFETY_MARGIN;
// Scrolling too high
if( scrollPos <= lowerLimit ){
// Move content to top;
$(lastDiv).prependTo(document.body);
// Adjust scroll position to compensate
// for the new content at the top
$(window).scrollTop(scrollPos + $(lastDiv).height());
}
// Scrolling too low
else if( scrollPos + winHeight >= higherLimit ){
// Move content to bottom
$(firstDiv).appendTo(document.body);
// Adjust scroll position to compensate
// for the missing content at the top
$(window).scrollTop(scrollPos - $(firstDiv).height());
}
}
$(window).scroll(onScroll);
$(window).load(function(){
var $body = $(document.body);
$(window).scrollTop($body.height() / 2);
});
</script>
</head>
<body>
<div style="height: 600px; background-color: red"> </div>
<div style="height: 600px; background-color: green"> </div>
<div style="height: 600px; background-color: blue"> </div>
</body>
</html>

Related

make div scoll untill it reaches top of page then fixed

let's get straight to the point:
My code looks like the following:
<div id="keep_up">
<div id="thread_menu">
<div id="new_thread">
</div>
</div>
</div>
And my css:
#keep_up {
position: fixed;
width: 13%;
}
#thread_menu{
height: 80vh;
width: 100%;
float: left;
position: relative;
}
Now i use this for a forum. and this is basically to show the active and new threads on the side of the screen.
However. When watching a thread, the header disappears (Wich makes sense because we are scrolling down).
but i want the thread menu to stay on my side (So that it is always visible). In this case that is happening because my keep_up div has position: fixed. But i only see half of the thread menu becuase it is too long and won't scroll up.
My question:
I want the thread menu to scroll up, untill it reaches the top of my window. From then on i want it to stay there.
How do i do this?
I saw a few examples but none of them worked for me.
EDIT: Code i tried:
<script src="jquery.min.js">
$(window).scroll(function () {
var margin = null;
$(window).on("scroll", function () {
var scrollHeight = $(document).height(),
scrollTop = $(window).scrollTop(),
offsetBottom = 110, // Offset depending on the height of the footer
offsetTop = 100, // Offset depending on the height of the header
positionTop = $(".keep_up").offset().top,
affix;
if (margin != null && (scrollTop + margin <= positionTop)) {
// The sidebar has reached the bottom and is still on the bottom
affix = false;
} else if (positionTop + $(".keep_up").height() >= scrollHeight - offsetBottom) {
// The sidebar has reached the bottom
affix = 'bottom';
} else if (scrollTop <= offsetTop) {
// The sidebar has reached the top
affix = 'top';
} else {
// The sidebar is midway
affix = false;
}
// If the sidebar hasnot changed his state, return;
if ($(".keep_up").hasClass('at' + (affix ? '-' + affix : ''))) return;
if (affix == 'bottom') {
margin = positionTop - scrollTop;
} else {
margin = null;
}
// If the related class is added to the div
$(".keep_up").removeClass('at at-top at-bottom').addClass('at' + (affix ? '-' + affix : ''))
});
});
</script>
And the CSS:
.keep_up{
/*position: fixed;*/
width: 13%;
}
.keep_up.at {
top: 1px;
position: fixed;
}
.keep_up.at-top{
}
.keep_up.at-bottom {
top: 438px;
position: absolute;
}
modify this on HTML:
<div id="prevent"></div>
<div id="keep_up" data-spy="affix" data-offset-top="200">
Add this CSS:
.affix{position: fixed !important; top:0px; z-index:999;}
.affixpatch{margin-top:100px !important;}
this will fix the div when you scroll down 200px. Change data-offset-top value to reach it on different break point.
.affixpatch is a class that will be loaded with next jquery function. it prevents to hide content behind top fixed div. Change margin-top to another value if this don't solves the "hide content" problem that always generate affixing divs.
<script>
$(function() {
//caches a jQuery object containing the header element
var header = $(".affix");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 200) {
$('#prevent').addClass("affixpatch");
} else {
$('#prevent').removeClass("affixpatch");
}
});
});
</script>
Hope it helps. If not, you may have some class that rewrite or impede the correct function of this affix.
I've tested this hundreds of times, usually to fix navbars.
SCROLL:
Using overflow to scroll content:
#keep_up{
max-height:400px;
width: auto;
overflow:auto;}
This will scroll the content inside #keep_up div (or use it in another one)
NOTE: you must declare a fixed max height for this div. Set max-width only if you need.
You can use %, em, rem... no need to be px for fix the max witdth. (to get a responsive effect, use responsive measurements)
If I understand your scenario correctly, the way to do this might be to use jQuery (or native JS, but you've tagged jQuery so I'm assuming that's in play).
There's a plugin that handles this kind of thing: http://leafo.net/sticky-kit/
I'd suggest you look at the plugin source code to see how it works - an event handler function on $(window).scroll() which then toggles classes on your #thread_menu to fix it in place. To keep your code lightweight, you probably don't need everything the plugin provides.

jQuery doesn't show and hide the header

I'm trying to make a header that appears at a certain place of the page.
So what I'm doing is checking the scroll to top of the page and the top offset of the element after which the header should appear. If the scrollTop is greater than offset the header is shown, otherwise it disappears.
But! When I scroll to the place, the header position is constantly switching between top: -13% and top: -12.999998%. After some time it finally shows the header but it never disappears.
What am I doing wrong?!
JSFiddle: https://jsfiddle.net/5k5s016f/
Well, i think the problem is that the .animate() functions are running constantly, causing the animations to "restart" before its ends.
It is not the most beautiful solution, but just adding a flag that controls the execution of the functions and a timeout to run the handler less frequently solves the problem.
https://jsfiddle.net/5k5s016f/2/
var visible = false;
$(window).scroll(function() {
setTimeout(function(){
var height = $(window).scrollTop();
var $page2 = $("#page2");
var offset = $page2.offset().top;
if (height > offset) {
if (visible) {
return;
}
visible = true;
$(".floating-header").show().animate({
top: 0
});
} else {
if (!visible) {
return;
}
visible = false;
$(".floating-header").animate({
top: "-13%"
});
}
}, 200)
});
The issue you are seeing is because each time a scroll event gets called animation queues up. If you wait long enough, you can see that the animation to set top to 0 actually works.
You can use the stop() function to stop all animation before attempting to run another one.
Something like this
if (height > offset) {
$(".floating-header").stop().show().animate({
top: "0"
}, 700);
} else {
$(".floating-header").stop().animate({
top: "-13%"
}, 700);
}
A couple of improvements I can suggest are
Debounce the scroll event handler
Check the current state of the header before queuing animation. i.e. do not try to hide it if it is already hidden and vice versa
Your logic is all messed up. Basically, you want to make sure that you are only animating when you absolutely need to - no more, no less. And since scroll events happen hundreds of times... constantly rapid firing as the user scrolls... you want to make sure you are doing the least amount of work possible during each scroll event. This especially means that you don't want to be querying the DOM on every scroll event if you don't have to (ps. $('selector') is a dom query). Take a look at this fiddle:
https://jsfiddle.net/5k5s016f/6/
Looks like I'm last to the party due to interruptions, but since I wrote it up I'll post the answer FWIW.
jsFiddle Demo
You need to debounce your code. Here is a simple system, but studing Ben Alman's explanation/examples is also recommended.
var $m1 = $('#m1'), $m2 = $('#m2'); //TESTING ONLY
var $win = $(window), $page2 = $("#page2"), $hdr=$(".floating-header");
var $offset = $page2.offset().top;
var hvis = false, curpos;
$win.scroll(function() {
curpos = $win.scrollTop();
$m1.html(curpos); //TESTING ONLY
$m2.html($offset);//TESTING ONLY
if ( curpos > $offset ) {
if ( !hvis ){
hvis = true;
//$m1.html(curpos);
$hdr.finish().animate({
top: "0"
}, 700);
}
} else {
if ( hvis ){
$hdr.finish().animate({
top: "-60px"
}, 700);
hvis = false;
}
}
});
html,
body {
height: 100vh;
width: 100vw;
}
#page1,
#page2,
#page3 {
height: 100%;
width: 100%;
background-color: #fff;
}
.floating-header {
position: fixed;
top: -60px;
background-color: #000;
width: 100%;
height: 60px;
}
.msg{position:fixed;bottom:10px;height:30px;width:80px;text-align:center;}
.msg{padding-top:10px;}
#m1 {left:3px; border:1px solid orange;background:wheat;}
#m2 {right:3px;border:1px solid green; background:palegreen;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<header class="floating-header">Header</header>
<div id="page1">
<p>Page1</p>
</div>
<div id="page2">
<p>Page2</p>
</div>
<div id="page3">
<p>Page3</p>
</div>
<div id="m1" class="msg"></div>
<div id="m2" class="msg"></div>

Scrolling Two Divs Using JQuery/Javascript

Wrapper - Overflow Hidden
Div One: Sidebar
Div Two: Main Content
Div Two will have a normal scroll. Div One I wish to have no visible scroll however when you scroll Div One it scrolls Div Two.
Upon Div One's height hitting the bottom, it will no longer scroll and visa-versa for scrolling back up.
This will result in the sidebar always being visible at the side. Before you ask, I've tried all positioning types to get this to work resulting in many failed attempts.
My live demo can be seen here: http://rafflebananza.com/admin/newadmin.html#
Note I've tried to make a JSFiddle simplified but my maths does not seem to work in there the same. Please suggest whether I should fork all my page to there or whatnot for future visitors needing the same help.
Overview
Scrolling in the wrapper will scroll sidebar to point x only (x being the sidebars height) then stopping but will continue to allow the content to be scrolled. Visa-versa for scrolling back up.
Somewhat half way there...
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop,
position = document.body.scrollTop;
function scrollD() {
var scroll = document.body.scrollTop;
if (scroll > position) {
// Scrolling Down Functions
} else {
// Scrolling Up Functions
}
position = scroll;
}
Updated the answer to match OPs requirements.
I downloaded your website in its current state and made the following changes to your code:
var scrollY = 0;
$(window).scroll(function() {
var sideNav = $('.SideNav'); // The side navigation
var wScrollY = $(this).scrollTop(); // Current scroll position of Window
var navHeight = sideNav.height(); // Height of the Navigation
var StageHeight = $(window).height() - 46; // The display space
if(sideNav.height() > StageHeight) { // Do the following if the side navigation is higher than the display space
var spaceLeft = sideNav.height() - StageHeight; // spaceLeft -> how many pixel left before fixing navigation when scrolling
if(scrollY < wScrollY) { // Scroll direction is down
if (wScrollY >= spaceLeft) // If scroll top > space left -> fixate navigation at the bottom, otherwise scroll with the content
sideNav.css({top:46-spaceLeft+wScrollY});
if (wScrollY <= 46) // Set top strict to 46. Sometimes there is white space left, caused by the scroll event.
sideNav.css({top:46});
} else { // Scroll direction is up
var sideNavTop;
if (sideNav.offset().top < 0) {
sideNavTop = Math.pow(sideNav.offset().top); // if top is negative, make it positive for comparison
} else {
sideNavTop = sideNav.offset().top;
}
if (sideNavTop > (46+wScrollY)) // Fixate the header if top of navigation appears
sideNav.css({top:46+wScrollY});
}
} else {
sideNav.css({top:46+wScrollY}); // Fixate always
}
scrollY = wScrollY;
});
This will let you scroll your side navigation up until its end. Then fixate. If you scroll up, it will still be fixated until your reach the point, where the navigation must scrolled back to its original position.
You can check the edited version here: http://pastebin.com/Zkx4pSKe
Just copy the raw code into a blank html page and try it out.
It's a bit messy and maybe not the best solution, but it works.
Ok, here you go:
var $sidebar = $('.sidebar'),
$window = $(window),
previousScroll = 0;
$window.on('scroll', function (e) {
if ($window.scrollTop() - previousScroll > 0) {
$sidebar.css({
'top': Math.max($window.scrollTop() + $window.height() - $sidebar.outerHeight(true), parseInt($sidebar.css('top'))) + 'px'
});
} else {
$sidebar.css({
'top': Math.min($window.scrollTop(), parseInt($sidebar.css('top'))) + 'px'
});
}
previousScroll = $window.scrollTop();
});
http://jsfiddle.net/7nwzcpqk/1/
i might have misunderstood your desired result incorrectly but you can see if this works for you :
.SideNav {
position: fixed; // you currently have this as position:absolute;
}
You don't need nor a wrapper element nor jQuery. I assume that you are using a wrapper because you want to have the top bar placed there. I think there is a better way to do it by using simply three divs.
The top bar has to be fixed (to be always visible) and of full width.
The side bar also has to be fixed (to be always visible) with a top margin of the height of the top bar.
The content needs just a left padding (width of side bar) and top padding (height of top bar).
Here is the example code (http://jsfiddle.net/zckfwL4p/):
HTML
<div id="top_bar"></div>
<div id="side_bar">links here</div>
<div id="content"></div>
CSS
body {
margin:0px;
padding:0px;
}
#side_bar {
width:50px;
position: fixed;
left:0px;
top:20px;
background-color:blue;
}
#top_bar {
position:fixed;
height:20px;
left:0px;
right:0px;
background-color:red;
}
#content {
position:relative;
padding-left:55px;
padding-top:25px;
}

A cleaner way for a fixed div at bottom of the window but stays above the footer and triggers on page width

I've created a sticky bar to stay at the bottom of the window. As the user scrolls down to the bottom of the page the same bar will stay fixed until the footer shows, then removes its fixed position, temporarily, to stay above the footer until the user scrolls back up and it remains fixed again.
I only want to happen when the page is wider than 680px. Anything under that will keep the sticky bar in a default position (CSS: position:inherit).
This is the website: http://ttd.firefly-digital.co.uk
It works as expected. However, when I test on Chrome in Mac it triggers my CPU fan which suggests this not very efficient and with my limited JavaScript skills, wondered if there is a cleaner way to achieve this is?
This is the current js code:
$(window).scroll(function(event) {
var scroll = $(this).scrollTop();
var docHeight = $(document).height();
var windowHeight = $(window).height();
var footerHeight = $('.footer').height();
if(docHeight - (windowHeight + scroll) < footerHeight) {
$('.contact-bar').css({
bottom: footerHeight - (docHeight - (windowHeight + scroll))
});
} else {
$('.contact-bar').css({
bottom: 0
});
}
});
var windowWidth = $(window).width();
$(window).resize(function() {
windowWidth = $(window).width();
if(windowWidth > 680) {
$('.contact-bar').css({
position: "fixed"
});
} else {
$('.contact-bar').css({
position: "inherit"
});
}
});
CSS code
.contact-bar {
background: $contact-bar;
width: 100%;
height: 40px;
text-align: center;
position: fixed;
bottom: 0;
z-index: 10;
}
You can do it in reverse. Make it so that the bar, without position fixed, is above the footer without any JavaScript (incl. media queries). Than add a fixed class with position:fixed and bottom:0 that will be added accordingly. Like so:
.contact-bar.fixed { position:fixed; bottom:0; }
The jquery code that will trigger this, is as follows:
$(window).scroll(function (event) {
var windowTop = $(this).scrollTop();
if (windowTop >= $(".footer").offset().top) {
$(".contact-bar").addClass("fixed");
} else {
$(".contact-bar").removeClass("fixed");
}
});
Then add a few lines that the above code will only fire if the window width is > 680, either with jquery or pure javascript. For example with:
if ($(window).width() < 960) { // above function }
Do note I have not tested this, so please comment if it doesn't work. Credit: Preventing element from displaying on top of footer when using position:fixed
You better use classes to target your elements, at least to prevent jQuery from traversing the whole DOM using selectors appropriately which is good in performance.

Trigger event when user scroll to specific element - with jQuery

I have an h1 that is far down a page..
<h1 id="scroll-to">TRIGGER EVENT WHEN SCROLLED TO.</h1>
and I want to trigger an alert when the user scrolls to the h1, or has it in it's browser's view.
$('#scroll-to').scroll(function() {
alert('you have scrolled to the h1!');
});
how do I do this?
You can calculate the offset of the element and then compare that with the scroll value like:
$(window).scroll(function() {
var hT = $('#scroll-to').offset().top,
hH = $('#scroll-to').outerHeight(),
wH = $(window).height(),
wS = $(this).scrollTop();
if (wS > (hT+hH-wH)){
console.log('H1 on the view!');
}
});
Check this Demo Fiddle
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:
if (wS > (hT+hH-wH) && (hT > wS) && (wS+wH > hT+hH)){
//Do something
}
Demo Fiddle
Combining this question with the best answer from jQuery trigger action when a user scrolls past a certain part of the page
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
}
});
I think your best bet would be to leverage an existing library that does that very thing:
http://imakewebthings.com/waypoints/
You can add listeners to your elements that will fire off when your element hits the top of the viewport:
$('#scroll-to').waypoint(function() {
alert('you have scrolled to the h1!');
});
For an amazing demo of it in use:
http://tympanus.net/codrops/2013/07/16/on-scroll-header-effects/
Inview library triggered event and works well with jquery 1.8 and higher!
https://github.com/protonet/jquery.inview
$('div').on('inview', function (event, visible) {
if (visible == true) {
// element is now visible in the viewport
} else {
// element has gone out of viewport
}
});
Read this https://remysharp.com/2009/01/26/element-in-view-event-plugin
Fire scroll only once after a successful scroll
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();
}
});
You could use this for all devices,
$(document).on('scroll', function() {
if( $(this).scrollTop() >= $('#target_element').position().top ){
do_something();
}
});
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);
You can use jQuery plugin with the inview event like this :
jQuery('.your-class-here').one('inview', function (event, visible) {
if (visible == true) {
//Enjoy !
}
});
Link : https://remysharp.com/2009/01/26/element-in-view-event-plugin
This should be what you need.
Javascript:
$(window).scroll(function() {
var hT = $('#circle').offset().top,
hH = $('#circle').outerHeight(),
wH = $(window).height(),
wS = $(this).scrollTop();
console.log((hT - wH), wS);
if (wS > (hT + hH - wH)) {
$('.count').each(function() {
$(this).prop('Counter', 0).animate({
Counter: $(this).text()
}, {
duration: 900,
easing: 'swing',
step: function(now) {
$(this).text(Math.ceil(now));
}
});
}); {
$('.count').removeClass('count').addClass('counted');
};
}
});
CSS:
#circle
{
width: 100px;
height: 100px;
background: blue;
-moz-border-radius: 50px;
-webkit-border-radius: 50px;
border-radius: 50px;
float:left;
margin:5px;
}
.count, .counted
{
line-height: 100px;
color:white;
margin-left:30px;
font-size:25px;
}
#talkbubble {
width: 120px;
height: 80px;
background: green;
position: relative;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
float:left;
margin:20px;
}
#talkbubble:before {
content:"";
position: absolute;
right: 100%;
top: 15px;
width: 0;
height: 0;
border-top: 13px solid transparent;
border-right: 20px solid green;
border-bottom: 13px solid transparent;
}
HTML:
<div id="talkbubble"><span class="count">145</span></div>
<div style="clear:both"></div>
<div id="talkbubble"><span class="count">145</span></div>
<div style="clear:both"></div>
<div id="circle"><span class="count">1234</span></div>
Check this bootply:
http://www.bootply.com/atin_agarwal2/cJBywxX5Qp
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)
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.
https://www.npmjs.com/package/jquery-on-scrolled-to
It will be
$('#scroll-to').onScrolledTo(0, function() {
alert('you have scrolled to the h1!');
});
or use 0.5 instead of 0 if need to alert when half of the h1 shown.
Quick and fast implementation,
let triggered = false;
$(window).on('scroll',function() {
if (window.scrollY > ($('#scrollTo').offset().top+$('#scrollTo').outerHeight()-window.innerHeight) & !triggered){
console.log('triggered here on scroll..');
triggered = true;
}
});
using global variable triggered = false makes it just to happen once, otherwise, every time crossing past the element, this action is triggered.

Categories

Resources