How to use CSS to Create a 'Two Step' Photographic Gallery

By Stu Nicholls.

Introduction

Following from the success of my previous article 'How to Create a Photographic Gallery Using CSS' I've now taken things a little further and produced a totally new method which doesn't require thumbnail images and has a unique two step method of display. The 'mouse hover' stage creates a half size image and the 'mouse click' creates a full size image.

As with the previous article you'll learn how to produce a professional quality photograph gallery using nothing more than an unordered list of photographs and a Cascading Style Sheet (CSS). You'll go through the styling one step at a time and end up converting:

Each step is thoroughly explained and has an example page showing the effect of the additional styling. This is so you know what to expect.

This photograph gallery will also work in all the latest browsers and I have included hacks enabling Internet Explorer 5.5 to interpret the style correctly. The styling is not too long or difficult, but the layout needs a lot of attention to detail and preplanning.

Method

Step 1

The images

For this gallery I have used 24 images each 320px x 240px all on the theme of graffiti. I have chosen this size for several reasons:

  1. The file size for each image needs to be fairly small as all the images are required to be loaded before the gallery will work.
  2. As the 'thumbnails' surround the display area, on a 7 x 7 grid it is an easy calculation to find the thumbnail size is 64px x 48px.
  3. There will be five 'thumbnails' across the 320px horizontal display area (320px/5=64px)
  4. There will be five 'thumbnails' down the 240px vertical display area (240px/5=48px)
  5. There will be one 'thumbnail' in each corner making a total of 24 'thumbnails' (5+5+5+5+4=24)

It's always possible to adapt this layout to fit any quantity of images at any size but always consider the time required to download the images.

The basic (x)html list is given below.


<ul id="gallery">
  <li><img src="../images/g1.jpg" alt="#1" title="#1" /></li>
  <li><img src="../images/g2.jpg" alt="#2" title="#2" /></li>
  <li><img src="../images/g3.jpg" alt="#3" title="#3" /></li>
  <li><img src="../images/g4.jpg" alt="#4" title="#4" /></li>
  <li><img src="../images/g5.jpg" alt="#5" title="#5" /></li>
  <li><img src="../images/g6.jpg" alt="#6" title="#6" /></li>
  <li><img src="../images/g7.jpg" alt="#7" title="#7" /></li>
  <li><img src="../images/g8.jpg" alt="#8" title="#8" /></li>
  <li><img src="../images/g9.jpg" alt="#9" title="#9" /></li>
  <li><img src="../images/g10.jpg" alt="#10" title="#10" /></li>
  <li><img src="../images/g11.jpg" alt="#11" title="#11" /></li>
  <li><img src="../images/g12.jpg" alt="#12" title="#12" /></li>
  <li><img src="../images/g13.jpg" alt="#13" title="#13" /></li>
  <li><img src="../images/g14.jpg" alt="#14" title="#14" /></li>
  <li><img src="../images/g15.jpg" alt="#15" title="#15" /></li>
  <li><img src="../images/g16.jpg" alt="#16" title="#16" /></li>
  <li><img src="../images/g17.jpg" alt="#17" title="#17" /></li>
  <li><img src="../images/g18.jpg" alt="#18" title="#18" /></li>
  <li><img src="../images/g19.jpg" alt="#19" title="#19" /></li>
  <li><img src="../images/g20.jpg" alt="#20" title="#20" /></li>
  <li><img src="../images/g21.jpg" alt="#21" title="#21" /></li>
  <li><img src="../images/g22.jpg" alt="#22" title="#22" /></li>
  <li><img src="../images/g23.jpg" alt="#23" title="#23" /></li>
  <li><img src="../images/g24.jpg" alt="#24" title="#24" /></li>
</ul>

Step 2

The !DOCTYPE

Firstly and most importantly, make sure that you have the correct (X)HTML !DOCTYPE. Without this most browsers will be thrown into 'quirks' mode which leads to all sorts of incompatibility problems. W3C QA - List of valid DTDs has a list of valid DOCTYPES that can be used. Select from XHTML1.0 or XHTML1.1 as these are more suitable for this styling. I use XHTML1.1 for all my current web pages.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
        

Step 3

Adding links and style information

To use the :hover pseudo class style I need to change the basic unordered list into an unordered list of links. This is because Internet Explorer will only allow :hover to be used on links. I also need to add extra markup to target specific images.

