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.