Effect Ideas for Card Stacks

Some effect inspiration for card stacks. The idea is to show animation ideas for positive (accept) or negative (reject) feedback on a generic card element.

Today we’d like to share some inspiration for card effects with you. The idea is to animate the top element of a stack by clicking on an accept or reject button. We’ve used this Tinder-like example to show some symmetric and complementing pairs of effects, but these kind of animations can fit into many scenarios involving all kinds of card stacks that don’t necessarily have a dual logic.

Attention: Some of the CSS techniques we use are only supported by modern browsers.

The markup for a stack and its controls looks like this:

<ul id="stack_yuda" class="stack stack--yuda">
	<li class="stack__item"><img src="img/1.png" alt="Tree 1" /></li>
	<li class="stack__item"><img src="img/2.png" alt="Tree 2" /></li>
	<li class="stack__item"><img src="img/3.png" alt="Tree 3" /></li>
	<li class="stack__item"><img src="img/4.png" alt="Tree 4" /></li>
	<li class="stack__item"><img src="img/5.png" alt="Tree 5" /></li>
	<li class="stack__item"><img src="img/6.png" alt="Tree 6" /></li>
</ul>
<div class="controls">
	<button class="button button--sonar button--reject" data-stack="stack_yuda">
		<i class="fa fa-times"></i>
		<span class="text-hidden">Reject</span>
	</button>
	<button class="button button--sonar button--accept" data-stack="stack_yuda">
		<i class="fa fa-check"></i>
		<span class="text-hidden">Accept</span>
	</button>
</div>

With all the stack items positioned absolutely on top of each other, we apply a “accept” or “reject” class to the current item, depending on which button we clicked.

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

For this demo we’ve implemented a little plugin that takes care of the functionality. We use dynamics.js by Michael Villar as animation library. The animations for moving the items away (accept/reject) are defined as CSS animations in the stylesheet.

The plugin has the following options:

Stack.prototype.options = {
	// stack's perspective value
	perspective: 1000,

	// stack's perspective origin
	perspectiveOrigin : '50% -50%',

	// number of visible items in the stack
	visible : 3,

	// infinite navigation
	infinite : true,

	// callback: when reaching the end of the stack
	onEndStack : function() {return false;},

	// animation settings for the items' movements in the stack when the items rearrange
	// object that is passed to the dynamicsjs animate function (see more at http://dynamicsjs.com/)
	// example:
	// {type: dynamics.spring,duration: 1641,frequency: 557,friction: 459,anticipationSize: 206,anticipationStrength: 392}
	stackItemsAnimation : {
		duration : 500,
		type : dynamics.bezier,
		points : [{'x':0,'y':0,'cp':[{'x':0.25,'y':0.1}]},{'x':1,'y':1,'cp':[{'x':0.25,'y':1}]}]
	},

	// delay for the items' rearrangement / delay before stackItemsAnimation is applied
	stackItemsAnimationDelay : 0,

	// animation settings for the items' movements in the stack before the rearrangement
	// we can set up different settings depending on whether we are approving or rejecting an item
	stackItemsPreAnimation : {
		reject : {
			// if true, then the settings.properties parameter will be distributed through the items in a non equal fashion
			// for instance, if we set settings.properties = {translateX:100} and we have options.visible = 4, 
			// then the second item in the stack will translate 100px, the second one 75px and the third 50px
			elastic : true,
			// object that is passed into the dynamicsjs animate function - second parameter -  (see more at http://dynamicsjs.com/)
			animationProperties : {},
			// object that is passed into the dynamicsjs animate function - third parameter - (see more at http://dynamicsjs.com/)
			animationSettings : {} 
		},
		accept : {
			// if true, then the settings.properties parameter will be distributed through the items in a non equal fashion
			// for instance, if we set settings.properties = {translateX:100} and we have options.visible = 4, 
			// then the second item on the stack will translate 100px, the second one 75px and the third 50px
			elastic : true,
			// object that is passed into the dynamicsjs animate function - second parameter -  (see more at http://dynamicsjs.com/)
			animationProperties : {},
			// object that is passed into the dynamicsjs animate function (see more at http://dynamicsjs.com/)
			animationSettings : {}
		}
	}
}

And this is an example for the reject/accept action effect:

/***********************************************/
/******************** yuda *********************/
/***********************************************/

.stack--yuda .stack__item--reject {
	-webkit-animation: yudaReject 0.5s forwards;
	animation: yudaReject 0.5s forwards;
}

@-webkit-keyframes yudaReject {
	to {
		opacity: 0;
		-webkit-transform: translate3d(0, 200px, 0);
		transform: translate3d(0, 200px, 0);
	}
}

@keyframes yudaReject {
	to {
		opacity: 0;
		-webkit-transform: translate3d(0, 200px, 0);
		transform: translate3d(0, 200px, 0);
	}
}

.stack--yuda .stack__item--accept {
	-webkit-transform-origin: 50% 300%;
	transform-origin: 50% 300%;
	-webkit-animation: yudaAccept 0.5s forwards;
	animation: yudaAccept 0.5s forwards;
}

@-webkit-keyframes yudaAccept {
	to {
		opacity: 0;
		-webkit-transform: rotate3d(0, 0, 1, 20deg);
		transform: rotate3d(0, 0, 1, 20deg);
	}
}

@keyframes yudaAccept {
	to {
		opacity: 0;
		-webkit-transform: rotate3d(0, 0, 1, 20deg);
		transform: rotate3d(0, 0, 1, 20deg);
	}
}

The tree vectors used in the demo are from Freepic and you can find them here: Tree vector designed by Freepik

We hope you have fun with these effects and find them inspirational!

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

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 18

Comments are closed.
  1. How hard would it be to add touch interaction so you could trigger action by pulling to left or right – ala tinder?

    • Not that hard. You can use jQuery for the swipe interaction.
      And when it is swiped in either direction, you can use an event handler to fire the above code.

  2. Hello, Can anyone tell me the relation between dynaminc.js and main.js xO
    I’ll be very preciate

  3. I have en error “Stack is not defined”. Could you please do more detail tutorial how to include this project?

    • Hi! Did you find a solution to make the back function? I’ve been trying and could make reed the previous item and show it, but with the no right the effects and position (translate). I can’t really find where make this settings.

  4. Hi, all material in your page is very interesting, but this material have any licence class ? Can I use it in my projects ? should I to pay for use it ? Thanks a lot.

  5. How hard could be add a previous button? Because now this example is just for show next elements.
    Any idea? Thanks!