9

When creating an image gallery in WordPress using the default Media Uploader, WordPress wraps the images in a bunch of HTML markup.

How can I overwrite this before it's generated so that I can output the desired markup and change the way the gallery layout is created?

Currently, WordPress is generating the code like this:

<div id="container"> <div src="<?php bloginfo('template_directory'); ?>/images/small.jpg"> <div src="<?php bloginfo('template_directory'); ?>/images/medium.jpg" data-media="(min-width: 400px)"></div> <div src="<?php bloginfo('template_directory'); ?>/images/large.jpg" data-media="(min-width: 950px)"></div> <div src="<?php bloginfo('template_directory'); ?>/images/extralarge.jpg" data-media="(min-width: 1200px)"></div> </div> 

5 Answers 5

33

Instead of overwriting the gallery shortcode function, a better way is to use the post_gallery filter that is included within that function.

Add this in functions.php

add_filter('post_gallery','customFormatGallery',10,2); function customFormatGallery($string,$attr){ $output = "<div id=\"container\">"; $posts = get_posts(array('include' => $attr['ids'],'post_type' => 'attachment')); foreach($posts as $imagePost){ $output .= "<div src='".wp_get_attachment_image_src($imagePost->ID, 'small')[0]."'>"; $output .= "<div src='".wp_get_attachment_image_src($imagePost->ID, 'medium')[0]."' data-media=\"(min-width: 400px)\">"; $output .= "<div src='".wp_get_attachment_image_src($imagePost->ID, 'large')[0]."' data-media=\"(min-width: 950px)\">"; $output .= "<div src='".wp_get_attachment_image_src($imagePost->ID, 'extralarge')[0]."' data-media=\"(min-width: 1200px)\">"; } $output .= "</div>"; return $output; } 

This is assuming you've set up image sizes for the different sizes you need using https://codex.wordpress.org/Function_Reference/add_image_size

Sign up to request clarification or add additional context in comments.

5 Comments

The filter and the get_posts work great, although i had to change the foreach loop as the wp_get_attachment_image did not retrieve anything even though i had the correct thumb sizes. But i could easily change it to get the data i needed. Very helpful the post_gallery filter tip, thanks!
Although, div would be the nicer solution, IMHO, using CSS background ;)
This works, although the order argument cannot be passed through get_posts() since the IDs are simply ordered in the shortcode itself. Does anyone have a method of keeping the order of the gallery this way?
@RCNeil post_gallery has 3 arguments: $output, $atts, $instance. $atts['ids'] contains the ids (of the gallery items) and $atts['orderby'] contains the order..
This doesn't seem to work for the new Gutenberg one :(
18

I missed the post_gallery filter mentioned in the Answer just below this one. You should really consider using that filter instead of copying over the whole function.

Add this code to your template's functions.php and modify the HTML inside function. This function is copy of WP35's default gallery shortcode function. Accordiong to Codex, each shortcode can have only one function assigned to it, and because of that, your function will override WordPress default one:

