Loading Effects for Grid Items with CSS Animations

Some inspiration for loading effects of grid items using CSS animations.

Grid Loading Effects

Today we’d like to share some loading effects for grid items with you. The idea is to show items in a grid with an animation once they are in the viewport. The possibilities are infinite and we’d like to give you some inspiration. Some of the effects are from the awesome CSS3 scroll effects by Hakim El Hattab and the idea is inspired by the tile animation seen in the Google Plus app.

Since Masonry is a popular library for laying out grids, we thought it might be a good idea to use it in this demo. If you’d like to use something else or no library at all, you’ll have to remove the initialization from the script and adjust the selectors etc. That should be pretty straightforward.

Please note: this only works as intended in browsers that support the respective CSS properties. Modern browsers only!

The beautiful illustrations featured in the demos are by Erika Mackley. Visit her website Erika Noel Design or check out her shop. If you’d like your artwork to be featured in one of our demos just contact us.

So, we’ll use an unordered list for the grid and we’ll simply add the respective effect class:

<ul class="grid effect-4" id="grid">
	<li><a href="http://drbl.in/fWMM"><img src="images/1.jpg"></a></li>
	<li><a href="http://drbl.in/fWPV"><img src="images/2.jpg"></a></li>
	<li><a href="http://drbl.in/fWMT"><img src="images/3.jpg"></a></li>
	<li><a href="http://drbl.in/fQdt"><img src="images/4.png"></a></li>
	<!-- ... -->

The idea is to add a class to the items already shown in the viewport when we load the page. The items that will appear when we scroll them into the viewport will get a class called animate. In the CSS we define the animation that will happen for each effect and the individual styles that are needed:

