Photo Tagging with CSS

Here's a little demonstration of photo tagging ala facebook, flickr, etc. done with just CSS. When you hover over a person in the photo, a red outline appears around the person and a grey box pops up displaying information about him.

First a couple acknowledgments: This photo is in the Public Domain, from the U.S. Library of Congress, and was taken by Alexander Gardner on November 8, 1863. The photo hovering technique is a variation of the pioneering work of Stu Nicholls in this article.

All right, let's take a look at the HTML since that the simplest part.


<div id="pict">
  <div class="item" id="dnic">
    <a id="nico" href="#x">
      <span>
      John G. Nicolay
      <br />
      1832 - 1901
      <br />
      Lincoln's Private Secretary
      </span>
    </a>
  </div>
  <div class="item" id="dlin">
    <a id="linc" href="#x">
      <span>
      Abraham Lincoln
      <br />
      1809 - 1865
      <br />
      U.S. President
      </span>
    </a>
  </div>
  <div class="item" id="dhay">
    <a id="hay" href="#x">
      <span>
      John Hay
      <br />
      1838 - 1905
      <br />
      Lincoln's Assistant Secretary
      </span>
    </a>
  </div>
</div>

Here we have 3 divs of the class "item" enclosed in the div "pict". Each of the "item" divs has a unique id and encloses an <a> tag that has a span inside it that contains the information about each person in the photo. Each <a> tag also has a unique id which enables us to target them precisely with our CSS.

Our enclosing div (of id "pict") is sized and styled with the following CSS.


  div#pict {   /* the div that holds the photo */
    display: block;
    width: 480px;
    height: 540px;
    background: url(nicolay-lincoln-hay480.jpg) no-repeat; 
    position: relative; 
    margin: 0; 
    border: 1px solid #000;
  }

Note that the photo is the background image of this div. Next let's take a look at the CSS for the red-outlined boxes.


/* size and position red boxes */
  div.item { width: 100px; height: 200px; position: absolute; }
  div#dnic { top: 125px; left: 10px; }
  div#dlin { top: 100px; left: 200px; }
  div#dhay { top: 10px; left: 330px; }
/* show red outline and slight grey fill on hover */
  div.item:hover { 
    display: block; 	
    border: 1px solid #f00;
    background: none;    /* the fallback if no rgba */
    background: rgba(200, 200, 200, 0.3);
  }
/* hide the span until hover */
  div.item span { display: none; } 
/* make the area of the a tag fill the div */
  div#pict a {
    display: block;
    width: 100%;
    height: 0;
    padding-top: 200px;
  }

As the comments indicate we size the "item" div by class and then position each one by id. (This part requires a little math and a way to figure the position of each one. I use the Firefox plug-in "MeasureIt".)

Next we set the hover properties for the divs. Note that we make the <a> tags fill the div by adding top padding equal to the height of the div. This way the hover event applies to both the div and the <a> tag within it. The padding pushes the actual text of the span below the bottom of the div, but it is not visible since we have set its display to none.

Next we position our spans when the div is hovered over.


  div#pict a:hover {
    background: none; 
  }
  div#pict a:hover span {
    position: absolute;  
    width: 240px;
    height: 60px;
    display: block; 
    font-family: georgia, serif; 
    font-size: 14px; 
    line-height: 1.4em;
    background: #ddd;  
    color:#000; 
    border: 1px solid #000; 
    padding: 5px;
  }

  div#pict a#nico:hover span {
    left: 0px; 
    top: -115px;
  }
  div#pict a#linc:hover span {
    left: -190px; 
    top: -90px;
  }
  div#pict a#hay:hover span {
    left: -320px; 
    top: 0px;
  }

  div#pict a:hover span:first-line {
    font-size: 18px;
    font-weight: bold;
  }

(The first little bit of CSS here which sets the background of the hover to none is only necessary to override the style for my Drupal theme which has a background color for <a> hovers.)

With "div#pict a:hover span" we set the font, size, and color properties for the span, and then we target each one by id to set its position relative to the position of the "item" div that encloses it (again requiring a little math and measuring).

Finally, we use the pseudo-class "first-line" just to make the first line of the text a little bigger and bolder.

This process doesn't scale well due to its math-intensiveness, but it is a good demonstration of the power of CSS.