The (x)html will now look like this.


<ul id="gallery">
  <li><a href="#nogo"><img src="../images/g1.jpg" alt="#1" title="#1" /></a></li>
  <li><a href="#nogo"><img src="../images/g2.jpg" alt="#2" title="#2" /></a></li>
  <li><a href="#nogo"><img src="../images/g3.jpg" alt="#3" title="#3" /></a></li>
  <li><a href="#nogo"><img src="../images/g4.jpg" alt="#4" title="#4" /></a></li>
  <li><a href="#nogo"><img src="../images/g5.jpg" alt="#5" title="#5" /></a></li>
  <li><a href="#nogo"><img src="../images/g6.jpg" alt="#6" title="#6" /></a></li>
  <li class="rgt"><a href="#nogo"><img src="../images/g7.jpg" alt="#7" title="#7" /></a></li>
  <li class="lft"><a href="#nogo"><img src="../images/g8.jpg" alt="#8" title="#8" /></a></li>
  <li class="rgt"><a href="#nogo"><img src="../images/g9.jpg" alt="#9" title="#9" /></a></li>
  <li class="lft"><a href="#nogo"><img src="../images/g10.jpg" alt="#10" title="#10" /></a></li>
  <li class="rgt"><a href="#nogo"><img src="../images/g11.jpg" alt="#11" title="#11" /></a></li>
  <li class="lft"><a href="#nogo"><img src="../images/g12.jpg" alt="#12" title="#12" /></a></li>
  <li class="rgt"><a href="#nogo"><img src="../images/g13.jpg" alt="#13" title="#13" /></a></li>
  <li class="lft"><a href="#nogo"><img src="../images/g14.jpg" alt="#14" title="#14" /></a></li>
  <li class="rgt"><a href="#nogo"><img src="../images/g15.jpg" alt="#15" title="#15" /></a></li>
  <li class="lft"><a href="#nogo"><img src="../images/g16.jpg" alt="#16" title="#16" /></a></li>
  <li class="rgt"><a href="#nogo"><img src="../images/g17.jpg" alt="#17" title="#17" /></a></li>
  <li class="pad"></li>
  <li class="lft"><a href="#nogo"><img src="../images/g18.jpg" alt="#18" title="#18" /></a></li>
  <li><a href="#nogo"><img src="../images/g19.jpg" alt="#19" title="#19" /></a></li>
  <li><a href="#nogo"><img src="../images/g20.jpg" alt="#20" title="#20" /></a></li>
  <li><a href="#nogo"><img src="../images/g21.jpg" alt="#21" title="#21" /></a></li>
  <li><a href="#nogo"><img src="../images/g22.jpg" alt="#22" title="#22" /></a></li>
  <li><a href="#nogo"><img src="../images/g23.jpg" alt="#23" title="#23" /></a></li>
  <li class="rgt"><a href="#nogo"><img src="../images/g24.jpg" alt="#24" title="#24" /></a></li>
</ul>

Make sure that each list item is on a single line as splitting them over several lines can cause unwanted spaces in Internet Explorer.

Style Ready List

Every list item is now enclosed in a link. Some have no class others have either 'lft' or 'rgt' which is short for 'left' and 'right.' I've also added an empty list item with a class="pad" to correct a bug in Internet Explorer, but more about that later.

I've used href="#nogo" instead of the more usual href="#" so that anyone clicking the link will not jump to the top of the page (just make sure you do not have an anchor #nogo on your page).

The (x)html unordered list is now complete and I won't need to make any more changes to it.

The Styling

Step 4

Removing the bullets

I'll style the unordered list to removing the bullets and the indentation.

Browsers have different ways of doing this, Internet Explorer and Opera use margin values for the indentation whereas Mozilla/Netscape/Firefox all use padding values, so to cater for this I need to style the list as follows.


/* Removing the list bullets and indentation */
ul#gallery {
  padding:0; 
  margin:0; 
  width:448px; 
  height:336px; 
  position:relative;
  list-style-type:none;
  background:#888;
  }
  • padding:0; - removes all padding.
  • margin:0; - removes all margins.
  • width:448px; - makes the total width 7 x 64px.
  • height:336px; - makes the total height 7 x 48px.
  • position:relative; - gives the ul a position relative so that we can position images absolutely.
  • list-style-type:none; - removes the bullets.
  • background:#888; - makes the background dark grey (for now).

