I'm using the following pen by Bramus to animate(FadeInUp) divs when entering the viewport. However currently the div only starts fading in when the div is completely in the viewport. What I need is the flexibility to start the animation when a div is a certain pixels inside the viewport. For example it will start the animation FadeInUp when the div is 100 pixels in the viewport. How can I do this with the current code/pen I'm using (see code below)?
Is this also possible with percentages? F.e. when a div is 20% in viewport the animation starts?
Thanks.
jQuery(function($) {
// Function which adds the 'animated' class to any '.animatable' in view
var doAnimations = function() {
// Calc current offset and get all animatables
var offset = $(window).scrollTop() + $(window).height(),
$animatables = $('.animatable');
// Check all animatables and animate them if necessary
$animatables.each(function(i) {
var $animatable = $(this);
if (($animatable.offset().top + $animatable.height() - 20) < offset) {
$animatable.removeClass('animatable').addClass('animated');
}
});
};
// Hook doAnimations on scroll, and trigger a scroll
$(window).on('scroll', doAnimations);
$(window).trigger('scroll');
});
Offsetting is already foreseen in the code. Tweak the value of 20 in this line:
if (($animatable.offset().top + $animatable.height() - 20) < offset) {
You might also need to change the - sign to a + to suit your needs.
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
function scrollContent(){
var div = $('#scrolling-content'),
ul = $('ul.image'),
// unordered list's left margin
ulPadding = 0;
//Get menu width
var divWidth = div.width();
//Remove scrollbars
div.css({overflow: 'hidden'});
//Find last image container
var lastLi = ul.find('li:last-child');
//When user move mouse over menu
div.mousemove(function(e){
//As images are loaded ul width increases,
//so we recalculate it each time
var ulWidth = lastLi[0].offsetLeft + lastLi.outerWidth() + ulPadding;
var left = (e.pageX - div.offset().left) * (ulWidth-divWidth) / divWidth;
div.scrollLeft(left);
});
}
This is how I scroll my image list. The problem is that #scrolling-content element's size is dynamic. It changes on window resize. Here;
$(window).resize(function() {
$("#scrolling-content").css("width",$(window).width() + "px");
$("#scrolling-content").css("height",($(window).height()-400) + "px");
});
So it has to recalculate the left value when user changes windows size. How sould I change script to do that? Recalling scrollContent() function with window.resize function is a noob solution I guess. And it creates conflict for IE.
You could set the width on resize and make your function call the variable like so. This method turns your function into a js object and the window update resets the width var inside that object. Course now you call the function like this: scrollContent.scroll();
var scrollContent = {
width: 0,
scroll:function(){
var div = $('#scrolling-content'),
ul = $('ul.image'),
// unordered list's left margin
ulPadding = 0;
//Get menu width
scrollContent.width = div.width();
//Remove scrollbars
div.css({overflow: 'hidden'});
//Find last image container
var lastLi = ul.find('li:last-child');
//When user move mouse over menu
div.mousemove(function(e){
//As images are loaded ul width increases,
//so we recalculate it each time
var left = (e.pageX - div.offset().left) * (ulWidth-scrollContent.width) / scrollContent.width;
div.scrollLeft(left);
});
}
};
$(window).resize(function() {
$("#scrolling-content").css("width",$(window).width() + "px");
$("#scrolling-content").css("height",($(window).height()-400) + "px");
scrollContent.width = $(window).width();
});
You can also just declare a standard js var and use that to keep things simple. I just prefer working with js objects to eliminate possible var interference.
At my website, I try to accomplish (with javascript) that the footer height changes if the page height is larger then a specific value (907 pixels, the body height). It also needs to change if the page height changes (so if the viewer changes his client height).
I use jQuery to get the page height, but I need it's continuously checked, and not only when the page loads.
This is the snippet I use:
$(document).ready(function(){
var windowheight = $(window).height();
if(windowheight >= "907") {
var extrafooterheight = windowheight - 907;
$('#footer').height(40 + extrafooterheight);
$('body').height(907 + extrafooterheight);
}
});
Thanks for your help.
I suggest attaching to the resize event of the window using jQuery:
$(document).ready(function(){
$(window).resize(function() {
var windowheight = $(window).height();
if(windowheight >= "907") {
var extrafooterheight = windowheight - 907;
$('#footer').height(40 + extrafooterheight);
$('body').height(907 + extrafooterheight);
}
});
});
Take a look at the jQuery resize() docs.
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.