From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
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.
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>
</figcaption>
<svg class="tilter__deco tilter__deco--lines" viewBox="0 0 300 415">
<path d="M20.5,20.5h260v375h-260V20.5z" />
</svg>
</figure>
</a>
As you can see, we have all the aforementioned elements present in this example.
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
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:hover,
.tilter:focus {
color: #fff;
outline: none;
}
.tilter__figure,
.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)
Initialize:
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
- anime.js by Julian Garnier
- Images from Pexels licensed under Creative Commons (CC0) and from Unsplash.com
- ImagesLoaded by Dave DeSandro
You’ve done it again! Beautiful.
Great effects!!!
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!
B.
true, but there are two demos – one is with hover transition, which works pretty well
The link to Pexels in “References and Credits” doesn’t work.
Thanks a lot, fixed! Cheers, ML
the awesomeness is do damn high
HaHaHa Well Done!
Curious to know where the bounce effect on leave comes from.
Did it 2 months ago : http://s.codepen.io/romaingranai/debug/JRyGJA π
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
Agreed. That’s my only criticism. Otherwise it’s very nice.
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
in Edge and other browsers, if a lot of cards – very hinders the effect, using transition: transform 0.2s ease-out;
and Firefox π
It’s so smooth! Nice! <3
Perfect, this is just awesome, very nice work.
Nice!
I love you work, would you mind if I build a React Component around this tilt effect? Of course I’d credit you when it’s publish.
Hi Son Chu, thanks for asking and I don’t mind at all π Cheers, ML
and further! If you add more than 5 blocks, 3 and 4 will behave properly
3 and 4 don’t work properly. How is it possible? :((
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.
That will be fun, if i could use orientation phone to actived tilt effect π
If you have an issue ?
Looks fun and enjoyable but I don’t think this is appropriate for UX.
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!
what do you mean with all the `parter`s !?!?!
paters
I made a React Component out of this. You’re welcomed to check it out here: https://github.com/chuson1996/tilt-hover
Fantastic and inspiring as always!
Is this using anime.js? The article should mention that it’s using anime.js.
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
really awesome and helpfull thanks.
anyone have tried to make it work on mobile devices?
I’m trying to add this effect to my site but it’s not working for me