Caption Hover Effects

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

Caption Hover Effects

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:

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 151

Comments are closed.
  1. Awesome effect. I’m trying to use this with one of your other scripts, the multi item slider
    I’m running into problems with the modernizr.customs. they are using 2 different sets of tools. I tried to download the whole modernizer with everything selected and it worked for the caption hover but not the item slider. is there some specific class name prefix or something that i need or how can i get this to work

    thanks

  2. Having issues in Chrome Version 30.0.1581.2 on Windows 8 as well as Chrome 28.0.1500.95 m in Windows 7. Tried using incognito mode to disable plugins and the plugins still aren’t triggering.

  3. I saw this article when it was just posted and it’s great post and very nice effects.

    Today I decided to use one of the effects, and noticed that you’re using tag for the images.
    I was using it this way too, but I read a couple of weeks ago that it seems like not it’s the best tag to use in this context.
    In particular, spec says that tag should allow to ‘be moved away from the main flow of the document without affecting the document’s meaning.’
    And in your case, the images inside figure tag clearly can’t be moved away.

    Here’s a great article about this issue in html5doctor: The figure & figcaption elements
    I hope you’d know something new from it, if you didn’t know it already. )
    Best wishes.

    • Hi Andrew,
      that’s a really interesting point and I was also wondering whether using the figure element makes sense here. I guess it doesn’t in this particular (demo) case because we are not really referencing to it from our main flow of the document and we can’t move it away because it actually constitutes the main flow… However, if these units are used within some primary content flow (i.e. a portfolio where one or several of these are shown along with some kind of main project description) then it would be appropriate to use the figure element. But I’ll definitely keep that in mind and thanks for pointing that out! The html5doctor article is really a great resource and I’ll add it to the post as a must-read πŸ™‚
      Thanks for the feedback, cheers, ML

  4. These are great esp 4 but a shame they doesn’t work in boring old Internet Explorer …

  5. These demos do not work in Chrome if you have a touchscreen monitor. I am using a Lenovo X1 Carbon Touch and Chrome is reporting that I have touch enabled, which I do, but not on my external monitor where I am using Chrome. So they do not work at all.

    My recommendation is to *never* use the .touch selector before the rules, and always allow the :hover to fire. Otherwise, everyone with these new touch laptops/tablets like mine or the Surface or anything else will not be able to use the effect at all.

  6. 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?

  7. 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…

  8. 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

  9. 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

  10. 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

  11. 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! πŸ™‚

  12. 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!

  13. 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.

  14. 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

  15. 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?

  16. 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

  17. 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?

  18. 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)

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

  20. Hi, very nice effect. I have only one problem. Is there a way that when you tap on mobile device the roll over for some item it will disappear on the previous item?
    Right now, when you tap an item the roll over appears and then stays visible even if you tap a second item.
    I think I have to slightly change the code in the file toucheffects.js but I don’t know how πŸ™
    Please help πŸ™‚

    • Works fine for me (latest Chrome and Firefox versions). What exactly are you referring to? Thanks.

  21. Hi! I am new to CSS transitions and animations.. I observed that these effects are not working without modernizr.js..
    Can you please explain, why is not working without Modernizr.js?

    Thanks

  22. Hi
    Im using the style 3 and I would like to add a second link button
    Thanks for helping !!

  23. I’m using the “Effect 4” from this tutorial on a web site and in the new Firefox 27.0.1 the effect has stopped working. Viewing the “demo” page here on copodrop all effects have stopped working. Any idea?

    Maybe something about css “transform” or “transition” conflict with this version of Firefox?

  24. Really like it!
    Though, I would like to use different styles on one site, and I cannot figure out how to do that…any help?

    • For all those who are having problems with Firefox. Try this:

      Go to component.css and add figure:hover for each of the 7 styles where you see figure.cs-hover. So for CS Style 1 go to line 74 and add this line .cs-style-1 figure:hover figcaption.

      Example:

      .no-touch .cs-style-1 figure:hover figcaption, .cs-style-1 figure.cs-hover figcaption, .cs-style-1 figure:hover figcaption {

      This would solve the FF Problem.

      Thanks
      Arslan Akram