/* Effect 4: fall perspective */
.grid.effect-4 {
	perspective: 1300px;

.grid.effect-4 li {
	transform-style: preserve-3d;

.grid.effect-4 li.animate {
	transform: translateZ(400px) translateY(300px) rotateX(-90deg);
	animation: fallPerspective .8s ease-in-out forwards;

@keyframes fallPerspective {
	100% { transform: translateZ(0px) translateY(0px) rotateX(0deg); opacity: 1; }

There are a couple of things that we can set. For adding some randomness, you can define a minimum and a maximum duration of the animation. Items that are appearing in the viewport will have an animation duration between those values. The viewportFactor defines how much of the appearing item has to be visible in order to trigger the animation. For example, if we’d use a value of 0, this would mean that it would add the animation class as soon as the item is in the viewport. If we were to use the value of 1, the animation would only be triggered when we see all of the item in the viewport (100% of it).

new AnimOnScroll( document.getElementById( 'grid' ), {
		minDuration : 0.4,
		maxDuration : 0.7,
		viewportFactor : 0.2
	} );

Note that we had to remove the transitions for Masonry so that there’s no conflict with the animations.

I hope you enjoyed this little experiment and find it inspiring!

Tagged with:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay in the loop: Get your dose of frontend twice a week

πŸ‘Ύ Hey! Looking for the latest in frontend? Twice a week, we'll deliver the freshest frontend news, website inspo, cool code demos, videos and UI animations right to your inbox.

Zero fluff, all quality, to make your Mondays and Thursdays more creative!

Feedback 116

Comments are closed.
    • Thanks Sara, yes we are using some of those… like I mention right in the beginning πŸ˜‰

  1. @MaryLou I posted the comment after viewing the demo and before reading through the article πŸ˜›

  2. Nice way to implement this effect, i bet someone will use this in a news feed.

  3. Hi !

    I try to use that in a div “overflow-y: auto”, i have hide the scroll in the body.

    In AnimOnScroll.js, i have change :
    var docElem = window.document.documentElement;
    var docElem = document.getElementById( ‘work_content’ ); // work_content its my div with the “overflow-y:auto” propertie.

    But no result, any one can help ??

    Any way thank for this super job !

    Thank !

  4. Fantastic job. I am always inspired by your contributions. My only criticism might be the inclusion of the Detroit Tigers grid item.

  5. (Y) awesome ,, thank for sharing this Mary,, and thank you for Hakim too πŸ™‚

  6. Mary Lou, many thanks for the tutorial! Awesome, this is what I was looking for my new website!

  7. Super boulot Mary,

    I am always inspired by your contributions, thank you for this great job..

    Le bonjour de Paris

  8. hi!! nice effects!! question. because i try to implement this with a block of divs with content, not images

    bla bla bla bla
    bla bla bla bla
    bla bla bla bla
    bla bla bla bla
    bla bla bla bla
    bla bla bla bla
    bla bla bla bla

    all blocks has width:100%

    i change all the mentions on the code.. but it’s not working..
    any ideas?

  9. So, the AnimOnScroll script is required for this effect? It cannot be done with pure CSS?

  10. hi guys
    im trying to work with this beautiful effect but i get this error at consol

    Uncaught ReferenceError: ImagesLoaded is not defined


    i have the imageloaded.js and its well referenced in the header.

    can someone show me a way to solve this ?

    thank you .

  11. i HATE that you dont do this cool stuff with mootools πŸ™
    i would use so much of this…

  12. Hi,
    it is a very nice plugin thx for develop.

    But I have one question.
    How can I configure to show only one column like?

    My text1
    My text2
    My text3

    Hope you can help me.

  13. Thank you for this tutorial! But how can i animate even the first elements when the page loads?

    • You need to modify plugin πŸ™‚ replace code from line 106-111 in AnimOnScroll.js

      self.items.forEach( function( el, i ) { if( inViewport( el ) ) { self._checkTotalRendered(); classie.add( el, 'animate' ); } } );

  14. Thank you so much for featuring my work and crediting me on your tutorial!! πŸ™‚

    • Is possible you need to replace line 89 whit this:
      this.items = this.el.toArray();

      and your init code will looks like:
      new AnimOnScroll( $('.yourBoxClass'), { minDuration : 0.4, maxDuration : 0.7, viewportFactor : 0.2 } );

      Basic change is to select all items with this class πŸ™‚

  15. I love these demo’s and as a matter of fact i love Codrops. I really wish though you would use JQuery in your examples… The whole world uses JQuery nowadays and the JS code would be much compact. Keep it up ! Cheers

  16. Hey Manoela, great script. We are having issues in Safari, and I cannot nail what the issue is.
    I initially, had to change : *, *:after, *:before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } from * to li ( it was affecting footer li list )

    Link to issue ( please view in Safari ) Grid Loading

    Only affects Safari, the 3rd row of loaded grid items are zoomed weirdly. Any suggestions

  17. LOL another Steve . G’day πŸ™‚

    For our purposes we used grid effect 5

    The fix was hard to track down, simple to implement.

    .grid.effect-5 li.animate { -webkit-transform-style: preserve-3d; -moz-transform-style: preserve-3d; transform-style: preserve-3d; /*-webkit-transform-origin: 50% 50% -300px; -moz-transform-origin: 50% 50% -300px; transform-origin: 50% 50% -300px;*/ -webkit-transform: rotateX(-180deg); -moz-transform: rotateX(-180deg); transform: rotateX(-180deg); -webkit-animation: fly .8s ease-in-out forwards; -moz-animation: fly .8s ease-in-out forwards; animation: fly .8s ease-in-out forwards; }

  18. Hi all, thanks for this awesomness ML!!

    I just wanted to ask, can one do this effect on a series of divs instead of list items?

    Thanks everyone!

  19. I can’t get this to work, I just get the following errors:

    TypeError: EventEmitter is not a constructor
    imagesLoaded( this.el, function() {
    [AnimOnScroll.js (line 96)]

    ReferenceError: imagesLoaded is not defined
    imagesLoaded( this.el, function() {
    [AnimOnScroll.js (line 96)]

    The js files are being called in the following order: imagesloaded.js, classie.js, AnimOnScroll.js

    I have got version 1.8.2 jQuery also being included above these.

    Any help would be appreciated.


  20. I had troubles with AnimOnScroll.js setting the ‘shown’ class on each element immediately. For some reason it set the ENTIRE website document length as the view port height in the client variable. I got it to work for me by editing the getViewportH function:
    var client = docElem[‘clientHeight]
    var client = document.getElementsByTagName(‘body’)[0].clientHeight

    Hope this helps someone.

    • Man, your code doesn’t work. Can you please give exact codes you used? I tried to implement above one you gave but doesn’t work!

  21. Its posible to add more columns, because only i have two columns and i want four, thank you

  22. Hi,
    Very good job !

    I need to hide or show elements but I cannot use the Masonry’s ‘reload’ method to replace my elements. Can you tell me how I have to do ?

    • I second this. I can’t seem to get them to hide and reload or use any of Masonry’s functionality. I looked inside the object prototype and see masonry but can’t use any of the methods.

  23. can u help me to use this awesome effect to wordpress loop? i have an infinite loop and i think is fabolous to apply this effect when scroll..

  24. Nice work here, code runs prefect on my site, but there is one small question when i put a div(with certain height) above ul, so i can scroll my ‘div’ alone not the whole page, but it doesnt load more in div, only body.

  25. Great work!

    Im having a problem with adding a hover state on the images which gets loaded in. The Visible items are working, but not the ones coming into view from the bottom.

    Seems to work OK in firefox, but not in Chrome+Safari+Opera. Removing the keyframe animation does the trick, but that is of course not an option;)

    Any ideas?

  26. How can we make the opposite, I mean the fade out effect if we scroll up again to the page????

    • You need to check if element is out of viewport and if has class “animate” and “shown” , remove this classes.

  27. This is beautiful! Is there any way to make the layout full screen width? Maybe a 4-6 column layout?

    Thank you for sharing this!

    • component.css line 1
      .grid { max-width: 1800px; //orwhatever you like depending on element widths }

    • But only changing the grid width breaks the mobile layout, where I could see 1 column now there are three of them.

    • Solved with some media queries for the grid, where width is a fraction of how many columns you want to show on each breakpoint

      @media only screen and (min-width: 1301px) { .grid li { width: 25%; } } @media only screen and (min-width: 901px) and (max-width: 1300px) { .grid li { width: 33%; } } @media only screen and (min-width: 481px) and (max-width: 900px) { .grid li { width: 50%; } } @media only screen and (min-width: 300px) and (max-width: 480px) { .grid li { width: 100%; } }

  28. Hi guys, I like your stuff and its been very helpful. I always want to promote the site by sharing content here but it seems the share buttons are difficult to see! Watsup?

  29. Hello,
    thanks for this!! πŸ™‚
    But how to load images for example 9 to 9 to save server bandwidth?


    • ….Ok I try use this with my php script for load image from folder, but is very slow, for 3 minutes page blank ( 1200 images) after this works! πŸ™‚
      Dont save sever bandwidth but for now is ok!

      Any ideas for reduce times to load images?