A Solution For The WordPress Gallery

There are things in WordPress, I do not like. This includes the gallery. Not that the idea behind it is bad. It is just poorly implemented. But only criticizing is not fair. Let's see what you can do better.

The problem of the gallery is the style sheet, which is simply written in the Post. So that the page no longer validates. Additional problems arise when you want to change the look of the pictures in your theme for example. The style sheet in the post overwrites the values from the theme style sheet. How do the developers know if I like a 2px border #cfcfcf around my images? Something like this definitely does not belong in the code!

Cause of the problem is the ability to choose when you insert the gallery into the post, the number of columns (2-9). WordPress then calculates the width of the list elements by the number of selected columns and writes the values in the style sheet.

WordPress Gallery settings

An own gallery function

The function gallery_shortcode, which generates the gallery, can be found in wp-includes/media.php. For simplicity, we copy the complete function gallery_shortcode in to functions.php of the active theme. Then we rename the function, disable the function of WordPress and activate our own function:

//deactivate WordPress function
remove_shortcode('gallery', 'gallery_shortcode');

//activate own function
add_shortcode('gallery', 'wpe_gallery_shortcode');

//the own renamed function
function wpe_gallery_shortcode($attr) {
    ...
}

We are now going to call up a post with an inserted gallery. It should all work exactly as before, except that our own gallery function is now active. Now let us take any necessary changes to improve the output of the gallery.

First, we delete the following line. Which calculates the column. We do not need it anymore.

$itemwidth = $columns > 0 ? floor(100/$columns) : 100;

Then we modify the variable $output. The style sheet will be completely erased. The inline style of the clearing br will be also removed. It's more elegant in its own theme style sheet. Finally, the last br-tag gets removed. The revised code $output should now look like this:

$output = apply_filters('gallery_style', "
    <div id='$selector' class='gallery galleryid-{$id}'>");

$i = 0;
foreach ( $attachments as $id => $attachment ) {
    $link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, $size, false, false) : wp_get_attachment_link($id, $size, true, false);

    $output .= "<{$itemtag} class='gallery-item'>";
    $output .= "
        <{$icontag} class='gallery-icon'>
            $link
        </{$icontag}>";
    if ( $captiontag && trim($attachment->post_excerpt) ) {
        $output .= "
            <{$captiontag} class='gallery-caption'>
            " . wptexturize($attachment->post_excerpt) . "
            </{$captiontag}>";
    }
    $output .= "</{$itemtag}>";
    if ( $columns > 0 && ++$i % $columns == 0 )
        $output .= '<br />';
}

$output .= "</div>\n";

return $output;

After we have updated the post in our browser, we see all the pictures one below the other. But the document is valid. Now we need to create the column functionality again, that we have erased before. We simply add one additional class with the number of columns in $itemtag:

$output .= "<{$itemtag} class='gallery-item col-{$columns}'>";

In your source code, depending on the number of columns you see

<dl class="gallery-item col-5">

Now, implement a few lines in the theme style sheet and the gallery is finished.

.gallery {
    margin: auto;
    /* gallery clearing*/
    overflow: hidden;
    width: 100%;
}
.gallery .gallery-item {
    float: left;
    margin-top: 10px;
    text-align: center;
}
.gallery img {
    border: 2px solid #cfcfcf;
}
.gallery .gallery-caption {
    margin-left: 0;
}
.gallery br { clear: both }

/* available Columns */
.col-2 { width: 50% }
.col-3 { width: 33.333% }
.col-4 { width: 25% }
.col-5 { width: 20% }
.col-6 { width: 16.666% }
.col-7 { width: 14.285% }
.col-8 { width: 12.5% }
.col-9 { width: 11.111% }

WordPress gallery

Comments are closed.

