Blog

Advanced web templating with PHP and regular expressions

This post describes a method to gain more control over the styling of images for web templates/blog themes, using a bit of Regular Expression magic. This is the technique used for my recent theme, Elegant Grunge.

You’ve just designed the most beautiful template ever – pleasing composition, clean lines, smooth colours and gradients and an awesome typeface. You apply it as the theme for your blog, or release it to the community, and there is much rejoicing.Example of the 'SH Trocadero' WordPress theme with image

Then you or someone else inconsiderately puts a photograph into a post – disaster! That nasty square of graphic just destroyed your composition, and the page is unbalanced and suddenly looks terrible.

Images are particularly tricky to make work with a theme, mostly because they’re so unpredictable. With text, it’s easy to control the way it looks. With images, they can be any colour or shape, many of which will break the composition of a theme, especially if the design elements of the theme contains irregular lines.

A big impediment to making images work is the limitations introduced by the current versions of CSS: All you can really do is provide a square border, possibly with some padding. That’s it, unless you’re willing to manually add tons of markup around images every time – and willing to make your users do it, if you’ve released a theme.Example of images in the "Green Light" WordPress theme

Some people will carefully Photoshop-up their images to make them fit – Webdemar (who made the theme I first used on my blog) does this, for example, and it looks great. That’s a lot of work, though, especially if you make frequent posts with images!

If you’re a theme designer, there’s an easier way to make images work.

CSS Borders

There are a thousand and one different ways to create styled borders in CSS. The basic principle is that one adds a certain amount of HTML markup around the content to be framed, and CSS rules apply background images in a variety of ways. The best of these techniques are very flexible, and allow designers to apply any kind of frame they can imagine.

The Joomla documentation describes one of these techniques quite well, and it’s worth a read.

So, providing a frame around images allows designers to break up those straight lines, among other things. Thus, this:

Example of "Elegant Grunge" WordPress theme without framed images
Note how the straight image border breaks the ‘broken-up’ edge theme

Becomes this:

200810121312.jpg
Frame with drop shadow provides illusion of depth, distancing image from theme

This is, of course, just one example, but there are many possibilities.

So, the question becomes: How do we provide the necessary HTML markup in the content, without doing it ourselves or making our users do it? Enter regular expressions…

Regex magic

The concept is very simple – whenever we encounter an image in the content, we surround it by the markup necessary to render a frame around it. There are, however, a few extra things that’d be nice:

  • Provide the ability to frame any content, not just images, by supplying a class
  • Provide the ability to avoid framing some images, to provide some control, by supplying a class
  • Manage image sizing, in case a too-large image is provided
  • Avoid showing frames if the surrounded image is too small (and would thus look wrong)
  • Some styles/classes applied to the inner content should be also applied to the frame (such as float settings)

This PHP script gives an example of how it can be done as part of a WordPress theme: framing-sample.php.zip

The script provides a filter function, used by WordPress during the render pipeline to modify content. The function looks for blocks with a class of ‘frame’, or images. It avoids any block with a class of ‘noframe’ (and also ‘wp-smiley’, which is the class used for those small emoticons in WordPress). It then uses a ‘callback’ helper function to perform the actual replacement, capturing styles/classes for the inner object, and managing image sizes in the process.

A caveat here: The regular expression that supports wrapping any kind of content block (as opposed to just images) uses a relatively modern feature of regular expressions called recursive sub-patterns, which will not work with PHP installations with an older PCRE regular expression library. Hence, the ‘@’ sign preceding the preg_replace_callback, which will cause it to fail silently, without throwing error messages everywhere.

So, this code wraps the content in four ‘span’ objects, which can then be styled using CSS. For small images, it also applies the ‘small’ class, which can be used to provide a smaller frame to avoid visual glitching.

CSS time

So, we now have markup in place, and it’s time to provide some styles. Here’s some sample CSS:


/* Frame */

.frame-outer {
background: url(images/frame-top-left.jpg) no-repeat left top;
padding: 0;
margin: 0;
display: inline-block;
}

.frame-outer span {
background: url(images/frame-bottom-left.jpg) no-repeat left bottom;
margin: 0;
padding: 0;
display: block;
}

.frame-outer span span {
background: url(images/frame-top-right.jpg) no-repeat right top;
display: block;
}

.frame-outer span span span {
background: url(images/frame-bottom-right.jpg) no-repeat right bottom;
padding: 32px;
min-width: 150px;
min-height: 150px;
text-align: center;
overflow: hidden;
display: block;
}

.frame-outer span span span * {
max-width: 425px;
}

.frame-outer.small {
background: url(images/frame-top-left-small.jpg) no-repeat left top;
}

.frame-outer.small span {
background: url(images/frame-bottom-left-small.jpg) no-repeat left bottom;
}

.frame-outer.small span span {
background: url(images/frame-top-right-small.jpg) no-repeat right top;
}

.frame-outer.small span span span {
background: url(images/frame-bottom-right-small.jpg) no-repeat right bottom;
padding: 10px;
min-height: 38px;
min-width: 38px;
}

.frame-outer span span span span {
background: none;
}

Here’s a sample of the images that are used here:

framing-images.jpg

Further possibilities

Providing frames around image is all very well, but what if that’s not enough? Perhaps you have a particular style set up that requires, say, rounded corners, or Aqua-style bubbles, or sepia tones? Maybe something more complicated, as with Webdemar’s page: Rounded corners, a dark border with a light inner-border, a gradient background, then the image itself rotated a bit then cropped.

It just so happens, there’s a whole lot one can do with the PHP ‘GD’ image processing library, if you’re willing to get your hands dirty. Imagemagick’s ‘convert’ utility is fairly capable too. This is outside the scope of this article, but I may return to the topic another time.

So, one possibility is to add an additional function that is called, which extracts the URL of any image, opens and processes the image, saves it to a local cache, and replaces the URL with a URL to the newly created, cached image. This function could do all kinds of nifty operations on the image, with zero work required on the part of the user.

, , , , , . Bookmark the permalink. Both comments and trackbacks are currently closed.

2 Comments

  1. Posted October 15, 2008 at 12:27 am | Permalink

    I handled this a different way by having special code in my post when I want to do images, callouts, floating boxes etc. It saves me some writing and has many variables I can set as needed. You can see it here:

    http://www.jeremyduffy.com/computers-internet/wordpress-stuff/jtags/

  2. Posted January 16, 2009 at 11:28 am | Permalink

    I was wondering if there was a way to place the navigation bar below the header, rather than all the way at the top? Also, how do I make the titles of the posts smaller? Thanks