Make html element stay in place when scrolled past - javascript

How does one make an html element not become fixed until it has been scrolled to? So while the user is scrolling it will be in normal position, but it won't go out of the screen after the user has scrolled past it?

Attach a listener to the onscroll event, and if the scrollTop is greater than the element's Y position, set it to position: fixed.

I've used this code before:
http://www.webdeveloperjuice.com/2011/08/07/how-to-fix-element-position-after-some-scroll-using-jquery/
(function($){
$.fn.scrollFixed = function(params){
params = $.extend( {appearAfterDiv: 0, hideBeforeDiv: 0}, params);
var element = $(this);
if(params.appearAfterDiv)
var distanceTop = element.offset().top + $(params.appearAfterDiv).outerHeight(true) + element.outerHeight(true);
else
var distanceTop = element.offset().top;
if(params.hideBeforeDiv)
var bottom = $(params.hideBeforeDiv).offset().top - element.outerHeight(true) - 10;
else
var bottom = 200000;
$(window).scroll(function(){
if( $(window).scrollTop() > distanceTop && $(window).scrollTop() < bottom )
element.css({'position':'fixed', 'top':'5px'});
else
element.css({'position':'static'});
});
};
})(jQuery);
Then just call the elements:
$(document).ready( function(){
$("#scrollingDiv").scrollFixed({appearAfterDiv:'.sidebar p', hideBeforeDiv:'.footer'});
$("#scrollingDiv1").scrollFixed({hideBeforeDiv:'.footer'});
});

Have a look at the jQuery Scrollfollow plugin. I have used this to achieve that effect conveniently.
You simply call it on the element that you want to stay in view:
<script type="text/javascript">
$( '#example' ).scrollFollow();
</script>
Easing, position and other parameters can be configured.

Related

Sticky div scrolls too far

I have a jquery code which makes an existing element follow the scroll of the user. I want it to stop when reaching a certain element #header-line, but it's not consistent. On some PDPs it scrolls and stops there, on others, it scrolls past the line.
Page: https://www.norli.no/to-pappaer
(Code is not activated here)
jQuery
require(['jquery'], function($){
$(document).ready(function() {
(function($) {
var element = $('.product-add-form'),
originalY = element.offset().top;
var hr = $('#header-line > hr');
topOfLine = hr.offset().top;
var topMargin = 250;
element.css('position', 'relative');
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
var nextPosition = scrollTop - originalY + topMargin;
var maxPositionAllowed = topOfLine - 1000;
element.stop(false, false).animate({
top: scrollTop + 250 < originalY ? 0 : Math.min(nextPosition, maxPositionAllowed )
}, 0);
});
})(jQuery);
});
});
You could definitely take advantage of using position: sticky if you are able to make sure all parent elements of the sticky element have overflow: visible
In that link you posted, if you wanted .product-add-form to be position: sticky you would have to make sure .off-canvas-wrapper has the overflow: hidden changed to overflow: visible.
I made an example fiddle of that page you shared so you could see how easy it would be to make that side form sticky.
https://jsfiddle.net/treckstar/d30phae8/8/

add element offset to jQuery offset calculations

I am rather new to jquery and i'm trying to find the right offset for a div element inside the body. I want to make this div element sticky whenever I scroll down and pass the top offset of this element.
I followed this tutorial: https://www.youtube.com/watch?v=utonytGKodc and it works but I have a metaslider in my header and the width/height of this element is left out of the calculations to find the right offset....
the result is that my element becomes a sticky element way to soon, is there a way I can manualy add the sliders coordinates (offset) to the offset calculation of the element i want to make sticky?
var offerteOffset = jQuery(".agendawrap").offset().top //+ metaslider coordinates??;
alert(offerteOffset);
jQuery(window).scroll(function() {
var scrollPos = jQuery(window).scrollTop();
if (scrollPos >= offerteOffset) {
jQuery(".agendawrap").addClass("fixed");
} else {
jQuery(".agendawrap").removeClass("fixed");
}
});
I cant believe people make such bad tutorials.
First of all: dont write jQuery all the time. Have a look at this thread.
Basically it says: use an invoking function with an own scope:
(function($) { /* all your jQuery goes here */ })(jQuery);
So you can just type $ instead of jQuery.
To your original question:
(function($) {
$(function() { // document ready...
var scrollTolerance = 50,
agendawrap = $(".agendawrap"),
offerteOffset = agendawrap.offset().top;
$(window).on('scroll', function() {
var scrollPos = $(window).scrollTop();
// OR: if (scrollPos - scrollTolerance >= offerteOffset) {
if (scrollPos + scrollTolerance >= offerteOffset) {
agendawrap.addClass("fixed");
}
else {
agendawrap.removeClass("fixed");
}
});
});
})(jQuery);

Determine the id of the div that has been scrolled to bottom