Example Step 4

The bullet point are gone and the grey background of the <ul> is visible. In Internet Explorer the grey background will stretched in height to enclose all the images, whereas in other browsers the images will overflow the grey background.

Step 5

Resizing the images

The initial size of the images was calculated to be 64px x 48px to act as 'thumbnails' around the outside of the display area.

However, I've decided to have a 1px border around each image to act as a separator. To do this I need to reduce the actual image size to 62px x 46px and the styling will be as follows:


/* Resize the images to 64px x 48px */
#gallery a img {
  position:relative;
  width:62px; 
  height:46px; 
  border:1px solid #888; 
  z-index:100;
  }

Example Step 5

The images are now reduced to 62px x 46px with the 1px border being the same color as the background.

Step 6

Positioning the thumbnails

We now move on to positioning the thumbnail images around the edge of the display area.

To do this we will style the <li> tags.

Step 6a - moves the top line of thumbnails into place

/* Default style for list items */
#gallery li {
  width:64px; 
  height:48px; 
  float:left; 
  z-index:100;
  }

The images are now grouped in 4 rows with a blank space between image 17 and 18.

Example Step 6a

Step 6b - moves the 'lft' styled list items to the left hand edge

/* Styling the left side of the display area */
#gallery li.lft {
  float:left; 
  clear:left;
  }

It's a bit of a jumble, but the left side of the display area is now filled.

Internet Explorer adds a small space vertically between each image but that will be taken care of later.

Example Step 6b

Step 6c - moves the 'rgt' styled list items to the right hand edge

/* Styling the right side of the display area */
#gallery li.rgt {
  float:right; 
  clear:right;
  }

If you use Internet Explorer you'll see that the top, left and right images are in the correct place but the bottom row is not at the bottom. All other browsers have the images correctly positioned

Example Step 6c

This is where that extra list item (class="pad") is brought into play. We can style this to force the bottom row of images into place.

Step 6d - moves the bottom row of thumbnails into place in Internet Explorer

/* Force the bottom row of images into place (IE only) */
#gallery li.pad {
  height:0; 
  display:block; 
  margin-top:-2px; 
  width:448px; 
  font-size:0;
  }

The bottom row of images are now in place but we still have gaps between the horizontal row of images in Internet Explorer.

Example Step 6d

Step 6e - get rid of the gaps under the images in Internet Explorer

/* Getting rid of the image gaps */
#gallery a {
  position:relative; 
  width:64px; 
  height:48px; 
  display:block; 
  float:left; 
  z-index:100; 
  cursor:default;
  }

Example Step 6e

Step 7

Adding the :hover state

With all the thumbnails now in their correct position around the display area we can move on to styling the :hover stage of the thumbnails. Since the images aren't actually thumbnails but reduced full-size images we can enlarge them to 160px x 120px and reposition them in the middle of the display area, leaving a blank space where they were originally positioned. However, if we did this then we'd lose our mouseover link and the selected image would flicker backwards and forwards between its original position and the new position.

In order to preserve our mouseover link we must expand the size of this link to be the full width and height of the <ul*gt;

We can do this by adding padding around the link to give a total height of 336px and a total width of 448px

What's more, the selected link must now drop behind all the other links in order that it does not obscure them and stop them being selected. So we must style the selected link with a z-index that's less than 100.

This section should be fully understood before continuing to the next stage.


/* Resizing the link on hover */
#gallery a:hover {
  width:160px; 
  height:120px; 
  padding:108px 144px; 
  position:absolute; 
  left:0; 
  top:0; 
  z-index:20;
  }
  • width:160px; - makes the link width bigger to hold the half linear size image.
  • height:120px; - makes the link height bigger to hold the half linear size image.
  • padding:108px 144px; - adds padding to make the overall size of the link 448px x 336px.
  • position:absolute; - allows us to absolutely position our link.
  • left:0; - moves the link to the left edge of the <ul>.
  • top:0; - moves the link to the top edge of the <ul>.
  • z-index:20; - moves the link so that it is below all the other links (on a lower layer).

Example Step 7a

This example shows that you can hover over each thumbnail and make it jump to the display area and still remain hovering over the link. It also shows that you can move onto any other image and that too will jump to the display area.

We can now style the thumbnail image :hover to enlarge to 160px x 120px. I have chosen to lose the border in this resize.


