I don’t claim to be a wiz at WordPress. If I was, I would have already known that v2.9 introduced thumbnail image support. If I had bothered to stop by the WP plugin site, I would have discovered that a search for “thumbnail” brings up 31 pages of plugins.

But I’m not a WP wiz and I didn’t know those things, so I wrote my own. :)

What Made Me Do It?

Little things about my site have been bugging me but not enough to work on them. Then I stopped by Digging Into WordPress. They just unveiled their new design and it is spectacular. When I returned to my own site, I was a little jealous and realized it was time to make some changes.

First off, my excerpts were too long. They should be very short teasers with a link to the full article. Shortening them is easy enough. You just insert a tag in a different place and WP does the rest.

Second, my articles ran together. There wasn’t a clear separation between articles. Most blogs put each article into a box or separate them with HR tags. Not my favorite look but I gave it a try and I think I like it. It’s appropriate too since each excerpt now looks something like the 4th edition power descriptions. For a dnd blog, I can’t think of anything better.

Third, I generally code for the lowest common denominator but I wanted to play with some of the cool new css. You’ll notice some unnecessary shadowing around the site now. I think it looks good and it degrades well for browsers that can’t use it.

Lastly, I wanted more images. A great many sites have started using thumbnails on each of their articles. That seems like a lot of work to me. But then I ran through my site and realized that the majority of the posts already had images being used but not being used very effectively. I decided to redesign a few things to convert existing images to thumbnails and start using thumbnails somewhat regularly.

How To Setup Thumbnails

There are a few design considerations for using thumbnail images:

  • I want to use roughly 125×125 images. (Standard ad size)
  • I want the image to be displayed in the upper right corner.
  • I want the title, meta info, and content to wrap tightly around the image.
  • I want to have flexibility in image size and not be tied to a fixed height and width.
  • I don’t want any limitation on image format.
  • I want to keep the images out of the database.
  • I don’t want to have to code each image individually as I have been doing.
  • I don’t want to fight the damn editor to format an image the way I want.
  • Some posts will have thumbnail images. Some will not. I want to be able to set thumbnails on a case by case basis.
  • Some posts will need to link to images or sites. Some of those require special target settings.

It didn’t seem like so much till I wrote it out but that is a pretty tall order. Especially the part of wanting to use varying size images. I’ll start with an overview and then list out the code I used.

Placing the image

Placing the image in the upper right corner is the easiest part. Just define the container as position: relative and then set the image to position: absolute with top: 10px; and right: 10px;. But since we aren’t floating the image, we’ve taken the image out of the flow and text won’t wrap around it.

That is fixed in three steps: pad the title, pad the meta info, and set a dummy float in the content area. This is a nice little trick but it isn’t mine. I wish I could credit it to someone but I’ve seen it all over the web for some time. It’s probably pretty standard but I still think it’s a cool technique. (Edit: I may as well credit this technique to Chris Coyier at CSS-Tricks. That at least is one of the places where I’ve seen it and if I didn’t learn it there, I’ve learned much of my CSS skills from him so I love giving him a shout-out.)

Set the title area and meta info area to padding: 5px 150px 5px 5px to give room for the image located in the right corner. Create a dummy div and style it as float: right; height: 50px; width: 125px; margin: 10px;. The image won’t be entirely in the content area. That’s why we set the height to only 50px. Part of the image is in the title area and the meta info area.

That takes care of placing the image and wrapping the text around it. It assumes a fixed size image but we’ll work on that later.

Setting Up the Links

WordPress has the ability to set up custom fields. I’ve heard they can do wonderful things but I’ve never really looked at them before. It turns out that they are incredibly easy to use. Edit a post or a page and scroll down. Just below the content there is an area for dealing with custom fields. Type in a name and a value, click add field and you’re done. You do, however, need to do that on every post that you want an image on. Fortunately, you can do these piecemeal if you have too many to do easily all at once.

