I was playing with my new Nexus 7 (I really wanted to own a real Android device) and I noticed a neat little effect in the Google+ app that comes with it. As you swipe down, new modules of content slide up into place. Video is best here:
We can do that! It’s a pretty easy two-step process:
When the window scrolls, check if module is visible
jQuery has a :visible selector, but that isn’t what we need here. We need to see if any part of the element is within the visual viewport. That is, an element may be technically visible, but located off-screen. We can figure out if an element is within the visual viewport through math. How wide and tall is the window, how far down is it scrolled, how wide and tall is the element, where is it positioned, etc. Fortunately that math is summed up super nicely by the jquery-visible plugin.
(function($) {
/**
* Copyright 2012, Digital Fusion
* Licensed under the MIT license.
* http://teamdf.com/jquery-plugins/license/
*
* @author Sam Sehnert
* @desc A small plugin that checks whether elements are within
* the user visible viewport of a web browser.
* only accounts for vertical position, not horizontal.
*/
$.fn.visible = function(partial) {
var $t = $(this),
$w = $(window),
viewTop = $w.scrollTop(),
viewBottom = viewTop + $w.height(),
_top = $t.offset().top,
_bottom = _top + $t.height(),
compareTop = partial === true ? _bottom : _top,
compareBottom = partial === true ? _top : _bottom;
return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
};
})(jQuery);
All that’s left for us is using it when the window “scrolls” to add a class name.
$(window).scroll(function(event) {
$(".module").each(function(i, el) {
var el = $(el);
if (el.visible(true)) {
el.addClass("come-in");
}
});
});
CSS will handle the slide-in:
.come-in {
transform: translateY(150px);
animation: come-in 0.8s ease forwards;
}
.come-in:nth-child(odd) {
animation-duration: 0.6s; /* So they look staggered */
}
@keyframes come-in {
to { transform: translateY(0); }
}
If elements are already visible, let them be
So we don’t trigger the animation on the already visible modules on the very first swipe, we’ll add a class name to remove that animation. And we can get a bit more efficient here too, “caching” selectors so we don’t have to find them on each scroll event (which fires tons of times).
var win = $(window);
var allMods = $(".module");
// Already visible modules
allMods.each(function(i, el) {
var el = $(el);
if (el.visible(true)) {
el.addClass("already-visible");
}
});
win.scroll(function(event) {
allMods.each(function(i, el) {
var el = $(el);
if (el.visible(true)) {
el.addClass("come-in");
}
});
});
That’ll do:
See the Pen
Slide in from bottom boxes by Chris Coyier (@chriscoyier)
on CodePen.
And note, the CSS transition could be anything. They could slide in from the sides, they could use scaling and opacity and look like they were flying in. There could be color involved. Whatevs.
Cool, but the slide effect only works the first time you scroll down…
Yep, that’s how it works in the G+ app. Like a visual indicator “this is new, you haven’t seen this yet.”
Check out this fork for a different effect that works going down and up.
I’m also sure there is an AJAX-y infinite scroll thing going on here. It appears that there is a lot more animation on my Nexus 10. It like comes from above and up… if that makes any sense. Like a 3D transition.
You could get it go to both ways by tying in the visible plugin with the toggleClass function. For instance. Just be warned that it’s a strange effect when you scroll back up – not intuitive at all.
Agree with Anja.
The “this is new, you haven’t seen this yet.”… I think this is a very subjective interpretation.
I personally see this behavior as a mere enhancement to the UI experience, that’s it.
And if you’ve ever seen the iPhone/iPad app Vodio, it has a very similar effect when scrolling down, but it also has it when scrolling up.
It honestly feels more “complete”.
Go ahead, check out Vodio and see for yourselves.
I’m trying to use something like this on a website I’m working on but I can’t get it to work. First I thought it was me, but I tried copying the whole working code from codepen, and it does all the animation instantly and not on scroll.
What’s wrong here?
Pretty nifty sure we will end seeing it on a ton of grid based sites now.
Awesome Chris :D
Glad to see how this was done, the simplest route is usually the correct one
Works great on desktop, but in Chrome on my HTC One X the box first appears in its final position before jumping down and doing the slide in animation to it’s final position. Does it do this on the Nexus 7 also?
Exactly the same problem with mobile safari here. Have you figured out what the problem is?
Would it be beneficial to remove the seen element from the cached array so that if you have a page with hundreds of elements, the array that you’re iterating over gets smaller and smaller as you go?
Very smart
Nicely done! A small and picky observation. It seems a bit confusing (to me) to call the removed classes “module.” If you’re working with other devs, I might class those elements something like “off-window” or to go with the “come-in” theme, “on-waitlist”. ^_^ :
Love this. I’ll definitely be using this sometime in the future!
Heads up
“how fall down is it scrolled,”
should properly be
“how far down is it scrolled,”
Thanks. Burying this because it’s fixed.
Ha ha ,”I really wanted to own a real Android device” :D Nexus 7 is awesome indeed :)
sorry guys , but I can’t get the output mind to point out the error that i have made ?
is it the correct way to use the visible plugin ?
regards
John
Hey, i get an error too…
Check mine –> http://goo.gl/Niqiz
Can you tell me what’s wrong with that?
neat trick. Works in desktop Windows Chrome , but not in Firefox. OK – that’s not a big problem, it’s just an enhancement. But would it be possible to having it run in Firefox too?
Works on my desktop Firefox without any problems.
try going through your apache server, assuming you have one. I find firefox doesn’t initialize js very well when working offline. Not sure why this is but that’s the ix.
Nice bit of work, i bought a nexus 4 the other day as wanted a android phone (always been iphone) and i saw this and other things a few weeks ago and they have added soem nice little effects to keep you interest, most people wont notice (the wife). Great piece of snippet
Nice, I always like this effect, glad to see a simple way to mimick it.
It seems like it only works in the opposite direction in Safari
The one on this page – yes! Even in Chrome. The JSFiddle version seems to work in both directions :-)
WOW! I just made a note yesterday, to figure out how to do this to show a long list of portfolio items for a client. Thank you!
This jQuery plugin doesn’t seem to work for me on Safari Mobile or Chrome Mobile (on my iPhone5). Has anyone else been able to see this plugin work on a mobile device? I used it a few weeks ago on a pen of mine and noticed the same thing: http://codepen.io/dganoff/full/jtvay
Don’t most mobile devices pause animations on scroll though?
Came here to say this as mobile Safari does this.
This is pretty awesome :P Do you reckon it could be used with lazy loading a gallery or WordPress posts (for example)?
That is pretty nice! I’m going to implement this on my next grid based design.
Just added the google+ app to my ipad, and it’s go the same effect but even better, they fly in. Awesome
I’m going to implement this on my next grid based design.
Here is my fork. Now animation works in both directions.
http://codepen.io/PawelGIX/pen/kmhLl
Yo, Pawel, this is really great job!!! It really works both ways!!!
This is EXACTLY how I think this effect should work.
Meh. Wayyy too much animation going on here. I much prefer the limited animation on Google+ that’s only present for new content.
Same here. Google don’t do things to “make cool animations, lol its fun!”. This is a feature to help user to know when the new content begin.
This is EXACTLY how I think this effect should NOT work.
This really looks great, and it is instant inspiration. Only one potential downfall – as i am finishing site that slightly resembles this, but only with four squares, (temp location Mambo Stars temporary) and you can’t even imagine how terrifying it looks in IE less then 10. Conditional stylesheet must be done from scratch, and it is actually a totally new site, this one I don’t even want to imagine.
Chris, IE7 is always a hair-pulling experience :)
Very clever, and nice! You don’t need to see the animation once you’ve seen it once already. It’s perfect like this
This animation is pretty for sure. I really like it but I wonder if it’s useful. You know you didn’t saw what’s hidden even without this animation. Doesn’t make sense to me.
I am so lost why this isn’t working for me, even when I try to make the same exact thing that’s on Codepen.
Nice stuff! I had some trouble with using the code. (Probably the same problem as Kris and other persons above have)
The solution:
The codepen uses SCSS, I think it isn’t nessecary
You have enabled the ‘prefix free’ option in codepen, this means codepen will add the neccescary prefixes. When you copy the code to your own server, you will need to add the prefixes.
Here is a codepen that works in Chromium and Firefox
Thanks for your answer! It helped me debug the problem I was having :)
Nice effect, really thanks!
Awesome .. got it working on desktops but not in mobile? Any way of making this work for mobile?
Thanks :)
It’s ok when you scroll slowly, but how does it looks when fast scrolling, especially on smartphones.
Animation are locked when scrolling on iPhone too.
This is great, love the implementation! For more advanced ‘is it visible’, I suggest you check out jQuery.fracs.
Working also with Zepto!
Just thought I’d mention that this doesn’t work with Canary as it doesn’t allow scripts with the wrong MIME type anymore.
Sorry I meant the CodePen example doesn’t work, not the method.
See also stroll.js: http://lab.hakim.se/scroll-effects/
On Chrome when the class
.come-in
is applied the element appears in its final position for an instant before being translated down 150px. It seems chrome draws the<div>
on-screen before translating it.This is rather visually jarring and slightly ruins the effect. To fix this the element should be invisible by default:And then after the js has applied the class
.come-in
it can undo thevisibility
attribute with a line of jQuery:The visibility detection plugin ignores the css visibility attribute so this shouldn’t interfere with that, and if the user has javascript disabled then
.come-in
won’t ever be applied and so no content will ever be hidden!Oh actually,
visibility: hidden;
should be applied to.module
instead. Got my classes mixed up!If you want to ensure compatibility with non-js users you should apply
visibility: hidden;
using javascript rather than css.Combined with the js in my above comment this should work as promised! :P
I wanted to do this via ajax, such that when user scroll down it automatically fetches result in my case Images and display it with the same css3 effect. Is there any way ?
Thanks for the script. It’s working! I now only have one question. Is it possible to trigger the event a bit later (give it an offset of a certain pixels / percentage of the screen height). So the event is triggered when the element is scrolled at a certain “view height”?
Thanks for your effort
Is not this a little bit slow?
I don’t know why but
if (el.visible(true)) {
el.addClass("come-in");
}
this part triggers my recalculate style (chrome timeline), even though I don’t even have styled my
come-in
class. and when I scroll enough, like more then 20 elements (big and havy) its just terrible experiance.This script doesn’t work. strange. I compiled that SCSS to CSS, Included jQuery, copied exact same JS and HTML on plain text file, made a simple demo, but doesn’t work. anyone have any clue?
Same issue here. When I do get it working it only works if you reload the bottom of the page and scroll up.
I have been struggling with that script to work for few hours until i removed body height:100%; now it is working perfectly.
what is the name of this new effect i have seen it on many websites
its not working…pls help me
Doing a browserstack test, and in older versions of IE it doesn’t work.. that’s fine but the fall back has one row of boxes with a large space at the top.
Any ideas on how to get it to fall back a little more gracefully
Thanks
Hello Chris,
I want to try this effect but facing problem.
I tried it by copying all these codes but nothing happens.
What should i do to run this effect.
Awesome!
I have one additional optimization: on Resize: