Converting a WordPress gallery into a responsive slideshow without a plugin (PHP code included)

A client needed a slideshow in their post content. I tried a number of slideshow plugins, but all required you create the slideshow before creating the post, and most had more features than I needed. So I wrote a function to convert standard WordPress galleries to slideshows.

From your post edit screen, select “add media”

Select “create gallery” and choose the images you want to include:

The images will appear as a gallery in the edit screen:

But when rendered in your post, they’ll show up as a slideshow:

Add the PHP code below to your functions.php file to convert WordPress galleries to slideshows.

Here’s the code:


function gallery_to_slideshow( $output, $attr, $instance ) {

	$args = array(
		'post__in'       => explode( ',', $attr['ids'] ),
		'post_type'      => 'attachment',
		'post_mime_type' => 'image',
		'no_found_rows'  => true,
		'posts_per_page' => - 1,
		'post_status'    => 'any'
	);

	$query       = new \WP_Query( $args );
	$slide_count = count( $query->posts );

	if (0 === $slide_count) {
		return '';
	}

	ob_start();
	?>
	<div
			class="sem-gallery"
			id="gallery-<?php echo $instance ?>"
			data-current="0"
			data-count="<?php echo $slide_count ?>"
	>
		<div style="
				position: relative;
				width: 100%;
				aspect-ratio: 16/9;
				overflow: hidden;
		">
			<div class="sem-gallery-slides"
			     style="
					     top: 0;
					     bottom: 0;
					     left: 0;
					     position: absolute;
					     display: flex;
					     width: <?php echo $slide_count * 100 ?>%;
					     ">
				<?php foreach ( $query->posts as $i => $post ) : ?>
					<div style="
							width: <?php echo 100 / $slide_count ?>%;
							background-color: #eee;
							background-image: url(<?php echo wp_get_attachment_url($post->ID) ?>);
							background-size: contain;
							background-position: center;
							background-repeat: no-repeat;
							"
					></div>
				<?php endforeach; ?>
			</div>
		</div>
		<div style="
		display: flex;
		margin-top: 1rem;
		gap: 1rem;
		justify-content: center;
	">
			<button type="button"
			        data-action="prev"
			        class="button">Previous
			</button>
			<button type="button"
			        data-action="next"
			        class="button">Next
			</button>
		</div>
	</div>
	<script>
		jQuery(function ($) {
			$('#gallery-<?php echo $instance ?> button[data-action]').click(function () {
				const $this = $(this);
				const $wrapper = $this.closest('.sem-gallery');
				const current = parseInt($wrapper.data('current'));
				const count = parseInt($wrapper.data('count'));

				const currentNew = 'next' === $this.data('action')
					? current + 1 < 0 || current + 1 + 1 > count ? 0 : current + 1
					: current - 1 < 0 ? count - 1 : current - 1;

				const $slides = $('.sem-gallery-slides', $wrapper);

				$slides.animate({ left: `-${currentNew * 100}%` });
				$wrapper.data('current', currentNew);
			});
			p;
		});
	</script>
	<?php

	$to_return = ob_get_contents();
	ob_end_clean();

	return $to_return;
}

add_filter( 'post_gallery', 'gallery_to_slideshow', 99, 3 );