Using Custom Data Attributes and Pseudo-Elements

A tutorial on how to (ab)use custom data attributes and pseudo-elements for creating image captions.

PseudoElementsImageCaptions

In today’s tutorial I want to show you some simple CSS tricks using data attributes and pseudo-elements. The aim is to create an image caption using only an anchor and an image as markup. We’ll be exploring how to create pseudo-elements from some data attribute values and use them in a hover effect or simply show them next to the image. Using (more) semantic markup is of course what you should be doing, especially for data that is important to be shown. But this is a mere exercise for learning how to use those properties and how to create some nice effects.

If you’d like to explore some fancy image caption hover effects with “real” markup, check out the Caption Hover Effects.

And if you are interested in some really cool animations and transitions with pseudo-elements, then check out this article by Marco Barria: Examples of Pseudo-Elements Animations and Transitions.

The demos feature some beautiful artwork by Jaime Martinez.

Please note that we will be using some CSS features that might not work in older browsers. Animating pseudo-elements is still not supported by every browser.

Let’s start with the markup. As already mentioned, we’ll be using an image that is wrapped within an anchor:

<a 
	class="caption" 
	href="http://cargocollective.com/jaimemartinez/Illustration" 
	data-title="Smug Eagle" 
	data-description="I watched the four riders ...">

	<img src="images/1.jpg" alt="Illustration of Smug Eagle">
	
</a>

As you can see, we define two data attributes, one for the title and one for the description. The values of these attributes will be used in the pseudo elements :before and :after.

Our first image caption will be a static one: we want to place the content of the data attributes right next to the image. For that we’ll first style the anchor and the image:

.caption {
	display: inline-block;
	position: relative;
	margin: 10px;
}

.caption img {
	display: block;
	max-width: 100%;
}

The anchor will be displayed as an inline-block element, allowing content to flow around it. We add some margin and set the position to relative. This is important because we’ll position the pseudo-elements absolutely and this will allow us to do so relatively to the anchor.

Giving the image a max-width of 100% prepares it for a responsive environment.

Example 1: Caption next to image

Now, let’s make that first magic caption from the data-title and data-description values. We want both pseudo-elements to be absolutely positioned, on the right side next to the image. Let’s define some common styles for both:

.caption::before,
.caption::after {
	position: absolute;
	left: 100%;
	width: 90%;
	margin: 0 0 0 10%;
	font-weight: 300;
	color: #89867e;
}

By setting the left to 100%, we put the pseudo-elements right next to the image. 90% is relative to the width of our anchor which again is defined by its content, the image.

Let’s set the content for each pseudo-element. We’ll get the value of the respective data attribute and add it to the content of the pseudo-element by using attr():

.caption::before {
	content: attr(data-title);
	top: 0;
	height: 25%;
	padding: 5px 30px 15px 10px;
	font-size: 40px;
	border-bottom: 1px solid rgba(0,0,0,0.1);
}

Besides some dimension styling, we’ll do the same with the :after pseudo-element:

.caption::after {
	content: attr(data-description);
	top: 25%;
	padding: 20px 10px 0;
	font-size: 18px;
}

Check out the result of what we just did:

Example 2: Show on hover (opacity)

Now, let’s make a caption that shows on hover by simply animating the opacity of the pseudo-elements. For that we’ll set them to an absolute position again. But this time, they will cover the image. Setting the opacity to 0 and a transition for the opacity, will allow us to animate it on hover:

.caption::before,
.caption::after {
	opacity: 0;
	position: absolute;
	width: 100%;
	color: #fff;
	padding: 20px;
	transition: opacity 0.3s; 
}

The title will have a different background color than the description and we’ll restrict its height to 30% of the total height:

.caption::before {
	content: attr(data-title);
	top: 0;
	height: 30%;
	background: #a21f00;
	font-size: 40px;
	font-weight: 300;
}

For the description we will not simply add the data-description value, but we will prepend and append an opening and a closing quotation marks. For that we add the CSS values for the marks which we converted with a tool like the Entity Conversion Calculator by Evolution Technologies. The background will be slightly lighter to the one of the title and we will align the text to the right:

.caption::after {
	content: '201C' attr(data-description) '201D';
	top: 30%;
	height: 70%;
	background: #db2e00;
	font-size: 16px;
	text-align: right;
}

