Got milk?

Continuing on from my example last week ("Creating Animated Inset Captions With Filtered Backgrounds Over Responsive Images"), I decided to do a black and white version, which you can see above.

One goal shared by designers and developers is to create ever-simpler solutions: less code, not more. With a little experimentation, I was able to get the I used in the earlier example down to just one figure element, while adding richer effects with .

The HTML used in the example is now simply:

<figure>
	<img src="got-milk.jpg" alt="Photograph of a man covered in milk">
	<figcaption>Got milk?</figcaption>
</figure>

Applying Filters, Sizing Text & Effects

One reason I was able to simplify the code as much as I have is the fact that the overlay version of the image (converted into greyscale through the use of ) is the background of the absolutely positioned <figcaption> element:

figure {
	margin: 0; padding: 0;
	position: relative;
	max-width: 1000px;
}
figure img { width: 100%; }
figure figcaption {
	position: absolute;
	top: 0; left: 0;
	width: 100%;
	height: 100%;
	filter: grayscale(100%);
	filter: url(desaturate.svg#greyscale);
	background: url(got-milk-large.jpg);
	background-size: contain;
	padding-left: 4vw;
	padding-top: 4vh;
	box-sizing: border-box;
	font-size: 10vw;
	color: #fff;
	text-align: center;
}

I’m using vw and vh units to size and pad the text despite the measurement units less-than-perfect support in current browsers (with the exception of IE 10, surprisingly) in order to scale the characters to the width of the <figure> element. I’m able to get away with this due to the fact that the text is also white; you’ll discover that the text color will always be presented in a greyscale value, due to the fact that a CSS filter affects everything within the element it is applied to.

The greyscale background of the image is now placed perfectly and completely over the color version. We want to clip that effect so that the <figcaption> is invisible. To that end, we add:

figure figcaption {
	clip: rect(0, 1000px, 0, 0);
}

That clips the caption into a slice that is 1000 pixels wide and no height. On hover, we want to change that:

figure:hover figcaption {
	clip: rect(0, 1000px, 400px, 0);
}

(Note that I’ve added the :hover to the <figure>, not the <figcaption> element: the latter, having no height, doesn’t have any area that can be triggered with a mouseover or touch ).

That works, but it’s all a bit sudden, like a guillotine coming down. Let’s add a that includes the animation principles of anticipation and follow-through. Back to the CSS for the <figcaption>:

figure figcaption {
	transition: .6s clip cubic-bezier(0.500, -0.440, 0.670, 1.475);
}

(Note that I’ve dropped vendor prefix variations for the sake of brevity).

That’s better: now the caption appearance has a bit of "bounce". The text still appears suddenly, however, and remains somewhat difficult to read against the background.

Chaining Transitions

If they consider transitions at all, most web developers think of the animation property as a one-shot deal, supporting moves from one state to another. That’s only true for individual properties, not for transitions of properties chained together. By separating them with commas, we can create a sequence of transitions in a single statement.

Before we do that, let’s set the default state of the text and a shadow so that it can be transitioned:

figure figcaption {
	color: rgba(255,255,255,0);
	text-shadow: 0 0 0 rgba(0,0,0,0);
}

On hover, we want to bring down the clip area first, then bring in the text, and add the shadow to distinguish the text from the background:

figure figcaption {
	transition: .6s clip cubic-bezier(0.500, -0.440, 0.670, 1.475),
	1s 1s color linear,
	1s 1.2s text-shadow ease-in-out;
}

The first number in each transition sequence is the duration of the effect; the second is the delay before it takes place. "Staggering" the two for each incremental transition creates an effect sequence you see in the example above.

That’s it! I plan to do one more version of this effect before heading on to other pastures.

Photograph by Matthias Weinberger, licensed under Creative Commons.

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.