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.

Animated Inset Captions With Filtered Backgrounds

Blurring the backgrounds of adaptive photo captions with CSS3

Placing text on top of an image requires careful attention to color and contrast to maintain legibility. Print designers have traditionally used partially opaque backgrounds over photographs to achieve this end, an effect replicated on the web many times.

Looking at the site mockups of my students this week I realized that some of them were suggesting a variation in which a text background was blurred, an effect associated with television news overlays. The technique could be used for static inset captions over photographs, or as animated text that transitions into visibility over an image; I decided to replicate the effect in animated, responsive CSS.

One might assume that simply placing a filtered div over an image might do the trick, but that doesn’t work: CSS filters affect content inside the element they are applied to, not content beneath. To render the effect successfully we’ll need to apply two copies of the same image: one inside a parent element, and one inside its child. In this example the parent element is a header, but it could be almost any tag:

<header>
<img src=jellyfish.jpg alt="Photograph of a jellyfish">
<figure>
<img src=jellyfish.jpg alt="">
<figcaption><strong>Turritopsis nutricula</strong> is a hydrozoan that can revert from mature jellyfish to its polyp stage in recursive cycles, effectively making the animal immortal.</figcaption>
</figure>
</header>

Our first challenge is to make the two images overlap exactly. To do that, we’ll remove margin and padding on all elements:

body, header, figure { margin: 0; padding: 0; }

Both the figure and figcaption are provided with relative positioning. I’ll set up a grouped selector to affect them both at the same time:

figure, figcaption { position: relative; font-family: Calluna Sans, sans-serif; color: #fff; text-shadow: 2px 2px 1px rgba(0,0,0,0.6); }

Then we set both of the images to position: absolute, ensuring that they align perfectly with each other.

header img, figure img { position: absolute;top:0;left:0;width:100%;height:auto;; }

Next, we’ll blur the topmost image. I’ve talked about cross-browser blur filters before, so I won’t go over the code here. For this example I’ll show only the Webkit/Firefox CSS, for the sake of clarity:

figure img { -webkit-filter: blur(10px);  filter: url(blur.svg); }

Clipping The Effect

The result to this point is that the topmost image is completely blurred. To limit the area of the blur and make the rest of the photograph invisible we’ll clip the image:

figure img { clip: rect(10px,300px,600px,30px); }

The important thing to remember about clip is that the numbers represent offsets from the image’s original top and left edges to determine its new top, right, bottom and left sides, respectively. The numbers we have used represent a visible area 270 pixels wide (right - left) and 590 pixels tall (bottom - top).

If you wanted to keep the effect static, at this stage you only need to position the figcaption over this area:

figcaption { left:30px;top:10px;width: 300px; padding: 50px; box-sizing: border-box; font-size: 4vw; }

(Note that I’ve used box-sizing: border-box to ensure that the added padding does not “bloat” the figcaption beyond the width of the clipped image. I’ve also used vw units to provide the text with some responsiveness).

Layers of the blurred background caption effect

Animating The Caption

Currently filters can only be animated in Webkit, but opacity can be transitioned in every modern browser. We’ll do both, sans vendor prefixes (with the exception of filters) to keep the code clear. Note that we reset the default state of the image.

figure img { clip: rect(10px,300px,600px,30px); -webkit-filter: blur(0px); transition: 1s -webkit-filter; }
figcaption { left:30px;top:10px;width:270px; padding: 50px; box-sizing: border-box; font-size: 4vw; opacity: 0;
transition: 1.2s .6s all; }
figure:hover figcaption { opacity: 1; }
figure:hover img { -webkit-filter: blur(10px); }

That’s it: the caption will now fade in over the image, with a blur effect under the text. Applying different filters would allow you to fade in caption text over greyscale image areas, or contrast-shifted boxes, variations I will show in future articles.

Drawbacks, Solutions & The Future

One disadvantage of the technique is that the inset box is a very particular and limited size, meaning that the caption will not act entirely responsively: clip cannot take percentage length values, at least not consistently. The obvious (if unsatisfying) solution is to keep the caption text short; a better solution for modern browsers is to size the text using vw units, as I’ve done here, to enable the size of the text to scale with the viewport.

The transition effect is not yet perfect, due to browser rendering issues: Firefox leaves a shaded box behind after the transition reverts, while Chrome adds a just-discernable jump to the clip effect. I expect that both these issues will be addressed by browser updates in the very near future.

Long term this same effect will likely be achievable with Adobe’s proposed Custom CSS Filters, but popular cross-browser support of that is likely several years off.

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.