Stack Motion Hover Effects

Experimental hover effects that reveal a stack of multiple colored cards behind the hovered item.

Today we’d like to share some tiny hover effect ideas with you. The concept stems from the hover effect seen on Merci-Michel which has a really nice feel to it because of its fluidity. The idea is to show a stack behind the hovered thumbnail that has the same main color as the image and then animate the elements in a swift motion. We are using the JavaScript library anime.js for the animations.

Attention: Modern CSS properties at work, so modern browsers only.

Stack Motion Effect Markup & Styles

The markup for the items is as follows:

<div class="grid grid--effect-vega">
	<a href="#" class="grid__item grid__item--c1">
		<div class="stack">
			<div class="stack__deco"></div>
			<div class="stack__deco"></div>
			<div class="stack__deco"></div>
			<div class="stack__deco"></div>
			<div class="stack__figure">
				<img class="stack__img" src="img/1.png" alt="Image"/>
			</div>
		</div>
		<div class="grid__item-caption">
			<h3 class="grid__item-title">anaerobic</h3>
			<div class="column column--left">
				<span class="column__text">Period</span>
				<span class="column__text">Subjects</span>
				<span class="column__text">Result</span>
			</div>
			<div class="column column--right">
				<span class="column__text">2045</span>
				<span class="column__text">133456</span>
				<span class="column__text">Positive</span>
			</div>
		</div>
	</a>
	<a href="#" class="grid__item grid__item--c2"><!-- ... --></a>
	<a href="#" class="grid__item grid__item--c2"><!-- ... --></a>
</div><!-- /grid -->

We use a specific class for the grid to create individual effects. The four stack__deco divisions are the decorative elements that we animate along with the stack__figure and the image. The grid itself is the container that has perspective. The grid caption has a title and two columns that optionally get animated, too.

For the grid we use a flexbox layout (see demo.css). For the decorative cards of the stack and the figure with its image will have the following styles:

.stack {
	position: relative;
	width: 100%;
	height: 200px;
	transform-style: preserve-3d;
}

.stack__deco {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background-color: currentColor;
	transform-origin: 50% 100%;
}

.stack__deco:first-child {
	opacity: 0.2;
}

.stack__deco:nth-child(2) {
	opacity: 0.4;
}

.stack__deco:nth-child(3) {
	opacity: 0.6;
}

.stack__deco:nth-child(4) {
	opacity: 0.8;
}

.stack__figure {
	position: relative;
	display: flex;
	justify-content: center;
	align-items: center;
	overflow: hidden;
	width: 100%;
	height: 100%;
	cursor: pointer;
	transform-origin: 50% 100%;
}

.stack__img {
	position: relative;
	display: block;
	flex: none;
}

For some effects we want some special styles:

/* Individual effects */

/* Vega */
.grid--effect-vega .column {
	opacity: 1;
}

/* deneb */
.grid--effect-deneb {
	perspective: none;
}

.grid--effect-deneb .stack__figure,
.grid--effect-deneb .stack__deco {
	transform-origin: 50% 50%;
}

.grid--effect-deneb .column {
	opacity: 1;
}

/* ... */

And here is an example for an effect animation (hovering in and out):

HamalFx.prototype._in = function() {
	var self = this;

	this.DOM.stackItems.map(function(e, i) {
		e.style.opacity = i !== self.totalItems - 1 ? 0.2*i+0.2 : 1
	});

	anime({
		targets: this.DOM.stackItems,
		duration: 1000,
		easing: 'easeOutExpo',
		translateY: function(target, index) {
			return -1*index*5;
		},
		rotate: function(target, index, cnt) {
			if( index === cnt - 1 ) {
				return 0;
			}
			else {
				return index%2 ? (cnt-index)*1 : -1*(cnt-index)*1;
			}
		},
		scale: function(target, index, cnt) {
			if( index === cnt - 1 ) {
				return 1;
			}
			else {
				return 1.05;
			}
		},
		delay: function(target, index, cnt) {
			return (cnt-index-1)*30
		}
	});
	
	anime({
		targets: this.DOM.img,
		duration: 1000,
		easing: 'easeOutExpo',
		scale: 0.7
	});

	anime({
		targets: [this.DOM.columns.left, this.DOM.columns.right],
		duration: 1000,
		easing: 'easeOutExpo',
		translateX: function(target, index) {
			return index === 0 ? -30 : 30;
		}
	});
	
};

HamalFx.prototype._out = function() {
	var self = this;

	anime({
		targets: this.DOM.stackItems,
		duration: 500,
		easing: 'easeOutExpo',
		translateY: 0,
		rotate: 0,
		scale: 1,
		opacity: function(target, index, cnt) {
			return index !== cnt - 1 ? 0 : 1
		}
	});

	anime({
		targets: this.DOM.img,
		duration: 1000,
		easing: 'easeOutElastic',
		scale: 1
	});

	anime({
		targets: [this.DOM.columns.left, this.DOM.columns.right],
		duration: 500,
		easing: 'easeOutExpo',
		translateX: 0
	});
};

We hope you like these hover effects and find them inspirational!

References and Credits

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 up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 12

Comments are closed.
  1. Wow! I don’t have any uses for something like that just now but I will definitely keep those in mind, awesome.

  2. I wonder if similar animation can be tried with multiple box-shadows. Worth trying…

  3. It is great….I kind of made it work. But in my case after the hover animation, the images disappears. If I hover on the empty space I can see the animation again (firefox and chrome). Oh well. Too advanced for me.

  4. Those are fantastic hover effect! I will use one of this in my personal landing page! Congrats!

  5. Amazing hover effects for slow motion. I can use all of these effects in my project. Thank you.

  6. Can you help me to implement it? i try to use it but im just seeing the items without hover effects

  7. unfortunately i cant fix it on my projectt , it was good if you make a short clip for install that or teach a lit better or more …