CSS3 Image Gallery with Dynamic Caption Text

This page may contain links from our sponsors. Here’s how we make money.

I have run into lots of tutorials on the web focused on creating stunning image galleries. These often include photo boxes or alternate JavaScript-enhanced functionality. Nominally in the modern era of web design there isn’t any problem with dynamic scripting. For more on image galleries, check out this post on free jQuery sliders.

For this tutorial, I want to show how we can build a standards-compliant HTML5/CSS3 image gallery with fading captions. We will be using CSS3 transitions to create the animated effects. Also, I have been working with a number of CSS3-specific properties on this tutorial alone. It leaves room for interpretation if you wanted to implement a JavaScript frontend animation using CSS3 as a fallback.

CSS3 Image Gallery with Dynamic Caption Text

Download Source Code

Creating the Page Document

To get us started I have created two new files inside my project directory. First is the typical index.html along with a styles.css for the CSS stylesheet. Now aside from the actual images this is all we will need to get the layout working properly.

I’ll first go over the small header portion and main document structure. I have included only one external JavaScript link to the Google html5shiv script. This will force newer HTML5 elements to render properly in older versions of Internet Explorer. Typically we would notice buggy rendering for elements such as header, footer, aside, and section.

<!doctype html>
<html lang="en-US">
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <title>CSS3 Dynamic Image Captions Demo</title>
  <meta name="author" content="Jake Rocheleau">
  <link rel="shortcut icon" href="https://www.vandelaydesign.com/favicon.ico">
  <link rel="icon" href="https://www.vandelaydesign.com/favicon.ico">
  <link rel="stylesheet" type="text/css" href="styles.css">
<!--[if lt IE 9]>
  <script type="text/javascript" src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

Inside the body element, I’m using some very simple HTML5 markup. I have the whole layout wrapped inside a div which is centered on the page. Then I am using figure as our HTML5 container element housing each image/caption pair.

  <img src="images/01-sketching.png" alt="tree sketching">
    Sketching (<a href="http://dribbble.com/shots/452443-sketching" target="_blank">Source</a>)

  <img src="images/02-strawberry-waffles.png" alt="Fresh Strawberries and Waffles">
  <figcaption class="light">
    Strawberries and Waffles (<a href="http://dribbble.com/shots/459466-waffles-with-fresh-strawberries" target="_blank">Source</a>)

This is the quickest and most properly-semantic way to go about coding images on the web. The whole image caption gallery could be wrapped in another container on your page, as this wouldn’t affect any of the internal content. All you need to do is make sure the whole image gallery is encased inside the .clearfix class. This will clear all our floating images and keep the document height linear.

Stylin’ with CSS

Before we jump right into the styles I want to point out a bit in my HTML code above. You will notice on the 2nd figure element I have added the class .light onto our figcaption. This is an updated style class for giving the caption a white background with dark text, as opposed to the dark background with lighter text. Test out both color schemes and see which one you like the best.

/* image figures */
figure {
  float: left;
  position: relative;
  padding: 3px;
  margin-right: 15px;
  margin-bottom: 1.35em;
  background: #fff;
  -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.35);
  -moz-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.35);
  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.35);

figcaption {
  width: 300px;
  position: absolute;
  background: rgba(0,0,0,0.6);
  font-size: 1.2em;
  color: #fff;
  padding: 10px 16px;
  opacity: 0;
  left: 3px;
  bottom: -10%;
  -webkit-transition: all 0.44s ease;
  -moz-transition: all 0.44s ease;
  -o-transition: all 0.44s ease;
  transition: all 0.44s ease;
figcaption a { color: #cce1ef; }
figcaption a:hover { color: #a9cbe1; }

figure:hover figcaption { opacity: 1; bottom: 5px; }

figcaption.light {
  background: rgba(255,255,255,0.6);
  font-size: 1.2em;
  color: #444;
  -webkit-transition: all 0.44s ease;
  -moz-transition: all 0.44s ease;
  -o-transition: all 0.44s ease;
  transition: all 0.44s ease;
figcaption.light a { color: #60a7d7; }
figcaption.light a:hover { color: #4d92c0; }

You will notice all of these CSS styles are put together in the same place. Each figcaption element is positioned absolutely while the figure elements have a position: relative; value. This will make it easier to place the caption box just outside the figure container and have it appear to fade in during hover.

The figcaption element has all of the transition effects added as well. The distinction is that we’re animating the figcaption element whenever a user hovers over the figure container. This works great towards building a systematic relatable user experience, since your visitors can still see the full image without pesky text getting in the way.

/* core body setup */
#topbar { position: fixed; top: 0; width: 100%; height: 45px; z-index: 999; background: #1b1b1b; border-bottom: 1px solid #575656; padding-left: 35px; }
#topbar a { line-height: 45px; font-size: 1.4em; font-weight: bold; color: #fff; }

#wrapper { width: 1000px; margin: 0 auto; padding-top: 70px; }
#gallery { padding: 0px 15px; display: block; }

This is the smaller portion of our custom CSS which is responsible for the page layout design. In the demo I have placed a static header bar which scrolls along the top of the page. Additionally the wrapper is limited to 1000px for the purposes of this demo. Although it would be completely reasonable to update this value, even into a responsive image gallery.

Resets and Clearfix

I also want to share these last snippets of CSS from my stylesheet example. You can get all of this from downloading my source code below, but it’s worth a quick explanation for other developers who are interested.

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
  outline: none;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
html { height: 101%; }
body { font-size: 62.5%; line-height: 1; font-family: Arial, Tahoma, sans-serif; background: #c9d7e0 url('images/bg.png'); padding-bottom: 65px; }

article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }
ol, ul { list-style: none; }

blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
strong { font-weight: bold; }

table { border-collapse: collapse; border-spacing: 0; }
img { border: 0; max-width: 100%; }

I am using a CSS reset kit based off Eric Meyer’s resets. In the big long selectors list at the top I have added box-sizing properties to keep the border-box ratio. This will force all widths to stay within the defined limit, causing padding/margins to calculate this into the final display. Plus I have some extra padding on the body to add space at the bottom of the page (otherwise captions look to be coming from nowhere).

.clearfix:after { content: "."; display: block; clear: both; visibility: hidden; line-height: 0; height: 0; }
.clearfix { display: inline-block; }

html[xmlns] .clearfix { display: block; }
* html .clearfix { height: 1%; }

And finally, this is the clearfix code I am using to contain the entire gallery. You won’t notice much in the demo here, but you will notice the effect if you have a sidebar or footer content displaying afterwards. The clearfix will force any floated container elements to pretend as a natural part of the DOM, even though the internal content is floated and removed from the document hierarchy.

And that should wrap it all up! What a simple effect to create one amazing outcome for your blog or personal website. Definitely check out my demo below if you haven’t already seen it, and feel free to download & manipulate my source code to your own liking.

Finished Product - CSS3 Image Gallery with Dynamic Caption Text

Download Source Code

Final Thoughts

The codebase here is very simple even to new web developers. Anybody fairly well-versed in CSS3 shouldn’t have a problem following my code. Additionally we are following typical HTML5 standards by using the figure/figcaption syntax.

I would recommend downloading a copy of my source code here and seeing how it can apply into your own layouts. Much of the code may be copied/pasted into your own documents and still work perfectly without any changes. Although feel free to make edits or updates to further blend into your layout. Additionally if you have ideas or questions on the tutorial feel free to share with us in the comments discussion area below.

Get the Free Resources Bundle