simple question, easy points, cannot find the answer in SO. The javascript function below alerts when a user scrolls to the bottom of a div. I have many divs, but I only want the alert to run when a div id=imageloc is scrolled.
$(window).scroll( function() {
if ( document.documentElement.clientHeight + $( document ).scrollTop() >= document.body.offsetHeight ) {
if (this.id == "imageloc" ) {
alert("bottom of the page.");
}
}
});
The javascript function below alerts when a user scrolls to the
bottom of a div. I have many divs, but I only want the alert to run
when a div id=imageloc is scrolled.
Maybe I have misunderstood, but it's phrased like you have many scrollable divs and want to do something if one of them is scrolled to the bottom. Then you should listen to scroll event on this particular div:
$("#imageloc").scroll( function(e) {
if ( this.scrollTop >= this.scrollHeight - this.offsetHeight ) {
console.log( 'bottom' )
}
});
http://jsfiddle.net/aheh5/
If you want to do something when the document has been scrolled past the bottom of a particular div try this: http://jsfiddle.net/aheh5/1/ (it will, however, trigger every time the user scrolls the window and #imageloc is above the viewport).
Use like this
$(window).scroll(function() {
var winTop = $(this).scrollTop();
var $divs = $('div');
var top = $.grep($divs, function(item) {
return $(item).position().top <= winTop;
});
alert($(top).attr('id'));
});
You can try something like this,
var imgLocTop = $('#imageloc').offset().top ;
var $window = $(window);
var limit = Math.abs($window.height() - imgLocTop);
$window.scroll( function() {
if($window.scrollTop() >= limit) {
alert('Reached the required div');
}
});
Demo

javascript scroll to bottom of div class

Hi I am trying to implement a simple chatbox in django and was wondering how to scroll to the bottom of a div class using javascript? Basically when the page loads I would like so that users can see the most recent message sent to them instead of the least recent.
I had to do this recently for a similar thing. I found a basic jquery plug-in that will smoothly scroll an element onto the screen.
(function($) {
$.fn.scrollMinimal = function() {
var cTop = this.offset().top;
var cHeight = this.outerHeight(true);
var windowTop = $(window).scrollTop();
var visibleHeight = $(window).height();
if (cTop < windowTop) {
$('body').animate({'scrollTop': cTop}, 'slow', 'swing');
} else if (cTop + cHeight > windowTop + visibleHeight) {
$(jQuery.browser.webkit ? "body": "html")
.animate({'scrollTop': cTop - visibleHeight + cHeight}, 'slow', 'swing');
}
};
}(jQuery));
which is used like this:
$('#chat').scrollMinimal();
Well, the basic script is set the scrollTop equal to scrollHeight, so you need a script like this:
var DIV = document.getElementById('theDIVElement');
DIV.scrollTop = DIV.scrollHeight;
You only need to change theDIVElement to your DIV id.
This is the script I used in my chat:
<SCRIPT LANGUAGE="JavaScript">
<!--
function myScroll() {
window.scrollBy(0,01)
setTimeout('myScroll()',100); }
if (document.layers || document.all)
myScroll()
//--></SCRIPT>
This is also nice for when new messages are added, if you scroll to the bottom too fast, it's hard on your eyes while you're trying to read.

How do I get an element to scroll into view, using jQuery?

