I'm now struggling on a sticky element that should scroll proportionally on a page. From top to the footer despite the page's height. So it's actually stick to the top of the scrollbar in the beginning and then to the bottom at the end. Or it just follows the scroll wheel.
Is there any chance to do it with jQuery ?
Below is the starting code with usual "sticky" div.
$(window).scroll(function(){
$("#sticky")
.animate({"marginTop":($(window).scrollTop())+"px"}, "fast");});
https://jsfiddle.net/flakessp/cxr78xc8/
Do you mean something like this?
$(window).scroll(function() {
// calculate the percentage the user has scrolled down the page
var scrollPercent = 100 * $(window).scrollTop() / ($(document).height() - $(window).height());
// get the height of the sticky element
var stickyHeight = $('.sticky').height();
// calculate the margin top of the sticky element
var marginTop = (($(window).height() - stickyHeight) / 100) * scrollPercent;
// set margin top of sticky element
$('.sticky').css('marginTop', marginTop);
});
Fiddle
So, this one was a little tricky, but here it is:
JSFiddle example
Basically, we're using a couple things here:
Scroll direction detection with this section:
var lastScrollPos = 0,
...
lastScrollPos < $window.scrollTop()
Then, you forgot to factor in things like document and window height. scrollTop does exactly what it says and only gives you the number from the top of the viewport to the top of the document. So we add in the visible height as well with $(window).height().
Then it's just a matter of whether we factor in the height of the element too (hence the ternary operator adding 0 or $('#sticky').height() depending on our scroll direction detection from the earlier section.
Anyhow, here's the full JS:
var lastScrollPos = 0,
$window = $(window),
$document = $(document),
$sticky = $('#sticky');
$(window).scroll(function(){
$sticky
.animate({"top":((($window.scrollTop() + (lastScrollPos < $window.scrollTop() ? $window.height() - $sticky.height() : 0))/$document.height()) * 100)+"%"}, "fast");
});
Iam using mCustomScrollbar , I want to know whether my scroll bar position is at bottom using jquery.How is that possible?Can i use ordinary bottom check usage in jquery or any functions are available in the mCustomScrollbar library?
Look at callbacks example - there is Scroll percentage that displays % of scrolled. Open HTML source and you will see that it's uses whileScrolling callback: $("#mcs-top-pct").text(this.mcs.topPct+"%");, so when this.mcs.topPct is 100, then container is scrolled to bottom :)
I used to myself something like:
$('#someElement').mCustomScrollbar({theme: "minimal"});
and after, you can get scrollTop using this code:
var scrollTop = $('#someElement').find(".mCSB_dragger").position().top;
You can calculate scrollTop from dragger's top position:
var $scrollerOuter = $( '.mCustomScrollbar' );
var $dragger = $scrollerOuter.find( '.mCSB_dragger' );
var scrollHeight = $scrollerOuter.find( '.mCSB_container' ).height();
var draggerTop = $dragger.position().top;
var scrollTop = draggerTop / ($scrollerOuter.height() - $dragger.height()) * (scrollHeight - $scrollerOuter.height());
I'm trying to get an div to animate 0% - 100% relative to the percentage scrolled of an element.
Now I've set up a few variables, but I'm having trouble trying to calculate the height of one by percentage.
We can set the starting width quite easily and detect the scroll easily enough too, as can we get the height of the element that'll trigger the animation, I just can't get it as a percentage.
If I can figure out how to return the percent of conheight scrolled then this should be easy.
$(window).scroll(function() {
// calculate the percentage the user has scrolled down the page
var scrollPercent = ($(window).scrollTop() / $(document).height()) * 100;
$('.bar-long').css('width', scrollPercent +"%" );
});
Here's a jsfiddle, http://jsfiddle.net/SnJXQ/
This is animating bar-long based on the percent scrolled of the body element.
Animates from 0% - 100% (well, it doesn't really, but I can't figure out why).
What I'd like to do is get scroll percent of the .post div, then animate bar-long relative to that.
ie. Scrolled 10% of .post, .bar-long is 10% width, scrolled 70% of .post, .bar-long is 70% width.
Demo
Your problem is the same as How to get horizontal scrolling percentage of an HTML element in JavaScript?, but vertically.
Then, to get the vertically scrolled percentage, use
/* JS */ var scrollPercentage = 100 * containeR.scrollTop / (containeR.scrollHeight-containeR.clientHeight);
/*jQuery*/ var scrollPercent = 100 * $(containeR).scrollTop() / ($(containeD).height() - $(containeR).height());
In your case, containeR = window; containeD = document:
var scrollPercent = 100 * $(window).scrollTop() / ($(document).height() - $(window).height());
Ok I see what you are trying to achieve....in fact I just did something very similar. Most solutions I found out there also were only for full page examples with window or document properties. Instead I needed this in a specific div which in my case was actually used to update the horizontal position of another div.
First, you are going to want the scroll event attached to your $('.post')
Next, the height of the $('.content') is going to equal your actual Scroll Height
Lastly, apply your percentage formula : (Y / (scrollHeight - postHeight)) * 100 = scrollPercent
So instead of using document or window attributes your code should be as follows:
$('.post').scroll(function() {
var currY = $(this).scrollTop();
var postHeight = $(this).height();
var scrollHeight = $('.content').height();
var scrollPercent = (currY / (scrollHeight - postHeight)) * 100;
});
You can find the fiddle here: JS Fiddle For Div Scroll Percentage
The current project where I have implemented this is located here: Vertical Scroll Drives Horizontal Position
I hope this solves your problem :)
Let's say you want to keep track of the scroll of some document found in some IFrame in your page.
object.addEventListener("scroll", documentEventListener, false);
Then your event listener should look like this:
function documentEventListener(){
var currentDocument = this;
var docsWindow = $(currentDocument.defaultView); // This is the window holding the document
var docsWindowHeight = docsWindow.height(); // The viewport of the wrapper window
var scrollTop = $(currentDocument).scrollTop(); // How much we scrolled already, in the viewport
var docHeight = $(currentDocument).height(); // This is the full document height.
var howMuchMoreWeCanScrollDown = docHeight - (docsWindowHeight + scrollTop);
var percentViewed = 100.0 * (1 - howMuchMoreWeCanScrollDown / docHeight);
console.log("More to scroll: "+howMuchMoreWeCanScrollDown+"pixels. Percent Viewed: "+percentViewed+"%");
}
I want to detect whenever the user changes the height of the scrollbar. Right now the script I have detects it once (when the user moves the scrollbar down) but when you move the scrollbar again nothing happens. My logic is that when the user moves the scrollbar to a position greater than 296 a div appears using animate(), and this works. But when the user moves the scrollbar to a position less than 296 the div should disappear using animate(). My code is below. Can anyone help? Thanks a lot.
$(window).scroll(function(){
var wintop = $(window).scrollTop();
var docheight = $(document).height();
var winheight = $(window).height();
var newWidthGrow = 500;
var smallHeight = 0;
var smallWidth = 0;
if(wintop > 296)
{
$("#slidebottom").animate({height:docheight +"px", width:newWidthGrow + "px"},'fast');
}
if(wintop < 296)
{
$("#slidebottom").animate({height:smallheight +"px", width:smallWidth + "px"}, 'fast');
}
});
Two issues here:
You initiate a variable named smallHeight but you use smallheight, which causes an error.
You should add the .stop()-method before running another animation like that:
$("#slidebottom").stop().animate();
And you should consider to run each animation only once and not any time the scroll event is fired. A boolean can be helpful here:
if(wintop < 296 && expanded) {
expanded = false;
$("#slidebottom").stop().animate();
}
Demo
Try before buy
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.