/* Resizing the thumbnail on hover */
#gallery a:hover img {
  background:#eee; 
  position:relative; 
  width:160px; 
  height:120px; 
  border:0; 
  z-index:20;
  }

Example Step 7b

The hover image is now enlarged to half linear size and is positioned centrally in the display area.

Step 8

Adding the :active and :focus states

Internet Explorer uses the :active pseudo class but all other browsers use to :focus pseudo class to style the mouse click.

As with the :hover style we enlarge the image area, this time to 320px x 240px and reduce the padding to 48px at the top and bottom and 64px at each side, maintaining a total size of 448px x 336px.

The clicked state of each link must also be moved further down the z-index so that it will be below the :hover stage. This will allow all links to be active and also allows the next :hover to appear on top of the 'clicked' image.


/* Resizing the link when 'clicked' */
#gallery a:active, #gallery a:focus {
  background:transparent; 
  width:320px; 
  height:240px; 
  padding:48px 64px; 
  position:absolute; 
  left:0; 
  top:0; 
  z-index:10;
  }

Example Step 8a

We can now style the 'clicked' image to be full size 320px x 240px.


/* Resizing the image when 'clicked' */
#gallery a:active img, #gallery a:focus img {
  background:#eee; 
  position:relative; 
  width:320px; 
  height:240px; 
  border:0; 
  z-index:10;
  }

Example Step 8b

Users of Internet Explorer may now notice a bug in this arrangement whereby the full sized clicked image does not display until the mouse is moved onto another image.

This is a very curious bug and I'm not sure why it happens intermittently. Fortunately, there's an easy cure (hack) that can be applied without any problem to other browsers.


/* The 'click' hack for Internet Explorer */
a:visited {
  color:#000;
  }

Adding this global style to all links cures this problem. If anyone knows why it happens, please contact me..

Example Step 8c

Step 9

Adding a background image to the list

The photograph gallery is now taking shape, but we have a large blank display area and also blank spaces left by the images as the get enlarged.

It's possible to fill these gaps with an overall background image for the <ul>.

For my example I've created an image that's in keeping with the graffiti theme and also gives an instruction to click the vacant space left by the hover stage.

background image

Of course, you can style this as desired.

Modify the following line in the existing ul#gallery style to add the background image.


/* Adding the background image */
ul#gallery {
  padding:0; 
  margin:0; 
  width:448px; 
  height:336px; 
  position:relative; 
  background:#888 url(../image/g26.jpg);
  }

Example Step 9

We now have the central default image in place and when you hover over any image it gets replaced by an instruction to 'click' which will produce the full sized image.

Step 10

Opera doesn't like :focus or :active

It's true. Opera doesn't work with :active and doesn't hold the :focus state when the mouse button is clicked and released.

We can let Opera do it's thing or we can apply a hack that tells Opera to just use the :hover as a full size image and to ignore the two steps.

Yes, there is a hack that targets Opera only, it's 'valid' css but the w3c validator does not recognize it as it's only a recommendation.


/* hack for Opera 7+ */
@media all and (min-width:0px){
#gallery a:hover {
  background:#888; 
  width:320px; 
  height:240px; 
  padding:48px 64px; 
  position:absolute; 
  left:0; 
  top:0; 
  z-index:10;
  }
#gallery a:hover img {
  background:#aaa; 
  position:relative; 
  width:320px; 
  height:240px; 
  border:0; 
  z-index:10;
  }
}

ONLY Opera 7+ understands this conditional styling which just enlarges the hover link and image to 320px x 240px (the same size as the active / focus link and image).

Example Step 10

If you're using Opera 7+ then you'll now see a full size image on hover, with the instruction to 'click' covered up by a grey background. The central default image is still in place and if you should click an image then you will not notice the problem.

Conclusion

Feel free to use this styling 'as is' with your own images or adapt it to use images of a different size or even a different arrangement. The only limitation is your imagination.

One last thing: a big thank-you to the photographers who supply their work 'free of charge' to the stock.xchng

About the Author

Stu's website documents his attempts at understanding and exploring the possibilities of CSS. From standard navigation links to his more bizarre experimental techniques. All of his examples are produced with JUST CSS--no javascript, or any other language, has been used in any of the examples. [Editor's note: Prepare to be amazed!] http://www.stunicholls.myby.co.uk/