Caption Hover Effects

A tutorial on how to create some subtle and modern caption hover effects.
Caption Hover Effects

From our sponsor: Try Mailchimp today.

Today we want to show you how to create some simple, yet stylish hover effects for image captions. The idea is to have a grid of figures and apply a hover effect to the items which will reveal a caption with the title, author and a link button. For some of the effects we will use 3D transforms. The aim is to keep the effects subtle and provide inspiration for many different variations.

Please note: this only works as intended in browsers that support the respective CSS properties.

The images used in the demos are Dribbble shots by talented Jacob Cummings.

Let’s get started.

The Markup

The structure of our grid and the figures will be made of an unordered list and each item will contain a figure element. The figure will contain an image and a figcaption with some text elements and a link:

<ul class="grid cs-style-1">
	<li>
		<figure>
			<img src="images/1.png" alt="img01">
			<figcaption>
				<h3>Camera</h3>
				<span>Jacob Cummings</span>
				<a href="http://dribbble.com/shots/1115632-Camera">Take a look</a>
			</figcaption>
		</figure>
	</li>
	<li>
		<figure>
			<!-- ... -->
		</figure>
	</li>
	<!-- ... -->
</ul>

Please note that using a figure only makes sense if it does not constitute the main content itself but if it’s typically referenced from the main flow of the document and if we can move it away (to an appendix for example). Read more about the figure element in this great HTML5 Doctor article: The figure & figcaption elements.

This is the default structure for all the grid examples. Note that for effect 4 we will have an additional division wrapping the image.
The class for each single effect will be added to the list; so example 1 will have “cs-style-1”, example 2 will have “cs-style-2” and so on. That’s how we will define the effect styles for each single example.

But first let’s define the common styles for all effects.

The CSS

Note that the CSS will not contain any vendor prefixes, but you will find them in the files.

The common styles for all the figures is the following. First, we’ll define the styles for the grid and the list items that will serve as the containers of our figures:

.grid {
	padding: 20px 20px 100px 20px;
	max-width: 1300px;
	margin: 0 auto;
	list-style: none;
	text-align: center;
}

.grid li {
	display: inline-block;
	width: 440px;
	margin: 0;
	padding: 20px;
	text-align: left;
	position: relative;
}

Making the list items display as inline-blocks will allow us to center them be applying a centerd text-align to the parent.

Let’s reset the margins of the figure elements and set the position to relative. Our figcaption will be positioned absolutely, so we need to make sure it will do so inside of the figure:

.grid figure {
	margin: 0;
	position: relative;
}

The image will have a maximum width of 100% which will come in handy when we define a media query to resize the list items:

.grid figure img {
	max-width: 100%;
	display: block;
	position: relative;
}

The figcaption will be positioned absolutely. By default it will be positioned in the top left corner. We won’t define any width or height here as we will do so in all the individual styles:

.grid figcaption {
	position: absolute;
	top: 0;
	left: 0;
	padding: 20px;
	background: #2c3f52;
	color: #ed4e6e;
}

And finally, let’s define some styles for the text elements and the link:

.grid figcaption h3 {
	margin: 0;
	padding: 0;
	color: #fff;
}

.grid figcaption span:before {
	content: 'by ';
}

.grid figcaption a {
	text-align: center;
	padding: 5px 10px;
	border-radius: 2px;
	display: inline-block;
	background: #ed4e6e;
	color: #fff;
}

We’ll add the “by” for the span that contains the author name using the pseudo-class :before. Of course you can add that in the HTML, but this will give you the freedom to change it easily into something like “made by” or “Designer: ” or similar. Be careful not to remove meaning from your HTML, though, by doing something like this.

In the end of our CSS we will also add a media query for smaller screens:

@media screen and (max-width: 31.5em) {
	.grid {
		padding: 10px 10px 100px 10px;
	}
	.grid li {
		width: 100%;
		min-width: 300px;
	}
}

And now let’s start by doing some nice effects.

Note that we will use Modernizr to detect touch. But be aware that this is not 100% bulletproof for testing if you are on a touch device as pointed out here. We will replace the hover for the touch and add a class that will trigger the effects when we have detected touch. So you will always see another rule for that in addition to the :hover. We only want the hover to trigger when we don’t detect touch.

Effect 1

Caption Hover Effect 1

Let’s start with a very simple effect. We want the caption to fade in and move a bit to the right and down, creating the illusion of a 3D layer that comes out of the image.

For that we first need to set the width and height of the figcaption and set the initial opacity to 0:

