Solving the Extra 10 Pixels in WordPress Captions with JavaScript

This post has been updated to improve the code snippet. Before I was grabbing the width of the image, which could be different in a responsive theme depending upon the current size of your window. Now we’re getting the width attribute, which will be the same no matter what size your viewport is. 

First of all, here’s the JavaScript code:

function correctCaptionWidth() {
    // Removes the extra 10 pixels added by WordPress.
    $(".wp-caption").width(function() {
        return jQuery('img', this).attr('width');
    // This allows it to be responsive.
    $(".wp-caption").css('max-width', '100%');

Lots of folks get steamed over WordPress captions, because they’re designed to be ten pixels wider than the photo they’re placed under. There’s actually a good reason for the extra space, but for some designs it can be a problem. I’ll explain how I got rid of it, but first I’d like to tell you why things are that way in the first place.

HTML elements, by default, expand to the size of their containers. To change this, some kind of width needs to be applied. Images are a little different because they actually have a real width of their own. By default, a photo will be its own regular size. To make a caption, WordPress wraps an image inside an HTML element. The image can be left aligned or whatever, but that caption container is going to run all the way to the end if we don’t do something. For this reason, WordPress looks at the photo and assigns a width to the containing div tag. They chose ten pixels because… well, because they wanted to. It goes well with the default design that comes with WordPress.

But there are problems if your design requires certain kinds of alignment, and especially if your design is responsive. An inline style is extremely specific, so it tends to override anything else you do. Even worse, it’s a set number and therefore refuses to scale down for responsive themes. (I’m assuming that you’re building your own theme here. Pre-built commercial or free themes might have solutions in place already.) The ten pixels really needs to be changed right there at the div, and there are two ways to do it:

  1. PHP: You could either place a filter in functions.php or build a small plugin.
  2. JavaScript: Add a small function to update the width of the caption container.

I decided to go with JavaScript since I’m a little stronger there, and because jQuery makes it really easy to target things. You’ll notice in the code that my first move is to target all of the WordPress captions on the page, and set their widths to a function. I could have grabbed the image width first, assigned a variable and then jumped up one level to the container before assigning the width, but this is much cleaner. The function takes care of the targeting for us. For each caption, we find out the width of the image it contains, and set the width to that value. Done.

But we’re still in trouble where responsive themes are concerned. We’ve killed the extra 10 pixels, but it’s still a set value. To solve this, an extra line is added to assign a max-width to the div. Since the max-width is inline, it carries the same specificity as the width attribute. We no longer need to worry about the hard number overriding our nice responsive styles.

Finer Points

I could have just tossed these lines of code into the $(document).ready function, but I chose to enclose them within their own function as a matter of policy. Maybe I’ll want to use a function when the browser window changes or put it on a timer or something. Or maybe I want a function to be called more than once, or with different arguments for different situations. For these reasons, I like to keep my code in functions for the most part. And besides, it makes the $(document).ready function easier to read. If a task takes more than a line or two, I tend to put it into a function. So the function sits somewhere in my functions.js file, and the $(document).ready function just contains a call to the resizing function.

And one last point about JavaScript variables. I used $(“.wp-caption”) twice in the code above. This means that jQuery had to go looking through the DOM twice to find all the elements with that class attached. There’s a pretty good argument for a variable here. I could have written it like this:

var wpCaption = $(".wp-caption");

This way, jQuery will go through the DOM once, and remember the elements that it found. When you should do this is a bit of a judgement call. Once doesn’t justify a variable. Twice may or may not make a difference in performance, depending upon how much jQuery has to look for. Three times, however, and you’re definitely in variable country.

This won’t make much of a difference in lighter sites with just a bit of JavaScript, but if you have a lot going on then you’ll be glad for the savings in performance. And you’ll be especially glad if you’re messing around with the HTML5 canvas element.

Hopefully this will help you with your design, especially if your theme is responsive. If you have a better idea about how to adjust WordPress captions, please drop in for a comment. I’m always looking for a better mousetrap.