Build a custom image slider using a Custom Post Type

In a previous tutorial, I showed you how one can build a custom image slider using the wp_get_attachement_image function(). This method works very well, but of course there are more than one ways to build a slider. The method of choice will depend on your functionality requirement.

The wp_get_attachement_image function() is great if you want to create a slider out of one post and multiple attachments. For example, portfolio pieces would fall in that category.
But what if instead you wanted a slider to feature multiple posts, with one image each, which would link to different pages? The slider itself would work the same way, but you’ll need to set your back-end a bit differently and use a different loop in your template.

This tutorial will show you how this can be done using a custom post type. Here’s a sneak peek at the demo site. The files used to create the theme as well as the slider snippet can be downloaded here.

This demo site is fairly simple. The front page template uses custom post types to build the slider.  The portfolio on the other hand links to a single.php template which also uses the same jQuery slider, but the images fade in and out. Our previous tutorial covered the necessary steps to build that. So let’s look how we can set up that front page.

Step 1: Create your Custom Post Type (CPT)

Our front page will display a slider displaying an image, title, brief content and a link to one of our portfolio pieces. This type of slider would be used to display “Featured” portfolio pieces. So let’s called our CPT “Feature”.

Custom post types can easily be added to any theme by updating our functions.php file. If you haven’t played around with CPTs yet, I would encourage you to read Justin’s article.

To create our CPT, let’s update our functions.php with the following:

