Brian Watson: tutorial


A resolution-independent photographic image gallery using floating auto-scaling thumbnails.

Design by Brian Watson, revised 25th March 2013

Here's a working example, an index page from my web site.

Several features must be considered when designing an image gallery:

Not many galleries meet these requirements, but it can be done, using just CSS and a little Javascript. This design has been tested with Safari 4.0.4 and Firefox 3.5.3 (Mac), and Internet Explorer 8 (Win).

Start by organising the thumbnail pictures, the full-sized versions and the pages needed to display them.

I use a folder "mediafiles" for the full-size images, a folder "thumbN" for the thumbnails, and "pages" for the html pages which will display the full-size images. For each image, the thumbnail, the full-size image, and the page to display it, all have the same file name (for example fileone.html for the page, and fileone.jpg for both the thumbnail and the full-size picture file),

The file structure looks like this:

gallery.html (the index file displaying the thumbnails)
   mediafiles/   (the full-resolution pictures)
   pages/    (the pages displaying the full-resolution pictures)
   thumbN/   (the thumbnail images)

If the html body is made to fill 100% of the height of the window, and the height of the thumbnail images are scaled to be a percentage of the window height, a page of floating, wrapping, auto-scaling thumbnails can be produced:

<style type="text/css">
  html, body {height:100%}
  img {height:8%; width:auto;}

I put the styles in the head of my html documents, because some galleries may require a different thumbnail height, depending on how many there are to display on the page. In this case we are using 8%, which is enough to give 9 rows of thumbnails (on any size of screen), and still leave some room at the top of the page for menus and titles. Use a smaller or larger value depending on how many thumbnails are on the page. Width is left at "auto".

Where there are more than about 50 thumbnails and the containing window is made very tall and narrow, the bottom rows of thumbnails may scroll off the screen: if this is a problem, giving the body a min-width prevents this.

   min-width:700px; /*(optional body style)*/

We place the thumbnails in a div (class name "hundiv") with a height of 100%. This is 100% of the div's container, the body, which is already 100% of the window height (BOTH of these "100%" MUST be specified):

   .hundiv {height:100%;}

Images are placed using a short Javascript routine in the <body> of the page, with a single parameter, a partial filename. There is one line for each thumbnail. The thumbnails are in the folder named "thumbN" at the same level as this file.

<script language="JavaScript">
  <div align="center" class="hundiv">
  <script type="text/javascript">
   thuN("filethree");.... etc

The partial filename is used in three places for each thumbnail:

1. "ThumbN/fileone.jpg": When the page is loaded, each line of the Javascript (see below) uses the partial filename to make up the path to the thumbnail image eg "ThumbN/fileone.jpg".

2. "pages/fileone.html" This is the path to the page with the full size image, the page which appears when the thumbnail is clicked: these pages are in the folder "pages" at the same level as this file.

3. "mediafiles/fileone.jpg" This is the path to the full size image in the page which is displayed when the thumbnail is clicked. The full size files are in the folder "mediafiles" at the same level as this file.

The Javascript finds each thumbnail's path eg "thumbN/fileone.jpg", and uses document.write to put the image on the page. An onclick command then defines what should happen when the thumbnail is clicked. In this case it shows the page "pages/fileone.html" containing the full size version of the image.

Thumbnail images are 150 pixels high, but can be any size: 150px is a good compromise between maintaining recognizability and file size. They don't even need to be the same size, because the browser will scale each one to be the same percentage of the height of the window.

Allowing a browser to scale images is not ideal, but for small images such as thumbnails it will be fast, and anything less than perfection in the quality will not be noticeable. Picture files as small as this can also be given a low jpg quality, and can only be 8 to 16k in size, and so will load quickly.

<script language="JavaScript">
 function thuN(name) {
   var thname = "thumbN/" + name + ".jpg";
   document.write("<img src='" + thname + "' onclick=showpage('" + name + "')>") }

 function showpage(name) {
   location.href='pages/' + name + ".html"; }

The display property of the thumbnail images can safely be omitted because it is to be 'inline' and this is the default value.

With a slow connection, thumbnail images may appear as (bordered) placeholders while they load. This can be avoided by loading all images as "hidden" by changing this:

img {height:8%; width:auto;}

to this:

img {height:8%; width:auto; visibility:hidden;}

...and by setting all images' visibility to 'visible' by calling this function:

function showImages() {
   for(var i=0; i<document.images.length; i++) {
      document.images[i].style.visibility = 'visible';

after all the images have loaded, using:

<body onLoad="showImages()">

By setting left and right borders for the page using CSS, images will wrap when they reach the right margin. Setting padding to zero ensures that there is no space, either between images, or between rows of images. The images will scale automatically so that all of them will be visible all the time even if the screen resolution is very low.

body {
   margin-left: 20px;
   margin-right: 40px;
   padding: 0;

Giving a shaded border to the images adds a 3D effect, and a hover state shows that the thumbnails are actually links.

img {
   border-right: 3px solid #aaa;
   border-bottom: 3px solid #aaa;
   border-top: 4px solid #333;
   border-left: 4px solid #333;
   padding: 0;

   border-right: 3px solid #55f;
   border-bottom: 3px solid #55f;
   border-top: 4px solid #00a;
   border-left: 4px solid #00a;

You may use my technique provided that you mention my name as the original author and include a reference to my web site: "".

Brian Watson