add_shortcode('gallery', 'my_gallery_shortcode'); function my_gallery_shortcode($attr) { $post = get_post(); static $instance = 0; $instance++; if ( ! empty( $attr['ids'] ) ) { // 'ids' is explicitly ordered, unless you specify otherwise. if ( empty( $attr['orderby'] ) ) $attr['orderby'] = 'post__in'; $attr['include'] = $attr['ids']; } // 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) ) { $_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) ) { $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; } $itemtag = tag_escape($itemtag); $captiontag = tag_escape($captiontag); $icontag = tag_escape($icontag); $valid_tags = wp_kses_allowed_html( 'post' ); if ( ! isset( $valid_tags[ $itemtag ] ) ) $itemtag = 'dl'; if ( ! isset( $valid_tags[ $captiontag ] ) ) $captiontag = 'dd'; if ( ! isset( $valid_tags[ $icontag ] ) ) $icontag = 'dt'; $columns = intval($columns); $itemwidth = $columns > 0 ? floor(100/$columns) : 100; $float = is_rtl() ? 'right' : 'left'; $selector = "gallery-{$instance}"; $gallery_style = $gallery_div = ''; if ( apply_filters( 'use_default_gallery_style', true ) ) $gallery_style = " <style type='text/css'> #{$selector} { margin: auto; } #{$selector} .gallery-item { float: {$float}; margin-top: 10px; text-align: center; width: {$itemwidth}%; } #{$selector} img { border: 2px solid #cfcfcf; } #{$selector} .gallery-caption { margin-left: 0; } </style> <!-- see gallery_shortcode() in wp-includes/media.php -->"; $size_class = sanitize_html_class( $size ); $gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>"; $output = apply_filters( 'gallery_style', $gallery_style . "\n\t\t" . $gallery_div ); $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='wp-caption-text gallery-caption'> " . wptexturize($attachment->post_excerpt) . " </{$captiontag}>"; } $output .= "</{$itemtag}>"; if ( $columns > 0 && ++$i % $columns == 0 ) $output .= '<br style="clear: both" />'; } $output .= " <br style='clear: both;' /> </div>\n"; return $output; } 

5 Comments

Hi guys, this looks great. I can see what it's doing but when I include it in my functions.php, it has no effect. I've made it the last function in the file in an effort to have it load last. Any ideas what might be the issue?
I can't get this working either. I tried to past into functions.php - with no change. @tadywankenobi - how did you get it work?
Actually, I got it. It won't take effect until you add a NEW gallery. For some reason it does not apply to already existing galleries
Actually, this is incorrect. You have to first unhook the default function and then add a new function to handle it. Unhook using remove_shortcode('gallery'), then add_shortcode('gallery', 'your function'). Furthermore, there is no need to copy the whole function. You only need to use the filter 'post_gallery' to return your own markup, and the default function wont be used.
You're right - that was already mentioned in the answer below this one: stackoverflow.com/a/23410472/1259882
4

Building off of @DaveF's answer, here is a gallery function that maintains the gallery order and also randomizes if it is selected in the WP editor -

add_filter('post_gallery','customFormatGallery',10,2); function customFormatGallery($string,$attr){ $posts_order_string = $attr['ids']; $posts_order = explode(',', $posts_order_string); $output = "<div class=\"gallery-container\">"; $posts = get_posts(array( 'include' => $posts_order, 'post_type' => 'attachment', 'orderby' => 'post__in' )); if($attr['orderby'] == 'rand') { shuffle($posts); } foreach($posts as $imagePost){ $output .= '<img src="' . wp_get_attachment_image_src($imagePost->ID, 'full')[0] . '" alt="" />'; } $output .= "</div>"; return $output; } 

1 Comment

Late comment: I get a syntax error on the $output line in the foreach. Appears to be the wp_get_attachment_image_src arguments....
2

Just addition to accepted answer To make it work you need first to remove default gallery short code like this:

add_action( 'after_setup_theme', 'my_override_of_default_gallery' ); function my_override_of_default_gallery() { remove_shortcode( 'gallery' ); add_shortcode('gallery', 'my_gallery_shortcode'); } //add_shortcode('gallery', 'my_gallery_shortcode'); function my_gallery_shortcode($attr) { $post = get_post(); ... } 

1 Comment

+1 for mentioning "removing" the other function. But note that the best aproach is to use the provided filter (see filter "post gallery" around line 981).
1

Here is the code that I change to obtain the layout that I was looking for:

/****** REWRITE THE GALLERIE FUNCTION FROM WORDPRESS **********/ add_shortcode('gallery', 'my_gallery_shortcode'); function my_gallery_shortcode($attr) { $counter=0; //var_dump("Rewrite the shortcode gallery"); $post = get_post(); static $instance = 0; $instance++; if ( ! empty( $attr['ids'] ) ) { // 'ids' is explicitly ordered, unless you specify otherwise. if ( empty( $attr['orderby'] ) ) $attr['orderby'] = 'post__in'; $attr['include'] = $attr['ids']; } // 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( /****** CHANGE TO FULL SIZE TO GET THE CORRECT INFORMATION **********/ 'order' => 'ASC', 'orderby' => 'menu_order ID', 'id' => $post->ID, 'itemtag' => 'dl', 'icontag' => 'dt', 'captiontag' => 'dd', 'columns' => 3, 'size' => 'Full size', 'include' => '', 'exclude' => '' ), $attr)); /***********************************************************************/ $id = intval($id); if ( 'RAND' == $order ) $orderby = 'none'; if ( !empty($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) ) { $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; } $itemtag = tag_escape($itemtag); $captiontag = tag_escape($captiontag); $icontag = tag_escape($icontag); $valid_tags = wp_kses_allowed_html( 'post' ); if ( ! isset( $valid_tags[ $itemtag ] ) ) $itemtag = 'dl'; if ( ! isset( $valid_tags[ $captiontag ] ) ) $captiontag = 'dd'; if ( ! isset( $valid_tags[ $icontag ] ) ) $icontag = 'dt'; $columns = intval($columns); $itemwidth = $columns > 0 ? floor(100/$columns) : 100; $float = is_rtl() ? 'right' : 'left'; $selector = "gallery-{$instance}"; $gallery_div ="<div pictures-content>"; $gallery_style =""; $output = apply_filters( 'gallery_style', "\n\t\t" . $gallery_div ); $i = 0; $count=0; foreach ( $attachments as $id => $attachment ) { $test = $attachments[$id]; $link=$test->guid; $nocsript=""; if ($count==0){$nocsript ="<noscript><img src='$link'</noscript>";$sentence ="<div data-src='$link'></div>";} if ($count==1){$sentence ="<div data-src='$link' data-media='(min-width: 400px)'></div>";} if ($count==2){$sentence ="<div data-src='$link' data-media='(min-width: 800px)'></div>";} if ($count==3){$sentence ="<div data-src='$link' data-media='(min-width: 1000px)'></div>";} if($nocsript==""){ $output .= "$sentence";} else { $output .= $nocsript."$sentence";} $count++; } $output .= "</div>\n"; return $output; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.