.cs-style-1 figcaption {
	height: 100%;
	width: 100%;
	opacity: 0;
	text-align: center;
	backface-visibility: hidden;
	transition: transform 0.3s, opacity 0.3s;
}

We also add a transition and set the backface-visibility to hidden to avoid a jump in the text rendering in the end of the transition. You don’t have to use that if you don’t mind the little glitch.

On hover (or on touch) we will set the opacity to 1 and translate the figcaption a bit:

.no-touch .cs-style-1 figure:hover figcaption,
.cs-style-1 figure.cs-hover figcaption {
	opacity: 1;
	transform: translate(15px, 15px);
}

Additionally, we will position the text elements:

.cs-style-1 figcaption h3 {
	margin-top: 70px;
}

.cs-style-1 figcaption span {
	display: block;
}

.cs-style-1 figcaption a {
	margin-top: 30px;
}

Effect 2

CaptionHoverEffect2

This effect will move the image up and reveal the figcaption just like you can see on Minimamente from which it got inspired by.

So let’s add a transition for the transform to the image and make it move up on hover:

.cs-style-2 figure img {
	z-index: 10;
	transition: transform 0.4s;
}

.no-touch .cs-style-2 figure:hover img,
.cs-style-2 figure.cs-hover img {
	transform: translateY(-90px);
}

We’ve set the z-index to 10, so that the image stays on top of the caption.

The figcaption needs a fixed height and a width of 100%. We’ll stick it to the bottom of the figure:

.cs-style-2 figcaption {
	height: 90px;
	width: 100%;
	top: auto;
	bottom: 0;
}

Let’s also position the link button on the right side:

.cs-style-2 figcaption a {
	position: absolute;
	right: 20px;
	top: 30px;
}

Effect 3

CaptionHoverEffect3

A different approach to effect 2 is to hide any overflow when moving the image. Let’s do that and make it appear as if the caption is slightly pushing the image up.

First, we need to set the overflow of the figure to hidden. Like this we won’t see anything that spills out when moving around:

.cs-style-3 figure {
	overflow: hidden;
}

The image needs a transition for the transform and on hover we will translate it 50px up:

.cs-style-3 figure img {
	transition: transform 0.4s;
}

.no-touch .cs-style-3 figure:hover img,
.cs-style-3 figure.cs-hover img {
	transform: translateY(-50px);
}

The figcaption will be a bit higher than in the previous example and we will translate it out of the view of the figure. Let’s also add a transition for the transform and the opacity:

.cs-style-3 figcaption {
	height: 100px;
	width: 100%;
	top: auto;
	bottom: 0;
	opacity: 0;
	transform: translateY(100%);
	transition: transform 0.4s, opacity 0.1s 0.3s;
}

On hover we’ll set to opacity to 1 and translate it up. See how we have added two transitions? One for the normal state and one for the hover? This is how we can control what happens when we hover and when we hover out. The transition here will be applied on hover: we want the element to become opaque quickly while taking 0.4 seconds for the transform. When we hover out, the opacity will be set again to 0 but only after a delay of 0.3 seconds. This will make the effect look consistent and natural.

.no-touch .cs-style-3 figure:hover figcaption,
.cs-style-3 figure.cs-hover figcaption {
	opacity: 1;
	transform: translateY(0px);
	transition: transform 0.4s, opacity 0.1s;
}

Let’s not forget about our link button:

.cs-style-3 figcaption a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

Effect 4

CaptionHoverEffect4

The forth example will make use of some 3D goodness. The aim is to flip the caption from the left side and push the image to the right.

We will use the list item as a perspective container so that we can play around with 3D transforms:

The CSS

.cs-style-4 li {
	perspective: 1700px;
	perspective-origin: 0 50%;
}

The child needs to have the following transform-style if we want the 3D transforms to work in the other elements:

.cs-style-4 figure {
	transform-style: preserve-3d;
}

As mentioned earlier, this example is going to have another wrapper for the image, Why do we need this? Well, we need to set the image’s parent to overflow hidden, because we don’t want to see the image spilling out of the container when we move it. We could set the overflow of the figure to hidden but then we won’t see the beautiful 3D effect of the caption. So, let’s add another wrapper and set it to overflow hidden instead:

.cs-style-4 figure > div {
	overflow: hidden;
}

Let’s move the image on hover:

.cs-style-4 figure img {
	transition: transform 0.4s;
}

.no-touch .cs-style-4 figure:hover img,
.cs-style-4 figure.cs-hover img {
	transform: translateX(25%);
}

