1   Idea

There are some websites showing pictures with over-image-caption, for example, this cat photo on Posterous.com. Move your cursor over the photo, you will see a rounded bar shows up offering some actions you can take. I began to think if I can use similar thing to add a photo caption over the photo. I knew there is a CSS gradients1, which can help me archive my goal with better visual effect.

Why do I need a caption, because it’s a way to add attribution. Many photos on Internet are licensed under the Creative Commons, therefore you must attribute the work author. I think it’s a great way to put attribution to photo caption.

The following photo2 should demonstrate what I want to show you, you can view this screenshot for the correct result if your browser doesn’t support.

Paper Kite
Zebra Butterfly by San Diego Shooter, on Flickr

2   Styles

2.1   Image

This image has a border with padding inside. The style is from default Blogger Simple template. I found it’s quite neat, normally, I don’t like borders around images, but I like this style. Its CSS style is listed as follows:

.post-body img {
  padding: 5px;
  background: #ffffff;
  border: 1px solid #eeeeee;
  -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
  -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
  box-shadow: 1px 1px 5px rgba(0, 0, 0, .1);
}

As you can see, it uses another CSS3 feature box-shadow.

2.2   Caption Strip

I call this caption style as Photo Caption Strip.

2.2.1   Gradient

It’s really simple to make a gradient background for an element:

div.image-wrapper > div.caption {
  background-image: -webkit-gradient(linear, left bottom, right bottom, from(#000), to(#fff));
  background-image: -moz-linear-gradient(left,  #000,  #fff);
  background-image: linear-gradient(left,  #000,  #fff);
}

You can see the gradient is in place of background-image, generally, gradients could be applied on any kind of CSS image property.

2.2.2   Position

When I tried to make this caption to be placed over the photo, I tried to simply put a new caption element right after image and use position: relative to move the caption element up. But this results a problem, it will leave an blank (white) space at where the caption’s original place. One solution is to use a wrapper and compensate with margin-bottom. See the code as follows:

<div class="image-wrapper">
  <img>
  <div class="caption">Caption</div>
</div>

<style>
  div.image-wrapper{
    margin-bottom: -3em;
  }

  div.image-wrapper > div.caption {
    position: relative;
    top: -3em;
  }
</style>

This would do the trick. I also tried to directly use margin on caption to compensate, but the caption would go below the image. I couldn’t figure out the reason, therefore I came out the resolution as shown above.

2.2.3   More touch-ups

The following CSS sets the text style, white text, shadow to increase the readability, opacity at 75%, align to center. margin to make sure this caption strip stay on the edges of photo not image element, this would look better.

div.image-wrapper > div.caption {
  background-color: #000;
  color: #fff;
  text-shadow: #000 1px 1px 0;
  opacity: 0.75;
  font-size: 2em;
  text-align: center;
    margin: auto 6px;
  padding: 0 6px;
    height: 1.4em;
    overflow: hidden;
}

The background-color is a fail-back option for browsers do not support gradient, so visitors can still see text in white on black.

What if the caption has long length content? height and overflow could ensure only one-liner, height has to be same as line-height.

You might not want the photo to be covered by the strip, you might want the visitor to view the image without the caption. The following code uses CSS3 transition module to add a nice effect, the caption would fade out when cursor hovers the image:

div.image-wrapper > div.caption {
  -webkit-transition-property: opacity;
  -webkit-transition-duration: 0.5s;
  -moz-transition-property: opacity;
  -moz-transition-duration: 0.5s;
  -o-transition-property: opacity;
  -o-transition-duration: 0.5s;
  transition-property: opacity;
  transition-duration: 0.5s;
  }

div.image-wrapper:hover > div.caption {
  opacity: 0;
}

This effect could also be achieved by using JavaScript, but if you can use simple few lines, why bother to reinvent the wheel?

You can also use CSS transform to rotate the image a bit:

Zebra Butterfly
Zebra Butterfly by San Diego Shooter, on Flickr
<div class="image-wrapper" style="-webkit-transform: rotate(15deg); -moz-transform: rotate(15deg); -o-transform: rotate(15deg); width: 500px; opacity: 0.5; margin: auto;">
<a href="https://www.flickr.com/photos/nathaninsandiego/4526594659/" title="Zebra Butterfly by San Diego Shooter, on Flickr"><img src="http://farm5.static.flickr.com/4065/4526594659_eb88185182.jpg" width="500" height="333" alt="Zebra Butterfly" /></a>
<div class="caption">Zebra Butterfly by San Diego Shooter, on Flickr</div>
</div>

2.2.4   Complete CSS

div.image-wrapper{
  margin-bottom: -3em;
}

div.image-wrapper > div.caption {
  background-image: -webkit-gradient(linear, left bottom, right bottom, from(#000), to(#fff));
  background-image: -moz-linear-gradient(left,  #000,  #fff);
  background-image: linear-gradient(left,  #000,  #fff);

  position: relative;
  top: -3em;

  background-color: #000;
  color: #fff;
  text-shadow: #000 1px 1px 0;
  opacity: 0.75;
  font-size: 2em;
  text-align: center;
  margin: auto 0;
  padding: 0 6px;
  height: 1.4em;
  overflow: hidden;

  -webkit-transition-property: opacity;
  -webkit-transition-duration: 0.5s;
  -moz-transition-property: opacity;
  -moz-transition-duration: 0.5s;
  -o-transition-property: opacity;
  -o-transition-duration: 0.5s;
  transition-property: opacity;
  transition-duration: 0.5s;
}

div.image-wrapper:hover > div.caption {
  opacity: 0;
}

3   Auto-caption using jQuery

Here I am going to use jQuery to make auto-caption if the image embedding code is copied from Flickr.

Welcome to the Carlsbad flower fields
<a class="auto-caption" href="https://www.flickr.com/photos/nathaninsandiego/4521036886/" title="Welcome to the Carlsbad flower fields by San Diego Shooter, on Flickr"><img src="http://farm3.staticflickr.com/2743/4521036886_f9669dc969_z.jpg" width="640" height="427" alt="Welcome to the Carlsbad flower fields"></a>

<script>
$(function (){
  $('a.auto-caption[href^="https://www.flickr.com/photos"]').each(function (i, e){
    var $e = $(e);
    var $wrapper = $('<div></div>').addClass('image-wrapper');

    $e_clone = $e.clone().appendTo($wrapper);

    $('<div></div>')
      .addClass('caption')
      .html(
        $('<a></a>')
          .attr('href', $e.attr('href'))
          .attr('title', $e.attr('title'))
          .text($e.attr('title'))
        )
      .appendTo($wrapper)
      ;

    $e.replaceWith($wrapper);
    });
  });
</script>

The JavaScript isn’t hard to understand if you know jQuery already, the image embedding code is almost same as provided from Flickr, only a class="auto-caption" is added, which allows the JavaScript code to know which needs to be added a caption.

4   Conclusion

Currently, many CSS feature in this article are not supported or just a draft in standard or the syntax is different in browsers. You may need to add few more CSS, so it would have same result in different browsers. For linear gradient, you can check out this page; for transition, read this page. Most browsers are simply used their own prefixes, such as -moz, -webkit, or -o. Internet Explorer is a special case, I don’t have it and I really don’t care how the page would look like on it, the previous 2 links should give you insights about how to make same effects on it.


[1]Linear gradient is still in draft status, though Chromium supports linear gradient (tested in 5.0.375.3), however it doesn’t support this syntax linear-gradient() yet.
[2]I have been viewing San Diego Shooter‘s photo for a long time. If you like natural world, or animals (including human females :D), then you must add him as your contact on Flickr.