I have an HTML document with images in a grid format using <ul><li><img.... The browser window has both vertical & horizontal scrolling.
Question:
When I click on an image <img>, how then do I get the whole document to scroll to a position where the image I just clicked on is top:20px; left:20px ?
I've had a browse on here for similar posts...although I'm quite new to JavaScript, and want to understand how this is achieved for myself.
There's a DOM method called scrollIntoView, which is supported by all major browsers, that will align an element with the top/left of the viewport (or as close as possible).
$("#myImage")[0].scrollIntoView();
On supported browsers, you can provide options:
$("#myImage")[0].scrollIntoView({
behavior: "smooth", // or "auto" or "instant"
block: "start" // or "end"
});
Alternatively, if all the elements have unique IDs, you can just change the hash property of the location object for back/forward button support:
$(document).delegate("img", function (e) {
if (e.target.id)
window.location.hash = e.target.id;
});
After that, just adjust the scrollTop/scrollLeft properties by -20:
document.body.scrollLeft -= 20;
document.body.scrollTop -= 20;
Since you want to know how it works, I'll explain it step-by-step.
First you want to bind a function as the image's click handler:
$('#someImage').click(function () {
// Code to do scrolling happens here
});
That will apply the click handler to an image with id="someImage". If you want to do this to all images, replace '#someImage' with 'img'.
Now for the actual scrolling code:
Get the image offsets (relative to the document):
var offset = $(this).offset(); // Contains .top and .left
Subtract 20 from top and left:
offset.left -= 20;
offset.top -= 20;
Now animate the scroll-top and scroll-left CSS properties of <body> and <html>:
$('html, body').animate({
scrollTop: offset.top,
scrollLeft: offset.left
});
Simplest solution I have seen
var offset = $("#target-element").offset();
$('html, body').animate({
scrollTop: offset.top,
scrollLeft: offset.left
}, 1000);
Tutorial Here
There are methods to scroll element directly into the view, but if you want to scroll to a point relative from an element, you have to do it manually:
Inside the click handler, get the position of the element relative to the document, subtract 20 and use window.scrollTo:
var pos = $(this).offset();
var top = pos.top - 20;
var left = pos.left - 20;
window.scrollTo((left < 0 ? 0 : left), (top < 0 ? 0 : top));
Have a look at the jQuery.scrollTo plugin. Here's a demo.
This plugin has a lot of options that go beyond what native scrollIntoView offers you. For instance, you can set the scrolling to be smooth, and then set a callback for when the scrolling finishes.
You can also have a look at all the JQuery plugins tagged with "scroll".
Here's a quick jQuery plugin to map the built in browser functionality nicely:
$.fn.ensureVisible = function () { $(this).each(function () { $(this)[0].scrollIntoView(); }); };
...
$('.my-elements').ensureVisible();
After trial and error I came up with this function, works with iframe too.
function bringElIntoView(el) {
var elOffset = el.offset();
var $window = $(window);
var windowScrollBottom = $window.scrollTop() + $window.height();
var scrollToPos = -1;
if (elOffset.top < $window.scrollTop()) // element is hidden in the top
scrollToPos = elOffset.top;
else if (elOffset.top + el.height() > windowScrollBottom) // element is hidden in the bottom
scrollToPos = $window.scrollTop() + (elOffset.top + el.height() - windowScrollBottom);
if (scrollToPos !== -1)
$('html, body').animate({ scrollTop: scrollToPos });
}
My UI has a vertical scrolling list of thumbs within a thumbbar
The goal was to make the current thumb right in the center of the thumbbar.
I started from the approved answer, but found that there were a few tweaks to truly center the current thumb. hope this helps someone else.
markup:
<ul id='thumbbar'>
<li id='thumbbar-123'></li>
<li id='thumbbar-124'></li>
<li id='thumbbar-125'></li>
</ul>
jquery:
// scroll the current thumb bar thumb into view
heightbar = $('#thumbbar').height();
heightthumb = $('#thumbbar-' + pageid).height();
offsetbar = $('#thumbbar').scrollTop();
$('#thumbbar').animate({
scrollTop: offsetthumb.top - heightbar / 2 - offsetbar - 20
});
Just a tip. Works on firefox only
Element.scrollIntoView();
Simple 2 steps for scrolling down to end or bottom.
Step1: get the full height of scrollable(conversation) div.
Step2: apply scrollTop on that scrollable(conversation) div using the value
obtained in step1.
var fullHeight = $('#conversation')[0].scrollHeight;
$('#conversation').scrollTop(fullHeight);
Above steps must be applied for every append on the conversation div.
After trying to find a solution that handled every circumstance (options for animating the scroll, padding around the object once it scrolls into view, works even in obscure circumstances such as in an iframe), I finally ended up writing my own solution to this. Since it seems to work when many other solutions failed, I thought I'd share it:
function scrollIntoViewIfNeeded($target, options) {
var options = options ? options : {},
$win = $($target[0].ownerDocument.defaultView), //get the window object of the $target, don't use "window" because the element could possibly be in a different iframe than the one calling the function
$container = options.$container ? options.$container : $win,
padding = options.padding ? options.padding : 20,
elemTop = $target.offset().top,
elemHeight = $target.outerHeight(),
containerTop = $container.scrollTop(),
//Everything past this point is used only to get the container's visible height, which is needed to do this accurately
containerHeight = $container.outerHeight(),
winTop = $win.scrollTop(),
winBot = winTop + $win.height(),
containerVisibleTop = containerTop < winTop ? winTop : containerTop,
containerVisibleBottom = containerTop + containerHeight > winBot ? winBot : containerTop + containerHeight,
containerVisibleHeight = containerVisibleBottom - containerVisibleTop;
if (elemTop < containerTop) {
//scroll up
if (options.instant) {
$container.scrollTop(elemTop - padding);
} else {
$container.animate({scrollTop: elemTop - padding}, options.animationOptions);
}
} else if (elemTop + elemHeight > containerTop + containerVisibleHeight) {
//scroll down
if (options.instant) {
$container.scrollTop(elemTop + elemHeight - containerVisibleHeight + padding);
} else {
$container.animate({scrollTop: elemTop + elemHeight - containerVisibleHeight + padding}, options.animationOptions);
}
}
}
$target is a jQuery object containing the object you wish to scroll into view if needed.
options (optional) can contain the following options passed in an object:
options.$container - a jQuery object pointing to the containing element of $target (in other words, the element in the dom with the scrollbars). Defaults to the window that contains the $target element and is smart enough to select an iframe window. Remember to include the $ in the property name.
options.padding - the padding in pixels to add above or below the object when it is scrolled into view. This way it is not right against the edge of the window. Defaults to 20.
options.instant - if set to true, jQuery animate will not be used and the scroll will instantly pop to the correct location. Defaults to false.
options.animationOptions - any jQuery options you wish to pass to the jQuery animate function (see http://api.jquery.com/animate/). With this, you can change the duration of the animation or have a callback function executed when the scrolling is complete. This only works if options.instant is set to false. If you need to have an instant animation but with a callback, set options.animationOptions.duration = 0 instead of using options.instant = true.

Categories

Resources