I set up three fields: image, href, and target. Image is the name of the image (no path). Href is the full url (including “http://”). Target is “_blank” to open the url in a new window or tab. One of my ad links requires other info in the target field. That’s why I needed to add it. Image is all that is really necessary for the thumbnails to work. the other two fields are used if they are set or ignored if they are not.

The Code

Now we get to the actual code. This is all done in PHP. It can probably be done easily and perhaps better, in javascript. But I want 100% usability.

Our code needs to retrieve the data from the three custom fields, check to see if the file exists, determine the height and width of the image, and create the IMG tag, wrapped in an A HREF if indicated and with a target specified if one was entered.

Allowing For Flexible Image Sizes

This is the important step. To allow for flexible image sizes, our code has to do a couple of things. It has to create the padding-right statements in both the title area and the meta info area. And it needs to create the dummy float div based on the size of the image. It will accomplish all that through embedding inline styles. I don’t see an easy alternative to that but inline styles aren’t the worst thing in the world.

No Walk-through

All of the above is pretty much a general description of what’s going to happen. Here’s the actual code I used. You will most likely have to make some modifications as your loop is probably different than mine. I didn’t write a walkthrough as the differences between everyone’s various sites would defeat any walk-through. Hopefully, the code will make enough sense that you won’t have any trouble using it.

Please make a backup before you start!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
      if (have_posts()) {
        while (have_posts()) {
          the_post();
 
          // The image directory path is hardcoded here (See the $file variable). You will need to change it!
 
          // $post->ID is the id of the post, 'image' is the name of the custom field, true says to return a single field opposed to an array.
          $file = '/images/thumbnails/' . get_post_meta($post->ID, 'image', true);
          $path = $_SERVER{'DOCUMENT_ROOT'};
          if (file_exists($path . $file)) {
            list($width, $height, $t, $a) = getimagesize($path . $file);
            $image_href = get_post_meta($post->ID, 'href', true);
            $image_target = get_post_meta($post->ID, 'target', true);
          }
?>
          <div class="post" id="post-<?php the_ID(); ?>">
            <div class="article">
              // If you don't use intval() you will generate php errors here. These two lines insert the 'padding-right' styles.
              <h2<?php if ($width) echo ' style="padding-right: ' . intval($width + 20) . 'px;"';?>><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
              <div class="post-meta"<?php if ($width) echo ' style="padding-right: ' . intval($width + 20) . 'px;"';?>><em>Written by</em> <?php the_author() ?> <em>on</em> <?php the_time('F jS, Y') ?></div>
              <div class="post-content">
<?php
                if (isset($width) & isset($height)) {
                  // This creates the dummy float div silghtly bigger than the image.
                  echo '<div class="post-thumbnail-placeholder" style="width: ' . intval($width + 20) . 'px; height: ' . intval($height - 70) . 'px;"></div><div class="post-thumbnail">';
                  if ($image_href) {
                    echo '<a href="' . $image_href . '"';
                    if ($image_target) echo ' target="' . $image_target . '"';
                    echo '>';
                  }
                  echo '<img src="' . $file . '" width="' . $width . '" height="' . $height . '" />';
                  if ($image_href) echo '</a>';
                  echo '</div>';
                  // If you do not unset these, the code will think the next record has an image even if it doesn't
                  unset($width);
                  unset($height);
                  unset($image_href);
                  unset($image_target);
                }
?>
                <?php the_content('<br /><button class="continue">Continue Reading &raquo;</button>'); ?>
              </div>
              <div class="clear"></div>
            </div> <!-- article -->
          </div> <!-- post -->
<?php
        }
      } else {
?>

And here’s the CSS that goes along with it.

1
2
3
4
5
6
7
8
9
10
11
.post { margin: 5px; }
.article { position: relative; border: 1px solid black; }
.post H2 { background: #690000; padding: 10px; color: white; font-family: Georgia, serif; }
.post H2 A { color: white; font-size: inherit; }
.post H2 A:hover { color: #c0c0c0; }
.post-meta { background: #181F25; color: #c0c0c0; font-size: 10px; padding: 5px; }
.post-meta A { font-size: 10px; color: #c0c0c0; }
.post-meta A:hover { color: black; }
.post-content { padding: 10px; background: #C8AE8B; }
.post-thumbnail-placeholder { float: right; }
.post-thumbnail { position: absolute; top: 10px; right: 10px; border: 1px solid black; background: white; }

Note that you will need to apply this modification to INDEX.PHP, PAGE.PHP, and SINGLE.PHP

The code will create a thumbnail for any page or post that has the image field filled out (assuming that the indicated file is found). Any page or post that does not have the image field defined, or if the file cannot be found, will not be affected.

I have tested this on this site and everything seems to be working just fine.