Search code examples
jqueryhtmlcssajaxtransition

Add fading transition to items loaded via ajax


I'm loading items containing information from some json files corresponding to the category I clicked on.

Below is some simplified code :

var $grid = $('.grid'),
	  $cat_link = $('.cat-list a');

// on loading the page for the first time, I define the category to display as the first one
$cat = 'cat-1';

function getCardsList() {
	$.ajax({
		url: 'js/' + $cat + '.json',
		dataType: 'json'
	}).done(listSuccess);

	function listSuccess(data) {
    var $card_items = [];
		
		for (var i = 0; i < data.length; i++) {
			var	card_item = '<div class="col">' + /*stuff from the json file*/ + '</div>';				
			$card_items.push( card_item[0] );
		}

		$grid.append( $card_items ).addClass('is-loaded');
	}
}

// execute immediately the function on the first load
getCardsList();

$cat_link.on( 'click', function(e) {
	e.preventDefault();

	$cat = $(this).data('cat');

	getCardsList();
});
.col {
  float:left;
  width:25%;
  transform: scale(0.85);
  opacity: 0;
  transition: transform 0.2s, opacity 0.2s;
}
.is-loaded .col {
  transform: scale(1);
  opacity: 1;
}
<ul class="cat-list">
	<li><a href="" data-cat="cat-1">Category 1</a></li>
	<li><a href="" data-cat="cat-2">Category 2</a></li>
	<li><a href="" data-cat="cat-3">Category 3</a></li>
</ul>

<div class="grid"></div>

Now I would like to add a transition to the divs that are appended to the grid. I tried hiding the element via CSS and then add a .is-loaded class to the grid to fade them in, in the success function, but since they're immediately appended to the grid, the transition doesn't work. Also tried adding a beforeSend parameter to the ajax call to hide the items beforehand but with no luck.

If I use a basic $('.grid .col').show() or .fadeIn() after appending the items, it works, but it's not the animation I want. Cannot use .animate() either since it's only animating numeric values.

I tried adding the .is-loaded class in the click event after the call to the function but it still doesn't work.

I feel very stupid but just can't figure how to do this, even though it seems so obvious. Thanks for any help.

Edit : here is a link to the (unfinished) online version. You will totally laugh looking at my script, I'm a self-taught JS noob.


Solution

  • One of the way to achieve what you want, without having to deal with additional classes are css animations. Example css:

    .col {
        float:left;
        width:25%;
        animation: popIn .2s;
    }
    @keyframes popIn {
        from {transform: scale(0.85); opacity: 0;}
        to {transform: scale(1); opacity: 1;}
    }
    

    Read more here: https://www.w3schools.com/css/css3_animations.asp

    Another way, which is a bit hacky, but lets you stick to the classes and transitions:

    First, modify you css to look like this:

    .col {
      float:left;
      width:25%;
      transform: scale(0.85);
      opacity: 0;
      transition: transform 0.2s, opacity 0.2s;
    }
    .col.is-loaded {
      transform: scale(1);
      opacity: 1;
    }
    

    Then modify your append by adding a delay between appending the element and adding class to it. This is required for the transition to take place.

    $("<div class='col'>One</div>").appendTo('.container').delay(1).queue(function (next) { 
        $(this).addClass('is-loaded'); 
        next(); 
      });