From our sponsor: Chromatic - Visual testing for Storybook, Playwright & Cypress. Catch UI bugs before your users do.
The power of CSS3 is enormous and in this tutorial we will see how to exploit it in a very creative way. We are going to create some thumbnail hover effects with CSS3 transitions. On hover over a thumbnail, we will reveal some description of the thumbnail, using a different style in each example.
Please note that this will only work properly in modern browsers that support the CSS3 properties in use.
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 Markup
The structure of markup is very simple and intuitive. Create a container that will have our image and all the other infomation.
Inside the view insert an element with the class mask that will be responsible for our effects driven by CSS3 and inside it we will put a title, description and a link to the full image. (For some examples, we’ll need to add the mask element as a separate element and wrap the description in a devi with class content.)
<div class="view"> <img src="image.gif" /> <div class="mask"> <h2>Title</h2> <p>Your Text</p> <a href="#" class="info">Read More</a> </div> </div>
The CSS
After creating our markup we’re going to set our style.
We set the general rules for our class and then we are going to add a special class with the desired effect styles. We will omit the CSS3 vendor prefixes when showing the style.
.view { width: 300px; height: 200px; margin: 10px; float: left; border: 10px solid #fff; overflow: hidden; position: relative; text-align: center; box-shadow: 1px 1px 2px #e6e6e6; cursor: default; background: #fff url(../images/bgimg.jpg) no-repeat center center } .view .mask, .view .content { width: 300px; height: 200px; position: absolute; overflow: hidden; top: 0; left: 0 } .view img { display: block; position: relative } .view h2 { text-transform: uppercase; color: #fff; text-align: center; position: relative; font-size: 17px; padding: 10px; background: rgba(0, 0, 0, 0.8); margin: 20px 0 0 0 } .view p { font-family: Georgia, serif; font-style: italic; font-size: 12px; position: relative; color: #fff; padding: 10px 20px 20px; text-align: center } .view a.info { display: inline-block; text-decoration: none; padding: 7px 14px; background: #000; color: #fff; text-transform: uppercase; box-shadow: 0 0 1px #000 } .view a.info:hover { box-shadow: 0 0 5px #000 }
And now we’ll look at the ten effects.
Example 1
Add the special class view-first to the element with the class view for this effect. We will be adding a special class to each example’s view element (view-first, view-second, view-third, etc.).
<div class="view view-first"> </div>
In this first example we will just use some basic transitions to create a nice hover effect.
.view-first img { transition: all 0.2s linear; } .view-first .mask { opacity: 0; background-color: rgba(219,127,8, 0.7); transition: all 0.4s ease-in-out; } .view-first h2 { transform: translateY(-100px); opacity: 0; transition: all 0.2s ease-in-out; } .view-first p { transform: translateY(100px); opacity: 0; transition: all 0.2s linear; } .view-first a.info{ opacity: 0; transition: all 0.2s ease-in-out; }
And now comes the heart of our effect. When you move the mouse over the image, we can use the delay property to emulate simple animations. The transition-delay that we use in the hover class can be altered, to be differnt than the one in the normal class. In this example we did not use any delay in the normal class; but we added a delay on hover, which will make the transition start a bit later. Moving the mouse out, the default value of 0s will apply and the “reverse” will be quicker.
.view-first:hover img { transform: scale(1.1); } .view-first:hover .mask { opacity: 1; } .view-first:hover h2, .view-first:hover p, .view-first:hover a.info { opacity: 1; transform: translateY(0px); } .view-first:hover p { transition-delay: 0.1s; } .view-first:hover a.info { transition-delay: 0.2s; }
Example 2
In this second example we will add the special class view-second, but we will leave the element with the class mask empty and wrap the description in a div with the class content
<div class="view view-second"> <img src="images/5.jpg" /> <div class="mask"></div> <div class="content"> <h2>Hover Style #2</h2> <p>Some description</p> <a href="#" class="info">Read More</a> </div> </div>
Here the mask class will have different attributes to satisfy our effect, in fact we are going to apply the transform property (translate and rotate) and will make a square out of it. The description elements will be translated, i.e. moved so that we can slide them in on hover:
.view-second img { transition: all 0.2s ease-in; } .view-second .mask { background-color: rgba(115,146,184, 0.7); width: 300px; padding: 60px; height: 300px; opacity: 0; transform: translate(265px, 145px) rotate(45deg); transition: all 0.2s ease-in-out; } .view-second h2 { border-bottom: 1px solid rgba(0, 0, 0, 0.3); background: transparent; margin: 20px 40px 0px 40px; transform: translate(200px, -200px); transition: all 0.2s ease-in-out; } .view-second p { transform: translate(-200px, 200px); transition: all 0.2s ease-in-out; } .view-second a.info { transform: translate(0px, 100px); transition: all 0.2s 0.1s ease-in-out; }
For our hover effect we exploit the translate transformation in order to move our elements in place. The mask will also be rotated. The elements of the description will each come with a little delay:
.view-second:hover .mask { opacity:1; transform: translate(-80px, -125px) rotate(45deg); } .view-second:hover h2 { transform: translate(0px,0px); transition-delay: 0.3s; } .view-second:hover p { transform: translate(0px,0px); transition-delay: 0.4s; } .view-second:hover a.info { transform: translate(0px,0px); transition-delay: 0.5s; }
Example 3
In this third example we will use the translate and rotate transforms to bring up our content:
.view-third img { transition: all 0.2s ease-in; } .view-third .mask { background-color: rgba(0,0,0,0.6); opacity: 0; transform: translate(460px, -100px) rotate(180deg); transition: all 0.2s 0.4s ease-in-out; } .view-third h2{ transform: translateY(-100px); transition: all 0.2s ease-in-out; } .view-third p { transform: translateX(300px) rotate(90deg); transition: all 0.2s ease-in-out; } .view-third a.info { transform: translateY(-200px); transition: all 0.2s ease-in-out; }
These are the simple instructions that are applied on hover. Now we will reverse the appearing of the description elements by setting the transition-delay accordingly:
.view-third:hover .mask { opacity:1; transition-delay: 0s; transform: translate(0px, 0px); } .view-third:hover h2 { transform: translateY(0px); transition-delay: 0.5s; } .view-third:hover p { transform: translateX(0px) rotate(0deg); transition-delay: 0.4s; } .view-third:hover a.info { transform: translateY(0px); transition-delay: 0.3s; }
Example 4
Here in the fourth example we will perform a simple zoom out image and a zoom in of our content with rotation, all thanks to the scale transform. We set the transition-delay to 0.2s for the image style, but on hover we’ll say that it’s 0s. This will make it start immediately on hover, but delay it on mouse out.
.view-fourth img { transition: all 0.4s ease-in-out 0.2s; opacity: 1; } .view-fourth .mask { background-color: rgba(0,0,0,0.8); opacity: 0; transform: scale(0) rotate(-180deg); transition: all 0.4s ease-in; border-radius: 0px; } .view-fourth h2{ opacity: 0; border-bottom: 1px solid rgba(0, 0, 0, 0.3); background: transparent; margin: 20px 40px 0px 40px; transition: all 0.5s ease-in-out; } .view-fourth p { opacity: 0; transition: all 0.5s ease-in-out; } .view-fourth a.info { opacity: 0; transition: all 0.5s ease-in-out; }
These are the simple instructions to get the effect – with CSS3 you can do everything 🙂
.view-fourth:hover .mask { opacity: 1; transform: scale(1) rotate(0deg); transition-delay: 0.2s; } .view-fourth:hover img { transform: scale(0); opacity: 0; transition-delay: 0s; } .view-fourth:hover h2, .view-fourth:hover p, .view-fourth:hover a.info{ opacity: 1; transition-delay: 0.5s; }
Example 5
In this fifth example we will use the translate property along with the transition-timing-function ease-in-out in order to slide the content in from the left.
.view-fifth img { transition: all 0.3s ease-in-out; } .view-fifth .mask { background-color: rgba(146,96,91,0.3); transform: translateX(-300px); opacity: 1; transition: all 0.4s ease-in-out; } .view-fifth h2{ background: rgba(255, 255, 255, 0.5); color: #000; box-shadow: 0px 1px 3px rgba(159, 141, 140, 0.5); } .view-fifth p{ opacity: 0; color: #333; transition: all 0.2s linear; }
The hover effect will make the image slide to the right and the description come from the left, as if it’s pushing the image:
.view-fifth:hover .mask { transform: translateX(0px); } .view-fifth:hover img { transform: translateX(300px); transition-delay: 0.1s; } .view-fifth:hover p{ opacity: 1; transition-delay: 0.4s; }
Example 6
In this example we will make the description come from the front, zooming out until its original size (scale from factor 10 to 1). The info button will slide in from the bottom (translate).
.view-sixth img { transition: all 0.4s ease-in-out 0.5s; } .view-sixth .mask{ background-color: rgba(146,96,91,0.5); opacity:0; transition: all 0.3s ease-in 0.4s; } .view-sixth h2{ opacity:0; border-bottom: 1px solid rgba(0, 0, 0, 0.3); background: transparent; margin: 20px 40px 0px 40px; transform: scale(10); transition: all 0.3s ease-in-out 0.1s; } .view-sixth p { opacity:0; transform: scale(10); transition: all 0.3s ease-in-out 0.2s; } .view-sixth a.info { opacity:0; transform: translateY(100px); transition: all 0.3s ease-in-out 0.1s; }
The reverse transition will be delayed in such a way that it looks smooth:
.view-sixth:hover .mask { opacity:1; transition-delay: 0s; } .view-sixth:hover img { transition-delay: 0s; } .view-sixth:hover h2 { opacity: 1; transform: scale(1); transition-delay: 0.1s; } .view-sixth:hover p { opacity:1; transform: scale(1); transition-delay: 0.2s; } .view-sixth:hover a.info { opacity:1; transform: translateY(0px); transition-delay: 0.3s; }
Example 7
In this seventh example the idea is to rotate the image to the center and scale it down. Then the description comes rotating from up with the description content following.
.view-seventh img{ transition: all 0.5s ease-out; opacity: 1; } .view-seventh .mask { background-color: rgba(77,44,35,0.5); transform: rotate(0deg) scale(1); opacity: 0; transition: all 0.3s ease-out; transform: translateY(-200px) rotate(180deg); } .view-seventh h2{ transform: translateY(-200px); transition: all 0.2s ease-in-out; } .view-seventh p { transform: translateY(-200px); transition: all 0.2s ease-in-out; } .view-seventh a.info { transform: translateY(-200px); transition: all 0.2s ease-in-out; }
On hover we add a delay for the desciption elements. This will show us the rotating image first and then the description will come into the picture. In the reverse transition, everything will disappear immediately and we’ll see the image rotate back:
.view-seventh:hover img{ transform: rotate(720deg) scale(0); opacity: 0; } .view-seventh:hover .mask { opacity: 1; transform: translateY(0px) rotate(0deg); transition-delay: 0.4s; } .view-seventh:hover h2 { transform: translateY(0px); transition-delay: 0.7s; } .view-seventh:hover p { transform: translateY(0px); transition-delay: 0.6s; } .view-seventh:hover a.info { transform: translateY(0px); transition-delay: 0.5s; }
Example 8
In this eighth example we’ll use an animation and recreate a bounce effect. The description will bounce in from the top.
.view-eighth .mask { background-color: rgba(255, 255, 255, 0.7); top: -200px; opacity: 0; transition: all 0.3s ease-out 0.5s; } .view-eighth h2{ transform: translateY(-200px); transition: all 0.2s ease-in-out 0.1s; } .view-eighth p { color: #333; transform: translateY(-200px); transition: all 0.2s ease-in-out 0.2s; } .view-eighth a.info { transform: translateY(-200px); transition: all 0.2s ease-in-out 0.3s; }
We’ll add the animation to the mask element and define some fitting delays for the onset of the description elements:
.view-eighth:hover .mask { opacity: 1; top: 0px; transition-delay: 0s; animation: bounceY 0.9s linear; } .view-eighth:hover h2 { transform: translateY(0px); transition-delay: 0.4s; } .view-eighth:hover p { transform: translateY(0px); transition-delay: 0.2s; } .view-eighth:hover a.info { transform: translateY(0px); transition-delay: 0s; }
To recreate a true bounce effect we use the translateY, as you can see there are a couple of frames, in order to make the effect:
@keyframes bounceY { 0% { transform: translateY(-205px);} 40% { transform: translateY(-100px);} 65% { transform: translateY(-52px);} 82% { transform: translateY(-25px);} 92% { transform: translateY(-12px);} 55%, 75%, 87%, 97%, 100% { transform: translateY(0px);} }
Example 9
In this example, we will use two mask elements to slide them in from the bottom right and the top left:
<div class="view view-ninth"> <img src="images/11.jpg" /> <div class="mask mask-1"></div> <div class="mask mask-2"></div> <div class="content"> <h2>Hover Style #9</h2> <p>Some Text</p> <a href="#" class="info">Read More</a> </div> </div>
The two masks will have a different translation and a transfrom origin. Also, we’ll set one to be aligned at the top and the other at the bottom:
.view-ninth .mask-1, .view-ninth .mask-2{ background-color: rgba(0,0,0,0.5); height: 361px; width: 361px; background: rgba(119,0,36,0.5); opacity: 1; transition: all 0.3s ease-in-out 0.6s; } .view-ninth .mask-1 { left: auto; right: 0px; transform: rotate(56.5deg) translateX(-180px); transform-origin: 100% 0%; } .view-ninth .mask-2 { top: auto; bottom: 0px; transform: rotate(56.5deg) translateX(180px); transform-origin: 0% 100%; }
The content will be styled in a way that it looks like as if it’s coming out as a tiny slice through the touching edges of the two masks:
.view-ninth .content{ background: rgba(0,0,0,0.9); height: 0px; opacity: 0.5; width: 361px; overflow: hidden; transform: rotate(-33.5deg) translate(-112px,166px); transform-origin: 0% 100%; transition: all 0.4s ease-in-out 0.3s; } .view-ninth h2{ background: transparent; margin-top: 5px; border-bottom: 1px solid rgba(255,255,255,0.2); } .view-ninth a.info{ display: none; }
On hover, we’ll make the content come out from the slot and make the masks touch at their edges:
.view-ninth:hover .content{ height: 120px; width: 300px; opacity: 0.9; top: 40px; transform: rotate(0deg) translate(0px,0px); } .view-ninth:hover .mask-1, .view-ninth:hover .mask-2{ transition-delay: 0s; } .view-ninth:hover .mask-1{ transform: rotate(56.5deg) translateX(1px); } .view-ninth:hover .mask-2 { transform: rotate(56.5deg) translateX(-1px); }
We are setting the transition-delay for the masks in such a way, that when we hover, the transition happens instantly. But when moving out with the mouse, the delay will be longer, as if its “waiting” for the content to move back into the slot.
Example 10
In the last example, we will zoom in the image and make it fade out while bringing the descpription to the front. We can do that by using the scale transform and setting the opacity level:
.view-tenth img { transform: scaleY(1); transition: all 0.7s ease-in-out; } .view-tenth .mask { background-color: rgba(255, 231, 179, 0.3); transition: all 0.5s linear; opacity: 0; } .view-tenth h2{ border-bottom: 1px solid rgba(0, 0, 0, 0.3); background: transparent; margin: 20px 40px 0px 40px; transform: scale(0); color: #333; transition: all 0.5s linear; opacity: 0; } .view-tenth p { color: #333; opacity: 0; transform: scale(0); transition: all 0.5s linear; } .view-tenth a.info { opacity: 0; transform: scale(0); transition: all 0.5s linear; }
On hover, we’ll simply scale the image up and fade it out by decreasing its opacity to 0:
.view-tenth:hover img { transform: scale(10); opacity: 0; } .view-tenth:hover .mask { opacity: 1; } .view-tenth:hover h2, .view-tenth:hover p, .view-tenth:hover a.info{ transform: scale(1); opacity: 1; }
Conclusion
CSS3 has a really great potential for creating nice effects. Soon, we’ll hopefully be able to avoid the use of JavaScript for simple effects and rely 100% on CSS, in all browsers.
I hope that you liked these experiments, but above all I hope that they can inspire you for your projects.
Love the effect! Has anybody figured out a fix for iPad and iPhone?
I used this property which recognized with Chrome + Safari only but it works:
But the problem is I am using Django App with Internationalization basically it is translating website to multiple languages by clicking on icon which is refreshing the url to /en/, /it/, etc… ALL works on all browsers except the Safari in Lion when you click on any links it refreshes the page but no change but when you sroll a little it switches to requested page….when I remove this:
it starts working again but then I got that flicker back of entire screen. Basically no matter what link you click just click dont move the mouse nothing change and after scrolling a little it switches because of that backface hidden property….2nd thing would be great to make it work on iphone and ipad, I made it to work by adding an
around entire thing and when you click it works but there is a little problem “#” this will refresh the page and take you to the top of the screen and you need to scroll back to your picture item you selected, would be great to fix all this issues, anyway very nice tutorial, the best I saw out there 🙂
I found the way how to replicate the error:
Lion – Safari / Version 5.1 (7534.48.3)
Use exactly tutorial that you have ADD this to Style9.css & Style10.css
* {-webkit-backface-visibility: hidden;}
Go to index10.html load it in Safari, Click Example 9 (index.html) – but click the link and don’t move the mouse. You will see this like on the screenshot:
http://cl.ly/3j271Z2k252e2G3y273r
Look at the DEMO 9 how it is selected and URL is index9.html but content is 10!
Now scroll with mouse a little and the content will refresh, for Lion Safari * {-webkit-backface-visibility: hidden;} is not a solution.
Hope that helps to replicate the issue.
It doesn’t refresh, it just jumps to the # anchor, which is the top of the page. Assuming you have jQuery on the page you could do this by putting a “disabled” class on the link.
$(“a.disabled”).click(function(event){
// do not scroll to top of page
event.preventDefault();
});
Very Very Beautiful Creativity i Love all but 3rd and 7th examples are owesome
thanks dear
Quite interesting. I am so newbie with any coding language, also with CSS3.
Just downloaded and want to try the width and height but seemed I can’t do it.
Hope for your tutorial guys!
I mean, the demo image was sized 300×200 pixel, and I want to change it.
Please take a look at my screenshot here http://www.diigo.com/item/image/1kbzn/eryj
Hello its easy here:
1. in style_common.css: http://cl.ly/2p2E0x331a100X0q1L0O
2. changed it 200x 200 – http://cl.ly/1n2f0Z1E3Z3R0x043e2q
Nice css3 example
There is a problem when used on the browser internet-explorer
Is there a solution to this problem
It’s really awsome. I’m very grateful to this site. Codrops is the best site I ever saw……..
Hi there,
I had chosen Demo 1 for my photo gallery, everything looks great in Dreamweaver, but now that I have the page uploaded on my server, the orange mask no longer appears and the effect doesn’t work.
this is the page in question: http://216.71.184.136/gallery5.htm
I’m not sure what to look for in the script (I’m still learning), would anyone know what I need to change or add to make the effect work?
Awesome effects. This is exactly what we were just working on so you have saved us a whole bunch of time. Thanks for the effort guys!!
Dave
COOL and works perfect thanks a lot
These effects are amazing! CSS has really come a long way. Thanks for the great demo.
If I want that text disappear and picture appear on hover What I need to change this way?
These are great but you can’t tell me they wouldn’t become irritating to use as an interface after a while. I like demo 5 the best because it’s simple and quick and not too jarring.
The HTML mark-up for examples 2 through 8 are the same, correct?
On my test site all works fine except on my iphone. Is there some way of making the links on the images works without the hover effects.
Tried but that didn’t work.
Wooo, I love all styles. Thanks for sharing.
Hey all, really great effects.
But i got a problem on Safari – if i hover about the div/img an other div will be hidden and after the effect it will be visible.
The div which gets hidden while the effect have only a background-image…
Someone an idea for this bug?
Hi,
I have a problem in dreamweaver. After choosing style 2 and apparently everything correct with copy\paste to the source code and layout.ccs, come the problem:
The image is there and the information box also. The information should be hidden and appear only on mousehover right???????
Any help please
Amazing effect! Works beautifully in Chrome and Firefox…
I’m having the same problem as Michael right now in Safari as seen on the site I’m currently developing:
http://roxannecook.com
When you hover over any of the portfolio items, the nav background image quickly disappears and reappears after the animation is done. Any idea what is causing this and how to fix it? Thanks!
Hi Roxanne, I don’t know why this is happening, but changing the background-attachment to “scroll” (you have “fixed”) in your header seems to solve the problem. Let me know if it works for you! Cheers, ML
That solved it! Thank you Marylou!
Love these effects very nice, keep up the great work.
How would I implement these to work for ipad/iphone?
hi. would you happen to know how to make this work in mobile devices? please advise. thank you so much.
Hi Alessio, really love the demo, cheers!
Added border-radius .view, .view .mask, view .content, and .view img to make these into circles.
It works perfectly in firefox but not with webkit or opera.
The img and mask keep popping out of the circle??
Very frustrating, dont know what the problem is so where do i look for the solution!
Any one got any ideas?
is it a glitch?
this is really great effects, i love it and any thanks for share
Hi there!
Thanks for the work you have put up for this tutorial 🙂
I’m just wondering… Could these same effects be applied and work on a responsive grid? If so, could anyone show me the way or parts of tutorials where I can find the method to do it?
Cheers!
Daniel yes sure you could put them in a responsive grid no problem, im doing it right now.
I do have a question though, why will images within the div tag not show up? Can you not have images within the mask div?
Thanks,
Matt
Thanks for these great samples. It saved me a bunch of time. and the effects are beautiful.
One Question: I couldn’t find a solution for the ipad and I’ve seen, some more guys ask the same.
Will it possible to solve this issue, especially for No. 10 ? (example: http://tinyurl.com/78c3w5r)
No. 5 is the only one which is working fine.
Best regards
Thomas
Me again. I tested it on iPad in the Apollo Browser and it worked all fine,. Nothing in Skyfire Browser.
Thomas
Thanks, love these effects. I’m having an issue on my site with these though. It shows the image and on hover it will show the title, content and button but no effect (ex. on number 1 it just has an immediate transparent background, no movement and no timed fade. On number 10 it doesn’t have the zoom effect at all and there is no time lapse in the hover.
Any help is much appreciated.
Hello!
Why it doesn’t work on the forum phpbb3?
Thanks