The figcaption will have half of the width of the figure and we’ll set its initial opacity to 0. Now, let’s rotate it 90 degrees on the Y-axis which will make it be flipped towards us with the origin on its left side. We would basically not see it like that. Let’s set a transition for the “hover out” which will work in the same principle like described in the previous example:

.cs-style-4 figcaption {
	height: 100%;
	width: 50%;
	opacity: 0;
	backface-visibility: hidden;
	transform-origin: 0 0;
	transform: rotateY(-90deg);
	transition: transform 0.4s, opacity 0.1s 0.3s;
}

On hover we will fade it in and rotate it to 0 degrees, making it flip like a page of a book from the left side:

.no-touch .cs-style-4 figure:hover figcaption,
.cs-style-4 figure.cs-hover figcaption {
	opacity: 1;
	transform: rotateY(0deg);
	transition: transform 0.4s, opacity 0.1s;
}

Last, but not least, our little link button:

.cs-style-4 figcaption a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

Effect 5

CaptionHoverEffect5

This effect will make the image shrink and scale the caption in from the back.

Let’s put the image on top of the caption and add a transition for the transform:

.cs-style-5 figure img {
	z-index: 10;
	transition: transform 0.4s;
}

On hover, we want to scale the image down:

.no-touch .cs-style-5 figure:hover img,
.cs-style-5 figure.cs-hover img {
	transform: scale(0.4);
}

The caption will initially scaled to 0.7 and faded out:

.cs-style-5 figcaption {
	height: 100%;
	width: 100%;
	opacity: 0;
	transform: scale(0.7);
	backface-visibility: hidden;
	transition: transform 0.4s, opacity 0.4s;
}

On hover, we will scale it up and fade it in:

.no-touch .cs-style-5 figure:hover figcaption,
.cs-style-5 figure.cs-hover figcaption {
	transform: scale(1);
	opacity: 1;
}

Super-easy. Oh, and of course, the little link button wants to be in the bottom right corner:

.cs-style-5 figure a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

Effect 6

CaptionHoverEffect6

This effect is a variation of effect 5. There are many possibilities to play around with this type of effect, think about positioning the image in a different place and showing some more text. This effect will position the text and the image in a different place than before and we will not fade the caption in or scale it, it will already be there, creating a different “environment”.

So, let’s again do the same thing for the image, just that on hover we will also translate it up a bit:

.cs-style-6 figure img {
	z-index: 10;
	transition: transform 0.4s;
}

.no-touch .cs-style-6 figure:hover img,
.cs-style-6 figure.cs-hover img {
	transform: translateY(-50px) scale(0.5);
}

So, no transition for the caption this time:

.cs-style-6 figcaption {
	height: 100%;
	width: 100%;
}

And let’s position the text elements:

.cs-style-6 figcaption h3 {
	margin-top: 60%;
}

.cs-style-6 figcaption a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

Effect 7

CaptionHoverEffect7

The last effect in this tutorial will “grow” the caption from behind the image, making it look like a frame.

Since the frame of the first elements will be overlapping the other list items, we have to make sure that the z-indexes are correct (reversed):

.cs-style-7 li:first-child { z-index: 6; }
.cs-style-7 li:nth-child(2) { z-index: 5; }
.cs-style-7 li:nth-child(3) { z-index: 4; }
.cs-style-7 li:nth-child(4) { z-index: 3; }
.cs-style-7 li:nth-child(5) { z-index: 2; }
.cs-style-7 li:nth-child(6) { z-index: 1; }

Just like in the previous examples, we want the image to be on top of the caption:

.cs-style-7 figure img {
	z-index: 10;
}

The caption will be 100% of the figure and we’ll set the transition for the opacity, height and box-shadow. Why the box shadow? We can easily use the box shadow to create a frame around the caption:

.cs-style-7 figcaption {
	height: 100%;
	width: 100%;
	opacity: 0;
	backface-visibility: hidden;
	box-shadow: 0 0 0 0px #2c3f52;
	transition: opacity 0.3s, height 0.3s, box-shadow 0.3s;
}

On hover we will set the opacity to 1, increase the height and set the box shadow’s spread to 10 pixels:

.no-touch .cs-style-7 figure:hover figcaption,
.cs-style-7 figure.cs-hover figcaption {
	opacity: 1;
	height: 130%;
	box-shadow: 0 0 0 10px #2c3f52;
}

Let’s position the text elements. We want the elements to appear just after we animated the caption’s height but when we “hover out”, we want them to disappear immediately. So we’ll set the transition-duration to 0 seconds for the normal state.

.cs-style-7 figcaption h3 {
	margin-top: 86%;
}

