Creating a CSS Thumbnail Grid With a Dynamic Flyout Menu

When presenting data in a grid you often lose the ability to include extra information. Aside from appending dynamic menus or hover effects there is very little room to include metadata on each item. I want to use this tutorial as a thought process into the user experience of image thumbnail grids.

We will create a small flyout menu holding additional information on the image. This includes the image name, original source URL, and author URL. The beauty of this example is that we will be creating the dynamic effect using only CSS3 properties. Mostly all standards-compliant browsers will support dynamic CSS3 animations and these look fantastic! But even without animations, the flyout content will still work properly and degrade naturally for an all-around enjoyable user experience.

Live DemoDownload Source Code

Crafting the Document

To get started we need to create a single HTML5 document which behaves as our index page. I have included a copy of the Google Webfonts CSS which adds the Kavoon font family to our selection. This will be applied onto the header text for a showy design. Also if the user is on Internet Explorer 8 or earlier then we include the HTML5shiv document for good measure.

<!doctype html>
<html lang="en-US">
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <title>Thumbnail Gallery with CSS Flyouts</title>
  <meta name="author" content="Jake Rocheleau">
  <link rel="shortcut icon" href="https://designshack.net/favicon.ico">
  <link rel="icon" href="https://designshack.net/favicon.ico">
  <link rel="stylesheet" type="text/css" href="styles.css">
  <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Kavoon">
</head>

This will ensure any newer HTML5 elements like

or

will render properly. Now we can quickly move into the body section which holds our thumbnail gallery code. I have split up the different images using an unordered list where each list item represents a different thumbnail. Unordered lists work very well in typical website layouts because they are easy to customize and contain specific sects of data.

Sorting Thumbnails

Inside each item container we need to include two separate blocks of content. First is the image which may or may not link to another page in your website. Typically galleries will lead to internal pages with a larger photo of the thumbnail shot, or sometimes to the original source. In this case we aren’t linking anywhere so as not to drive the user off our page.

The other internal element is a div using the .meta class name. This content is positioned absolutely to remove it from the document flow. The positioning is important because we need the flyout menu to appear on top of the other elements, and not to push them away.

<div id="container">
  <ul id="thumbs">
    <li class="clearfix">
      <img src="images/01-birdie-shot-illustration.png">
      <div class="meta">
        <h4>Birdie</h4>
		
        <span><a href="http://dribbble.com/helder-oliveira" target="_blank">Author URL &rarr;</a></span>
	<span><a href="http://dribbble.com/shots/912406-Birdie" target="_blank">Source URL &rarr;</a></span>
      </div>
    </li>

Each list item also has the .clearfix class which deals with internal floated elements. Since we need to keep all the images together next to each other, floating is the quickest solution. But this leaves us with a floated image and an absolutely positioned div – both of which are now out of the document flow. To learn a bit more you may read up on my favorite clearfix resource which offers sample code.

The HTML in my demo is also very generic in comparison to fully published websites. You may need to include more data within the flyout box or add extra attributes onto the image element. None of these should directly affect the CSS3 animation so this technique is quick to scale as needed. Let’s jump into the stylesheet and figure out how it all works.

CSS Resets & Structure