// Custom Post types for Feature project on home page 
	   add_action('init', 'create_feature');
	     function create_feature() {
	       $feature_args = array(
	          'labels' => array(
	           'name' => __( 'Feature Project' ),
	           'singular_name' => __( 'Feature Project' ),
	           'add_new' => __( 'Add New Feature Project' ),
	           'add_new_item' => __( 'Add New Feature Project' ),
	           'edit_item' => __( 'Edit Feature Project' ),
	           'new_item' => __( 'Add New Feature Project' ),
	           'view_item' => __( 'View Feature Project' ),
	           'search_items' => __( 'Search Feature Project' ),
	           'not_found' => __( 'No feature project found' ),
	           'not_found_in_trash' => __( 'No feature project found in trash' )
	       'public' => true,
	       'show_ui' => true,
	       'capability_type' => 'post',
	       'hierarchical' => false,
	       'rewrite' => true,
	       'menu_position' => 20,
	       'supports' => array('title', 'editor', 'thumbnail')
	add_filter("manage_feature_edit_columns", "feature_edit_columns");

	function feature_edit_columns($feature_columns){
	   $feature_columns = array(
	      "cb" => "<input type=\"checkbox\" />",
	      "title" => "Title",
	  return $feature_columns;
	//Add Meta Boxes

	add_action( 'add_meta_boxes', 'cd_meta_box_add' );
	function cd_meta_box_add()
		add_meta_box( 'my-meta-box-id', 'Link to Project', 'cd_meta_box_cb', 'feature', 'normal', 'high' );

	function cd_meta_box_cb( $post )
		$url = get_post_meta($post->ID, 'url', true);
		wp_nonce_field( 'my_meta_box_nonce', 'meta_box_nonce' ); ?>

			<label for="url">Project url</label>
			<input type="text" name="url" id="url" value="<?php echo $url; ?>" style="width:350px" />

	add_action( 'save_post', 'cd_meta_box_save' );
	function cd_meta_box_save( $post_id )
		// Bail if we're doing an auto save
		if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;

		// if our nonce isn't there, or we can't verify it, bail
		if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;

		// if our current user can't edit this post, bail
		if( !current_user_can( 'edit_post' ) ) return;

		// now we can actually save the data
		$allowed = array( 
			'a' => array( // on allow a tags
				'href' => array() // and those anchors can only have href attribute

		// Probably a good idea to make sure your data is set
		if( isset( $_POST['url'] ) )
			update_post_meta( $post_id, 'url', wp_kses( $_POST['url'], $allowed ) );

Whoah! That’s a lot of code. But don’t let that scare you. Once the functions.php file updated, a new tab called Feature Project will appear as part of your sidebar. You’ll notice that I’ve also included a meta box. We could have used custom fields, but meta boxes are prettier and fairly easy to use. Here’s a great tutorial to get you started with Meta boxes.

Step 2: Populate your Feature Projects

Now that your CPT is ready, you can start setting up your projects. Go ahead and set up two or more projects by:

  1. Giving each a title
  2. Entering a few lines of content
  3. Uploading one image per project and set it as a featured image
  4. Inserting a link to one a page on your blog or an external site (optional)

For the purpose of this demo, I’ve set my image slider to be 940px x 280px. The images appearing on the left are 640px x 280px.

Step 3: Enqueue your jQuery

Step 3 of our previous tutorial is exactly the same here. You’ll need to update your functions.php as follows:

function blm_init_method() {
    wp_enqueue_script( 'slides', get_template_directory_uri().'/js/slides.min.jquery.js', array( 'jquery' ) );

add_action('wp_enqueue_scripts', 'blm_init_method');

Step 4: Update your header.php

In order to get the slider to work, you’ll need to add the following content about your </head> tag.

<script type="text/javascript">
			preload: true,
			preloadImage: '<?php echo get_template_directory_uri(); ?>/images/loading.gif',
			play: 5000,
			pause: 2500,
			hoverPause: true,
			generatePagination: false


Step 5: Display your CPT

Next, we need to pull the content out and display it. For the purpose of this demo, I’ve created a front-page.php which as the title says, I’m using on my home page.

In order to display the content, I’ll use the WP_query function inside like so:

<section id="featured-slider">
	<div id="slides">
		<div class="slides_container">
				$loop = new WP_Query(array('post_type' => 'feature', 'posts_per_page' => -1, 'orderby'=> 'ASC')); 
			<?php while ( $loop->have_posts() ) : $loop->the_post(); ?>

				<div class="slide">
					<?php $url = get_post_meta($post->ID, "url", true);
					if($url!='') { 
						echo '<a href="'.$url.'">';
						echo the_post_thumbnail('full');
						echo '</a>';
					} else {
						echo the_post_thumbnail('full');
					} ?>
					<div class="caption">
						<h5><?php the_title(); ?></h5>	
						<?php the_content();?>

			<?php endwhile; ?>
			<?php wp_reset_query(); ?>

		<a href="#" class="prev">prev</a>
		<a href="#" class="next">next</a>

This loop, will look at all of the post saved as “feature” and loops through all of them (posts_per_page’ => -1) and order them. It then spits out the content and links the image if the meta box has been filled. All of this is inserted inside various div tags which can now be manipulated with css.

Last step: Update your stylesheet

As mentioned above, the next step requires us to add some css. The following is what we’ve used on our demo site:

/* Home page featured slider
#featured-slider {
	width:940px; height:280px;
	margin:0 10px;
#featured-slider #slides {
#featured-slider .slides_container {
#featured-slider .slides_container div.slide {
#featured-slider .caption {
	top: 30px; left:670px;
#featured-slider .caption h2 {

#featured-slider #slides .next, #slides .prev {
	background: url(images/larr.gif);
#featured-slider #slides .next {
	background: url(images/rarr.gif);

There you have it. An easy to use and update feature slider for your home page. I’ve provided you with the files for the theme and also the snippets that I’ve used for the slider. Feel free to download them, play and let me know how you get on.


  1. Brilliant! Thanks for sharing – I found it useful – when implementing my own version of this.

  2. Nevermind — Fixed it. There is an issue when copying this part of the code into the functions.php:

    function blm_init_method() {
    wp_enqueue_script( 'slides', get_template_directory_uri().'/js/slides.min.jquery.js', array( 'jquery', 'easing' ) );


    I went into your template files you made available for download, and it seems that the ‘easing’ part of the top lines of code was removed and now it works fine. As you can see, the bottom code doesn’t have it. Just a heads up to fix up above so people don’t encounter the same problem.

    function blm_init_method() {

    wp_enqueue_script( 'slides', get_template_directory_uri().'/js/slides.min.jquery.js', array( 'jquery' ) );


  3. Thanks for alerting me to this error Vincent, I’ll have a look and update the files and tutorial. Glad to see you got it working.

  4. It would be nice to add some functionality to this great tutorial. I like this very much but I would like to ask if it’s possible to add slider buttons at the center of the slider that are click-able. This is to show how many sliders there are.
    Is this easy to achieve?

    1. Hi Tim,
      Yes you can integrate the buttons at the bottom. If you look at the original jQuery demo ( that I used for the demo and integrated in WordPress, you’ll see that there is pagination. In my step 4, in the code snippet, I set generatePagination: false. If you set pagination to true, the slider automatically generates the pagination. You then, just need to update your css to create the buttons.

  5. Thank you for both of your posts related to creating custom slideshows in WordPress. They are clearly spelled out and I’ve learned a great deal.

    Just wanted to let you know I found a tiny but important error in your code. In the line I’ve quoted below, I’ve changed “orderby” to “order”. The ordering doesn’t work otherwise.

    $loop = new WP_Query(array(‘post_type’ => ‘feature’, ‘posts_per_page’ => -1, ‘order’=> ‘ASC’));

    With the combination of your code and an ordering plugin I found ( I can easily change the order of the items in my slideshow.

    Thanks again!

Comments are Closed.