Since the title has a height of 30%, we will give the description the resting height of 70%.

And finally, we set the opacity to 1 on hover:

.caption:hover::before,
.caption:hover::after {
	opacity: 1;
}

The result of this style is the following (hover over the image):

Example 3: Slide in on hover (transform)

In the next example we want to show the caption with a bit more fanciness. On hover, we want it to slide in the title from the top and the description from the bottom. We also want to make the image darker to simulate a shadow. For that, we need to define some more things for the caption anchor and image.

The anchor’s overflow needs to be set to hidden because we need to position our title and description outside of it and we, of course, don’t want to see them. Additionally, we’ll give the anchor a black background so that we can darken the image when we reduce its opacity:

.caption {
	display: inline-block;
	position: relative;
	margin: 10px;
	overflow: hidden;
	background: #000;
}

We’ll add a transition to the image and set the opacity to 0.5 once we hover. This will make the image appear darker, just as we want:

.caption img {
	display: block;
	max-width: 100%;
	transition: opacity 0.3s ease-in-out; 
}

.caption:hover img {
	opacity: 0.5;
}

The common style of the ::before and ::after pseudo-elements is similar to the previous examples, just that we now give them an equal height and set the z-index to 1 so that they really stay on top of the image. The transition that we are adding will be for the transform. As you will see in the individual styles, we’ll position the pseudo-elements outside of the anchor rectangle by translating them on the Y-axis.

.caption::after,
.caption::before {
	position: absolute;
	width: 100%;
	height: 50%;
	color: #fff;
	z-index: 1;
	transition: transform 0.3s ease-in-out; 
}

Let’s set the background colors for the pseudo-elements and the transforms to move the title up and the description down:

.caption::after {
	content: attr(data-title);
	top: 0;
	background: #0083ab;
	font-size: 40px;
	font-weight: 300;
	padding: 30px;
	transform: translateY(-100%);
}

.caption::before {
	content: '...' attr(data-description) '...';
	top: 50%;
	background: #f27545;
	font-size: 14px;
	padding: 20px;
	transform: translateY(100%);
}

And on hover, we simply set the transform to translateY(0%) so that they go to the position we defined with the tops:

.caption:hover::after,
.caption:hover::before {
	transform: translateY(0%);
}

Example 4: Side push on hover (transform)

The last example that we want to do is a fancy “side push”. On hover, we want to move the image to the right while sliding in the pseudo-elements from the left, slightly shifted.

Let’s again create the shadow effect by animating the background of the anchor from a semi-transparent black to transparent:

.caption {
	display: inline-block;
	position: relative;
	margin: 10px;
	overflow: hidden;
	background: rgba(0,0,0,0.2);
	transition: background 0.3s ease-in-out;
}

.caption:hover {
	background: rgba(0,0,0,0);
}

The image will move to the right when we hover. For that, we’ll use translateX:

.caption img {
	display: block;
	max-width: 100%;
	transition: transform 0.3s ease-in-out;
}

.caption:hover img {
	transform: translateX(100%);
}

The pseudo-elements need to be beneath the anchor, so we’ll set a z-index of -1. The initial transform will set them to the left side:

.caption::before,
.caption::after {
	position: absolute;
	width: 100%;
	z-index: -1;
	background: #cecece;
	transform: translateX(-30%);
	transition: transform 0.3s ease-in-out;
}

As before, we will add the respective content to the pseudo-elements and give them a height and some styles for the text:

.caption::before {
	content: attr(data-title);
	height: 30%;
	color: #05b19a;
	font-size: 40px;
	font-weight: 300;
	padding: 30px;
}

.caption::after {
	content: '201C' attr(data-description) '201D';
	top: 30%;
	height: 70%;
	color: #fff;
	font-size: 14px;
	padding: 20px 30px;
}

And on hover, we’ll simply set the translateX to 0:

.caption:hover::before,
.caption:hover::after  {
	transform: translateX(0%);
}

See the result of this last example:

And that’s it! I hope you learned some new and interesting tricks, how to use pseudo-elements and how to give them the content of an attribute (think of others, not only custom data attributes) and how to animate them. Keep in mind that you should always add important content to the markup.

You can view all examples in this demo or download the ZIP file.

Please let me know if you enjoyed this tutorial and if would like to see more topics explored. Drop us a line if you have something specific in mind.

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.