I'm Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with HTML, CSS and SVG. To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

my books

Pro CSS3 Animation book coverPro CSS3 Animation, Apress, 2013

my other blogs

Massive Head CanonMassive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

The New DefaultsThe New Defaults — A Sass color keyword system for designers.

CSSslidyCSSslidy — an auto-generated #RWD image slider. 3.8K of JS, no JQuery.

Filtered HTML5 Image Caption With Dynamic Clip

Featuring an unappreciated aspect of CSS3 transitions

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 HTML I used in the earlier example down to just one figure element, while adding richer effects with CSS.

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 CSS filters) 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%; -webkit-filter: grayscale(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 transition 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.

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.