At the top of my CSS document I have copied the resets from Eric Meyer’s webpage and customized a few additional properties. This is extremely important to get all your margins, padding, and font sizes working properly in all modern browsers. One other interesting technique is the height: 101% on the html element. This will ensure we always have a sidebar so the website doesn’t jump back-and-forth when dynamic content appears.

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 { background: #d6d6d6; font-family: Verdana, Arial, sans-serif; font-size: 62.5%; line-height: 1; 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%; }

h2 { display: block; font-family: 'Kavoon', Tahoma, sans-serif; font-size: 4.2em; line-height: 1.2em; text-shadow: 1px 2px 1px #fff; margin-bottom: 8px; }

p { font-size: 1.3em; color: #666; margin-bottom: 16px; }

The CSS gets more interesting as we move into the thumbnails gallery. When you see the ID #thumbs this relates to the initial top-level unordered list. I prefer starting with root selectors using a unique ID and managing all other internal styles down the cascading DOM tree. Let’s take a peek at how this looks:

#thumbs { list-style: none; text-align: center; }
#thumbs li { position: relative; margin-right: 7px; margin-bottom: 14px; }

#thumbs li img { 
  float: left;
  cursor: pointer;
  opacity: 0.6;
  
  -webkit-transition: all 0.4s ease;
  -moz-transition: all 0.4s ease;
  -ms-transition: all 0.4s ease;
  -o-transition: all 0.4s ease;
  transition: all 0.4s ease;
}
#thumbs li:hover img { 
  opacity: 1.0
}

For a cleaner layout I have centered the entire unordered list so that thumbnails line up from the center and move outwards. It looks better when you have uneven rows as we do in the demo. Also you can see each image is floated left inside the list item container, and they are initially displayed with a 60% opacity. I like this fading effect because it helps each currently hovered thumbnail stand out above the other items.

However these transitions only relate to the image opacity and not to our flyout menu. So in theory you may edit this to include any other types of animation, or even remove it altogether. But the key aspect to this interface is having both animations display in unison so it is easier determining which thumbnail is active.

Menu Flyout Effect

This final part of the CSS code is a bit long but very easy to digest. We need to use the same number of CSS3 transition properties with the individual vendor prefixes. Also since we are targeting the internal .meta boxes it is easier applying all the same styles at once.

#thumbs li > .meta { 
  float: left;
  overflow: hidden;
  position: absolute;
  z-index: 9999;
  left: 125px;
  height: 85px;
  width: 0;
  
  font-family: Arial, Tahoma, sans-serif;
  font-size: 1.2em;
  background: #fff;
  
  -webkit-box-shadow: 1px 0px 4px #8f8e88;
  -moz-box-shadow: 1px 0px 4px #8f8e88;
  -o-box-shadow: 1px 0px 4px #8f8e88;
  box-shadow: 1px 0px 4px #8f8e88;

  
  -webkit-border-top-right-radius: 4px;
  -webkit-border-bottom-right-radius: 4px;
  -moz-border-radius-topright: 4px;
  -moz-border-radius-bottomright: 4px;
  border-top-right-radius: 4px;
  border-bottom-right-radius: 4px;
  
  
  -webkit-transition: width 0.3s linear;
  -moz-transition: width 0.3s linear;
  -ms-transition: width 0.3s linear;
  -o-transition: width 0.3s linear;
  transition: width 0.3s linear;
}

#thumbs li:hover > .meta {
  width: 115px;
  padding: 3px 5px;
}

I have broken down the newer CSS3 properties into sections where it is easier to read. All we need are a few rounded corners, box shadows, and some transitions for adding two new display properties onto the box. All the content is still visible on the page when it first loads. We just don’t see anything because the divs are setup at 0px width.

The additional padding is added onto the animation because it messes with the box display. If we include padding onto the root element then it will appear as 5-10px width but completely empty. So instead we slowly expand the width and internal padding just a big quicker than the image thumbnail fades into 100% opacity. These options are fairly easy to mess with and suit to your own liking.

sliding animated menu css3 preview demo

Final Thoughts

Building a user interface which fits into the majority of user’s preferences can be difficult. You want to offer better solutions without compromising simplicity. I love the idea of hidden web elements, and this tutorial is a fantastic demonstration of how these can be applied merely using CSS properties. I do hope this code may be useful to developers interested in building a similar layout.

Along with checking out my live demo above you should also feel free to grab a copy of my source code. Such a project is not very difficult to understand, but sometimes it can be easier working off the pre-existing codes. There are also many ways to improve the quality of animations by including some additional jQuery effects. If you have any questions or ideas on the tutorial please do share with us in the post discussion area.

Live DemoDownload Source Code