Tilt Hover Effects

Some ideas for hover animations with a fancy tilt effect. Inspired by the hover effect seen on the Kikk 2015 website.

Today we’d like to share some experimental hover effects with you. The idea is inspired by the hover effect seen on the grid of the Kikk 2015 website which was created by Dogstudio. We want to animate an image (which could be a link or simply a normal grid item) with a tilt effect on its parts. Having several elements in the item (that we call “tilter”), we can achieve a variety of effects that look very interesting. There’s the image, the “shine” element, the semi-transparent overlay with a colorful gradient, a border element and the caption. The examples show some ideas of how all of them (or some of them) can be animated. We hope you enjoy this little set.

For the effect we are using anime.js, the JavaScript animation engine by Julian Garnier.

Attention: Some of these techniques are very experimental and won’t work in all browsers. We’re using things like flexbox, perspective and in the last example we also use blend modes. Slinky browsers only! πŸ˜‰

The HTML structure of a “tilter” element

This is how we build a titler element. In this case we’re using an anchor:

<a href="#" class="tilter tilter--2">
	<figure class="tilter__figure">
		<img class="tilter__image" src="img/3.jpg" alt="img03" />
		<div class="tilter__deco tilter__deco--shine"><div></div></div>
		<div class="tilter__deco tilter__deco--overlay"></div>
		<figcaption class="tilter__caption">
			<h3 class="tilter__title">Helen Portland</h3>
			<p class="tilter__description">Seattle</p>
		<svg class="tilter__deco tilter__deco--lines" viewBox="0 0 300 415">
			<path d="M20.5,20.5h260v375h-260V20.5z" />

As you can see, we have all the aforementioned elements present in this example.

The styles for a “tilter” element

The styles for the tilter element are the following:

.tilter {
	position: relative;
	display: block;
	flex: none;
	width: 300px;
	height: 415px;
	margin: 1.5em 2.5em;
	color: #fff;
	perspective: 1000px;

.tilter * {
	pointer-events: none;

.tilter:focus {
	color: #fff;
	outline: none;

.tilter__image {
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;

.tilter__figure > * {
	transform: translateZ(0px); /* Force correct stacking order */

.tilter__figure {
	position: relative;

.tilter__figure::before {
	content: '';
	position: absolute;
	top: 5%;
	left: 5%;
	width: 90%;
	height: 90%;
	box-shadow: 0 30px 20px rgba(35,32,39,0.5);

.tilter__deco {
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	width: 100%;
	height: 100%;

.tilter__deco--overlay {
	background-image: linear-gradient(45deg, rgba(226, 60, 99, 0.4), rgba(145, 58, 252, 0.4), rgba(16, 11, 192, 0.4));

.tilter__deco--shine div {
	position: absolute;
	top: -50%;
	left: -50%;
	width: 200%;
	height: 200%;
	background-image: linear-gradient(45deg, rgba(0, 0, 0, 0.5) 0%, rgba(255, 255, 255, 0.25) 50%, transparent 100%);

.tilter__deco--lines {
	fill: none;
	stroke: #fff;
	stroke-width: 1.5px;

.tilter__caption {
	position: absolute;
	bottom: 0;
	width: 100%;
	padding: 4em;

.tilter__title {
	font-family: 'Abril Fatface', serif;
	font-size: 2.5em;
	font-weight: normal;
	line-height: 1;
	margin: 0;

.tilter__description {
	font-size: 0.85em;
	margin: 1em 0 0 0;
	letter-spacing: 0.15em;

The JavaScript

In the options we can define what movements each animatable element will have:

  • We can pass the following: translation and rotation for all axes and animation (duration, easing, and elasticity – same fashion like the anime.js options) to revert to the default style.
  • For both, translation and rotation, we can define the values per axis in the following way:
    • number: e.g. translation : {x: 10, y: -10} meaning that the element will move along the x-axis from -10px to 10px (as we move the mouse from left to right) and on the y-axis from 10px to -10px (as we move the mouse from top to bottom).
    • array: e.g. translation : {z: [10,100]} meaning that the element will move along the z-axis from 10px to 100px (as we move the mouse from top to bottom)

new TiltFx(el, [options]);

The options:

var options = {
	movement: {
		// The main wrapper.
		imgWrapper : {
			translation : {x: 10, y: 10, z: 30},
			rotation : {x: 0, y: -10, z: 0},
			reverseAnimation : {duration : 200, easing : 'easeOutQuad'}
		// The SVG lines element.
		lines : {
			translation : {x: 10, y: 10, z: [0,70]},
			rotation : {x: 0, y: 0, z: -2},
			reverseAnimation : {duration : 2000, easing : 'easeOutExpo'}
		// The caption/text element.
		caption : {
			rotation : {x: 0, y: 0, z: 2},
			reverseAnimation : {duration : 200, easing : 'easeOutQuad'}
		// The overlay element.
		overlay : {
			translation : {x: 10, y: -10, z: 0},
			rotation : {x: 0, y: 0, z: 2},
			reverseAnimation : {duration : 2000, easing : 'easeOutExpo'}
		// The shine element.
		shine : {
			translation : {x: 100, y: 100, z: 0},
			reverseAnimation : {duration : 200, easing : 'easeOutQuad'}

We hope you enjoy the effects and find them useful and inspirational!

Browser Support:
  • ChromeSupported
  • FirefoxSupported
  • Internet ExplorerSupported from version E
  • SafariSupported
  • OperaSupported

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 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 35

Comments are closed.
  1. Really impressive effect! My only point would be related to the moment you hover the element, the card is jumping straight to the position where the cursor is.
    It would be great if it was moving smoothly.

    Keep doing good stuff!


  2. Very nice effect but I don’t like the little jump when you hover the card for the first time, it could be more subtle the transition before entering the hover state

  3. Thanks everybody, really appreciate the feedback! The little jump is due to the fact that we don’t use CSS transitions on the elements because that did not work so smooth in Safari. We’ve added another demo where you can see the hover effect with CSS transitions (hard reload might be required). Thanks again for all the feedback, cheers, ML

    • Nevermind. I think I fix it. I overwrite the tiltSettings’ variable in the index with the same values which are in the main javascript file.

    • Salvatore Graziani, could you please expand on how you solved this issue?

    • Thomas Manstrup Knudsen, I had the same problem which i fixed, thanks to Salvatore.
      I know i’m a year late but if I can help a little.

      In the main.js, look for line 52 to +- 94 about movement, copy that.
      Then look in the index, just before , you’ll find something similar.
      You have to replace the lines you are using with what you just copied.

      Works for me.

  4. That will be fun, if i could use orientation phone to actived tilt effect πŸ™
    If you have an issue ?

  5. Beautiful.

    The only thing jarring about this is the initial mouseover. It doesn’t get pulled to your mouse position, it just instantly jumps there.

    Besides that, everything is perfect!

    • Hi Omar, it does use anime.js and we mention it in the credits. But you are right, it should say so in the beginning of the article; I’ve added it now. Thanks for the heads up! Cheers, ML