36 comments

  1. Doug Stewart

    Okay, that's just awesome. So awesome, in fact, that it probably should be in core.

    Too late for 2.9, but dang!, that oughtta be in 3.0.

  2. Bronson

    Nice thinking, I can definitely live with the end result if it means that I no longer have to tweak NextGen after every update anymore.

  3. Doug Stewart

    Okay, I started a ticket:

    http://core.trac.wordpress.org/ticket/11155

    I just put up a .diff for the PHP. I'll take a stab at the CSS too.

  4. Michael

    Doug, nice idea!

  5. Doug Stewart

    Okay, there was an existing ticket that covered the same area but lacked the simple approach you took. I've closed out my ticket as a dupe and submitted the PHP and CSS fixes over on that ticket instead.

    *crossed fingers* Here's hoping it goes into 3.0.

    Btw:
    http://core.trac.wordpress.org/ticket/10734

  6. designfollow

    thank for this great post

  7. Tomas Kapler

    I also like this solution, but imho there should be some settings for this, for backwards compatibility as all existing themes simply do not count with the need of implementing the style in their themes.

    P.S.: i think there should be also some semantics in the code, e.g. using dl for gallery, dt for caption and dd for image

  8. bfnh

    i stumbled across this site looking to find info on how to create a plugin. i have been trying to write up a description on the changes i've made to the wordpress gallery to use an additional attribute called currentid. i may need to take some of these changes, too.

  9. Simon

    I always thought that the core gallery function of wordpress felt more like a rush job to get it in the release than a final approach. Even so I have recently taken the opinion of why use a plug-in to reinvent something that the core already provides so I have been using the core function. Your solution just gave me vindication for my approach, one more thing in wordpress's favour.

  10. Domas

    It's really nice, but pagination for this would be just awesome! Any suggestion?

  11. Joe Banks

    This is an elegant solution and worth taking an extra moment to fawn over via this comment. The WordPress core would only be improved, and I should visit your site more often. *noted*

  12. Dam Milward

    Damn. That is awesome!!

    Any idea on how to make the images open in a thickbox as opposed to on a new page?

    That option I really would like to see in 3.0 :D

    Oh and I agree with Joe. I'm going to be keeping an eye on your site!!!

    Best,
    Dan

  13. Aaron Cimolini

    hehehe, Thanks man, you just saved my night. Awesome little fix.

    Check it, I reworked this to allow you to specifiy if you want some of the tags or not but just setting them to an empty string in the shortcode.

    like here I just set the icontag to "" and that gets rid of the icon tag entirely.
    [gallery link="file" columns="3" itemtag="div" icontag="" captiontag="p"]

    //the own renamed function
    function wpe_gallery_shortcode($attr) {
    global $post;

    static $instance = 0;
    $instance++;

    // Allow plugins/themes to override the default gallery template.
    $output = apply_filters('post_gallery', '', $attr);
    if ( $output != '' )
    return $output;

    // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
    if ( isset( $attr['orderby'] ) ) {
    $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
    if ( !$attr['orderby'] )
    unset( $attr['orderby'] );
    }

    extract(shortcode_atts(array(
    'order' => 'ASC',
    'orderby' => 'menu_order ID',
    'id' => $post->ID,
    'itemtag' => 'dl',
    'icontag' => 'dt',
    'captiontag' => 'dd',
    'columns' => 3,
    'size' => 'thumbnail',
    'include' => '',
    'exclude' => ''
    ), $attr));

    $id = intval($id);
    if ( 'RAND' == $order )
    $orderby = 'none';

    if ( !empty($include) ) {
    $include = preg_replace( '/[^0-9,]+/', '', $include );
    $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );

    $attachments = array();
    foreach ( $_attachments as $key => $val ) {
    $attachments[$val->ID] = $_attachments[$key];
    }
    } elseif ( !empty($exclude) ) {
    $exclude = preg_replace( '/[^0-9,]+/', '', $exclude );
    $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    } else {
    $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    }

    if ( empty($attachments) )
    return '';

    if ( is_feed() ) {
    $output = "\n";
    foreach ( $attachments as $att_id => $attachment )
    $output .= wp_get_attachment_link($att_id, $size, true) . "\n";
    return $output;
    }

    // check to see if tags have been set to false. If they are the defaults or have been set to a string value use that as the tag.
    if ($itemtag) $itemtag = tag_escape($itemtag);
    if ($captiontag) $captiontag = tag_escape($captiontag);
    if ($icontag) $icontag = tag_escape($icontag);
    $columns = intval($columns);

    $selector = "gallery-{$instance}";

    $output = apply_filters('gallery_style', "\n");

    $i = 0;
    foreach ( $attachments as $id => $attachment ) {
    ++$i;
    $link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, $size, false, false) : wp_get_attachment_link($id, $size, true, false);

    if ($itemtag) {
    $output .= "\t 0 && $i % $columns == 0) $output .= "last";
    $output .= '\'>';
    }
    if ($icontag) $output .= "";
    $output .= "\n\t\t" . $link . "\n";
    if ($icontag) $output .= "";
    // if the attachment has a caption set
    if ( trim($attachment->post_excerpt) ) {
    if ($captiontag) $output .= "\t\t";
    $output .= wptexturize($attachment->post_excerpt);
    if ($captiontag) $output .= "" . "\n";
    }
    if ($itemtag) $output .= "\t" . "\n";
    if ( $columns > 0 && $i % $columns == 0 ) $output .= "\n";
    }

    $output .= "\n";

    return $output;
    }

    oh, here's the css as well:
    gallery { margin: 0 24px; width: 552px; float: left;}
    .gallery-item { float: left; margin: 0 24px 24px 0; background:#C4BFA2; }
    .gallery .last { margin-right: 0; }
    .gallery-icon {}
    .gallery-caption {}
    .gallery br { clear: both; }

  14. Michael

    @Aaron: My motivation was to make the gallary valid not to add more features. That is Dev Stuff.

    @Dem: You can edit your gallery in the advanced tab and add classes or rel attributes for lightbox, thickbox etc. to make it work.

  15. rambal

    Very useful override to the gallery.
    It solves the problem.

    Thank you my friend.

  16. Rus Miller

    @Aaron, that seems like a good solution. Unfortunately, the blog chewed up all your code so I cleaned it up and posted it on Snipplr: http://snipplr.com/view/27051/wordpress-27-gallery-styles-fix/

    Thanks to you and Michael for your ingenuity and hard work.

  17. tom (dB)

    Nice work, thanks for posting it.

    P.S. Your sidebar says 'Most Commeted' (you missed out the N)

  18. Michael

    Thanks tom! fixed ;)

  19. Carlo Rizzante

    Thank you so much!!! It works wonderfully and I'm freaky happy to have finally validated my Galleries in my portfolio. That was an important issue. Solved brilliantly!

  20. Carlo Rizzante

    I would like to add that unfortunately I had an other problem which caused the not validation of my pages with a Gallery. Sort of this:

    (followed suddenly by a )

    Which I don't understand, 'cos the tag was missing the closure , causing 5 validation failures.

    Adding a fictional just after the shortcode [gallery] did not help, 'cos it ended up after the .

    But now it's all fine ;)

  21. fb

    This is very similar to Tadlocks Cleaner gallery

    http://justintadlock.com/archives/2008/04/13/cleaner-wordpress-gallery-plugin

  22. rogue cat

    Thanks so much for the great info.

  23. zamson

    First of - great solution! I'm almost there..

    How would I go about to add a class to the thumbnail images?

    I'm trying to get them to work with a jquery plugin. I've managed everything but adding the class "thumb" to the a href.

    Please advice.

  24. Michael

    zamson, add the class with jquery :p

  25. zamson

    Thanks for the tip Michael. I tried with the addClass selector but I guess the js gallery plugin does not understand the links when the html still does not output the whole code :(

    Any ideas on how to add class to the thumnail image link from within wordpress?

  26. Nikita Sumeiko

    Your suggestion to change wordpress default gallery function is awesome. I used it to completely reworked gallery style. And now it is working for my client very well.

    Thank you very much, Michael!

  27. Michael

    @Nikita: Nice to hear :)

  28. satanclaus

    is there a chance to get the first image thumbnail bigger than the rest of the galery images?

  29. Benjamin

    Thank you so much Michael --

    I was getting so frustrated trying to track down the little bugger that was making my gallery pages not validate. Starting with your tip, my markup is actually semantic too!

    Count me as a new subscriber!

  30. John

    Just wow. Thanks so much. Was struggling with getting Masonry to work with a WP gallery, and the embedded WP CSS was messing with the layout. Plugged this in, and VIOLA!

    Much appreciated!

  31. jaime

    got this when i tryed to use your code on my functions.php :/

    Warning: Invalid argument supplied for foreach()

  32. Matthew

    @jaime Yeah, I get the exact same error in the foreach() line.

    Using wordpress 3.0.4

  33. Jeremy Howlett

    Looking to add a class to the a tag for the images in my gallery, just a set specific class like class="lightbox". any ideas?

    thanks

  34. Hawk in Winter

    I didn't even know what a dl/dt tag was before I tried to style the wp gallery. Then I ran into all kinds problems trying to style it correctly. Thanks for this!

2 pingbacks

  1. Die WordPress Galerielösung ist nun im Trac - WordPress, Ticket, Leider, Version, Engineer, Beitrag - dynamicinternet
  2. Random Compilation II | Deborah Schmidt