.cs-style-7 figcaption h3,
.cs-style-7 figcaption span,
.cs-style-7 figcaption a {
	opacity: 0;
	transition: opacity 0s;
}

.cs-style-7 figcaption a {
	position: absolute;
	bottom: 20px;
	right: 20px;
}

On hover we will make all elements appear with a delay:

.no-touch .cs-style-7 figure:hover figcaption h3,
.no-touch .cs-style-7 figure:hover figcaption span,
.no-touch .cs-style-7 figure:hover figcaption a,
.cs-style-7 figure.cs-hover figcaption h3,
.cs-style-7 figure.cs-hover figcaption span,
.cs-style-7 figure.cs-hover figcaption a {
	transition: opacity 0.3s 0.2s;
	opacity: 1;
}

And that’s it! I hope you enjoyed this tutorial and got inspired to create many cool caption hover effects.

Tagged with:

Mary Lou

ML is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

http://www.codrops.com

Stay up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 151

Comments are closed.
  1. Dear Mari Lou, I’ve done the tutorial step by step and gave me good results.
    But then I tried to achieve the effects in an article in Joomla 2.5.x and targeted not so lucky, because although css styles are met, can not see the hover effect.
    I placed the call to the js script in the index of my site. Is there a pattern to make it work?

  2. I too have been getting a little flicker after the picture completely transforms and then once again after I hover OUT. If I scroll the page whilst passing over an img container… the WHOLE page flickrs with that img… NOT in Safari, nor Firefox… On MY chrome like I said, it flickers, however on other’s chrome browsers, it doesnt… I can’t seem to think what the problem COULD be… I’m assuming maybe something with js…

  3. Hi Mary Lou

    Awesome effects, thank you. I was wondering if it’s possible to turn the effects off for certain screen sizes?

    Thanks,
    Gavin

  4. Hi Mary Lou,

    Im experiencing the same problem a few others are, a little flicker after the picture completes its hover animation and again after i have hovered off? Any solution?

    Thanks
    Chris

  5. Hi Mary,

    These are beautiful, love them and trying to implement them into the new build of my portfolio site, just having a bit of trouble with them on mobile, they don’t appear on tap on an iPhone or iPad for me, so anyone viewing on mobile can’t actually enter into, or see the title of the projects?

    Any idea how to get around this?

    David

  6. I’m also experiencing the flicker issue (even with the downloaded files). I’ve tested it in Chrome and i get the flicker, but not in Firefox.

    I’m using Chrome Version 29.0.1547.65.

    It’s worth noting that the flicker does not occur on the demo page. Maybe there is something else being pulled through from tympanus.net that is preventing the flicker. I’ll investigate and see if I can find out what! 🙂

  7. Hi, thanks for these great effects, I’m playing with the Demo 6 but wit .jpg images, and when the image is scaled, at the end of the animation it looses all its focus and becomes all blurry. It stays sharp while transitioning though. Anyone else experiencing this issue? Any ideas?

    Thanks a lot!

  8. Hi Everyone,

    Thanks for this fantastic work.
    I would like to use some of these effects on my wordpress wibesite.
    Does someone know how to make this work in wordpress?

    Regards,

    Shari

    • Works for me in the same versions of Chrome and Firefox. Can you please describe what you see? Thanks.

    • Yeah, I’m having the same issue. Working great in Safari 5.1.7, but nothing on Chrome 29.0.1547.76 or Firefox 24. Sussing around in add-ins and other possibles.

  9. Hi,

    i tried to implement this demo in a WordPress site, and I lost the header and nav.

    Any thoughts as to why that would happen???

    thanks

    C

  10. Quick question. I notice that you didn’t use the browser engine specific CSS3 properties (transform/transition/etc) but on the GitHub code you do have the whole set of properties for each browser. Is this something that you got pre-processed by another library or you just didn’t include all of the properties for demonstration purposes?

  11. Is there a good fallback for non-supported browsers? I’m looking specifically for IE8 and below. By default it just displays the figcaption in an opened state.

    Thanks

  12. HI when I view the online examples of effect the effcts on this website they work in IE. However the downloaded files are not working in IE 10 and below for me. Not sure what is missing?

    • It works in IE 9, 10. Except IE 8 the caption screen is viewable before the mouse event occurs?

  13. I have a using “background-attachment: fixed” below these grids. But when applying a translate to them, the background image of will flash. (If move the section before grids, it’ll be OK…).
    Is there anyway to fix this bug? (only in webkit browsers)

  14. I really love this effect… you guys rock (As useall 😉 – but the problem it makes other relative positined elements “twich” on the site…