This tutorial will show you how to integrate the awesome jQuery plugin Smooth Div Scroll with WordPress using a Custom Post Type and creating a short code to display it.

So what is the Smooth Div Scroll plugin? Smooth Div Scroll is a jQuery plugin that scrolls content horizontally left or right. Apart from many of the other scrolling plugins that have been written for jQuery, Smooth Div Scroll does not limit the scrolling to distinct steps. As the name of the plugin hints, scrolling is smooth. There are no other buttons or links on outside the scroller since the scrolling is done using your fingers (touch), hotspots, the mouse wheel or via auto scrolling. Unobtrusive and smooth is the key here.

This great plugin was created by Thomas Kahn. You can view a demo and download the plugin at Once you complete our tutorial, you may what to read through the documentation to make any changes or to better understand how it works.

So let’s get started…

Step 1 – Get the plugin

Download the plugin Download Smooth Div Scroll 1.3 (zip archive)

Step 2 – Add the .JS files

You will need to upload the included .js files to your javascript folder within your theme. Our folder is named /js/ but if you are using a different name make sure to update the lines of code below. The lines of code below go in to your funtions.php file where you enqueue your scripts. See the wordpress codex for information on how to enqueue scripts.

// Loads jQuery UI JavaScript file.
wp_enqueue_script( 'jquery-ui', get_template_directory_uri() . '/js/jquery-ui-1.10.3.custom.min.js', array( 'jquery' ), '1.10.3', true );

// Loads product scroll mouse wheel JavaScript file.
wp_enqueue_script( 'mouseWheel', get_template_directory_uri() . '/js/jquery.mousewheel.min.js', array( 'jquery' ), '1.0', true );

// Loads product scroll touch JavaScript file.
wp_enqueue_script( 'kinetic', get_template_directory_uri() . '/js/jquery.kinetic.min.js', array( 'jquery' ), '1.0', true );

// Loads Product smooth scroll JavaScript file.
wp_enqueue_script( 'smoothDivScroll', get_template_directory_uri() . '/js/jquery.smoothdivscroll-1.3-min.js', array( 'jquery' ), '1.3', true );


Step 3 – Create the custom post type

Below is the code we used to create our custom post type but you can read a great article on on the complete guide to custom post types for other perspectives as well:


// Add custom post type

function my_custom_post_product() {
	$labels = array(
		'name'               => _x( 'Products', 'post type general name' ),
		'singular_name'      => _x( 'Product', 'post type singular name' ),
		'add_new'            => _x( 'Add New', 'book' ),
		'add_new_item'       => __( 'Add New Product' ),
		'edit_item'          => __( 'Edit Product' ),
		'new_item'           => __( 'New Product' ),
		'all_items'          => __( 'All Products' ),
		'view_item'          => __( 'View Product' ),
		'search_items'       => __( 'Search Products' ),
		'not_found'          => __( 'No products found' ),
		'not_found_in_trash' => __( 'No products found in the Trash' ),
		'parent_item_colon'  => '',
		'menu_name'          => 'Products',

		$slugname = 'products';
		$slugname = 'productos';

	$args = array(
		'labels'        => $labels,
		'description'   => 'Holds our products and product specific data',
		'public'        => true,
		//'rewrite' 		=> array( 'slug' => 'products', 'with_front' => false ),
		'menu_icon' => 'dashicons-cart',
		'menu_position' => 5,
		'supports'      => array( 'title', 'editor', 'thumbnail', 'excerpt', 'comments' ),
		'has_archive'   => true,

	register_post_type( 'product', $args );
add_action( 'init', 'my_custom_post_product' );

// Add custom post type messages

function my_updated_messages( $messages ) {
	global $post, $post_ID;
	$messages['product'] = array(
		0 => '',
		1 => sprintf( __('Product updated. <a href="%s">View product</a>'), esc_url( get_permalink($post_ID) ) ),
		2 => __('Custom field updated.'),
		3 => __('Custom field deleted.'),
		4 => __('Product updated.'),
		5 => isset($_GET['revision']) ? sprintf( __('Product restored to revision from %s'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
		6 => sprintf( __('Product published. <a href="%s">View product</a>'), esc_url( get_permalink($post_ID) ) ),
		7 => __('Product saved.'),
		8 => sprintf( __('Product submitted. <a target="_blank" href="%s">Preview product</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
		9 => sprintf( __('Product scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview product</a>'), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
		10 => sprintf( __('Product draft updated. <a target="_blank" href="%s">Preview product</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
	return $messages;
add_filter( 'post_updated_messages', 'my_updated_messages' );

// Add contextual help for custom post type

function my_contextual_help( $contextual_help, $screen_id, $screen ) {
	if ( 'product' == $screen->id ) {

		$contextual_help = '<h3>Products</h3>
		<p>Products show the details of the items that we sell on the website. You can see a list of them on this page in reverse chronological order - the latest one we added is first.</p>
		<p>You can view/edit the details of each product by clicking on its name, or you can perform bulk actions using the dropdown menu and selecting multiple items.</p>';

	} elseif ( 'edit-product' == $screen->id ) {

		$contextual_help = '<h3>Editing products</h3>
		<p>This page allows you to view/modify product details. Please make sure to fill out the available boxes with the appropriate details (product image, price, brand) and <strong>not</strong> add these details to the product description.</p>';

	return $contextual_help;
add_action( 'contextual_help', 'my_contextual_help', 10, 3 );

// Add custom product categories

function my_taxonomies_product() {
	$labels = array(
		'name'              => _x( 'Product Families', 'taxonomy general name' ),
		'singular_name'     => _x( 'Product Family', 'taxonomy singular name' ),
		'search_items'      => __( 'Search Product Families' ),
		'all_items'         => __( 'All Product Families' ),
		'parent_item'       => __( 'Parent Product Family' ),
		'parent_item_colon' => __( 'Parent Product Family:' ),
		'edit_item'         => __( 'Edit Product Family' ),
		'update_item'       => __( 'Update Product Family' ),
		'add_new_item'      => __( 'Add New Product Family' ),
		'new_item_name'     => __( 'New Product Category' ),
		'menu_name'         => __( 'Product Families' ),
	$args = array(
		'labels' => $labels,
		'hierarchical' => true,
	register_taxonomy( 'product_category', 'product', $args );
add_action( 'init', 'my_taxonomies_product', 0 );

Once your post type is added you should see it in your WordPress admin as shown in the screen below.



Step 4 – Create the shortcode

First you need to create a shortcode file if you don’t already have one. To include your shortcodes file you need to add include ‘shortcodes.php’; to your functions.php file.

Now that you have that set up in your shortcodes.php file you will add the following code.


// create shortcode to list all products
function product_listing_shortcode( $atts ) {
    $query = new WP_Query( array(
        'post_type' => 'product',
        'posts_per_page' => -1,
        'order' => 'ASC',
        'orderby' => 'title',
    ) );
    if ( $query->have_posts() ) { ?>
        <ul id="makeMeScrollable" class="product-scroller">
            <?php while ( $query->have_posts() ) : $query->the_post(); ?>

            <li id="post-<?php the_ID(); ?>">
				<?php if ( has_post_thumbnail()) { ?>
                    <a href="<?php the_permalink(); ?>" class="product-img-link" title="<?php the_title_attribute(); ?>" >
                        <?php the_post_thumbnail('full'); ?>
                <?php } else { ?>
                	 <a href="<?php the_permalink(); ?>" class="product-img-link" title="<?php the_title_attribute(); ?>" >
                     	 <img src="<?php echo get_template_directory_uri(); ?>/images/default-prod-thumb-img.jpg" alt="default image" title="<?php the_title_attribute(); ?>" />
                <?php } ?>

                <a href="<?php the_permalink(); ?>">
                    <div class="product-preview">
                        <h5 class="product-title"><?php the_title(); ?></h5>
                        <div class="product-desc"><?php echo short_excerpt(); ?></div>
                        <span class="btn-learn-more">Learn More</span>
            <?php endwhile;
            wp_reset_postdata(); ?>
    <?php $myvariable = ob_get_clean();
    return $myvariable;
add_shortcode( 'list-products', 'product_listing_shortcode' );


Another important step before testing the code set up so far is adding the short_excerpt function to trim the length of the excerpt properly. In your functions.php file add the code below and this will make echo short_excerpt(); work in the shortcode.

function short_excerpt(){
	$excerpt = get_the_excerpt();
	$excerpt = preg_replace(" (\[.*?\])",'',$excerpt);
	$excerpt = strip_shortcodes($excerpt);
	$excerpt = strip_tags($excerpt);
	$excerpt = substr($excerpt, 0, 105);
	$excerpt = substr($excerpt, 0, strripos($excerpt, " "));
	$excerpt = trim(preg_replace( '/\s+/', ' ', $excerpt));
	$excerpt = $excerpt.'...';
	return $excerpt;

Now you can add your shortcode [list-products] to any page or post.



Step 5 – Adding the CSS

Now we need to add the CSS to make everything look good. The following CSS will give you a finished product that looks like the screen below.


#makeMeScrollable {
	height: 330px;
	position: relative;

div.scrollWrapper {
	position: relative;
	overflow: hidden;
	width: 100%;
	height: 100%;

div.scrollableArea {
	position: relative;
	width: auto;
	height: 100%;

div.scrollingHotSpotRight {
    border: 2px solid #fff;
	-webkit-border-radius: 100%;
	-moz-border-radius: 100%;
	-ms-border-radius: 100%;
	-o-border-radius: 100%;
	border-radius: 100%;
	color: #FFFFFF;
	font-size: 34px;
	height: 85px;
	line-height: 93px;
	text-align: center;
	width: 85px;
	position: absolute;
	z-index: 200;
	margin-top: -40px;
	cursor: pointer;
	-webkit-transition:all 0.3s ease-in-out 0s;
	-moz-transition:all 0.3s ease-in-out 0s;
	-ms-transition:all 0.3s ease-in-out 0s;
	-o-transition:all 0.3s ease-in-out 0s;
	transition:all 0.3s ease-in-out 0s;

div.scrollingHotSpotLeft {
    background:url(images/arrow-left.png) no-repeat scroll center center;
	left: 20px;

div.scrollingHotSpotRight {
    background:url(images/arrow-right.png) no-repeat scroll center center;
	right: 20px;

div.scrollingHotSpotRight:hover {
	background:rgba(255,255,255, 0.25);

div.scrollingHotSpotLeftVisible {
	background-repeat: no-repeat;
	-webkit-opacity: 1;
	-moz-opacity: 1;
	-ms-opacity: 1;
	-o-opacity: 1;
	opacity: 1;
	zoom: 1; /* Trigger "hasLayout" in Internet Explorer 6 or older versions */

div.scrollingHotSpotRightVisible {
	-webkit-opacity: 1;
	-moz-opacity: 1;
	-ms-opacity: 1;
	-o-opacity: 1;
	opacity: 1;
	zoom: 1;

.product-scroller {
	margin: 0;
	padding: 0;

.product-scroller li.product {
	position: relative;

.product-scroller li.product a.product-img-link {
	display: block;

.product-scroller li.product a.product-img-link img {
	max-width: 333px;
	-webkit-transition:all 0.3s ease-in-out 0s;
	-moz-transition:all 0.3s ease-in-out 0s;
	-ms-transition:all 0.3s ease-in-out 0s;
	-o-transition:all 0.3s ease-in-out 0s;
	transition:all 0.3s ease-in-out 0s;

.product-scroller li.product:hover a.product-img-link img {

.product-scroller li.product .product-preview {
	background:rgba(0,0,0, 0.5);
	-webkit-transition:all 0.3s ease-in-out 0s;
	-moz-transition:all 0.3s ease-in-out 0s;
	-ms-transition:all 0.3s ease-in-out 0s;
	-o-transition:all 0.3s ease-in-out 0s;
	transition:all 0.3s ease-in-out 0s;

.product-scroller li.product:hover .product-preview {
    background:rgba(0,0,0, 0.65);

.product-scroller li.product .product-preview h5 {
     margin-bottom: 5px;

.product-scroller li.product .product-preview .product-desc {
    line-height: 22px;

.product-scroller li.product .product-preview .product-desc p {

.product-scroller li.product .product-preview .btn-learn-more {
    clear: both;
    display: block;
    float: right;
    height: 45px;
    line-height: 45px;
    padding: 0px;

.product-scroller li.product a {


Step 6 – Activate the code

Now you need to activate the scripts. We run it in our custom.js file that we enqueue in the functions.php file. You can also add this js directly to the page template of whichever page you are going to add your shortcode.

     autoScrollingMode: "onStart",
     touchScrolling: true,
     autoScrollingInterval: 30


Other Important Things To Pay Attention To

  • The shortcode is built to pull the featured image from the custom post type. You must add a featured image in order for one to display other wise it will show the a default image.
  • Create a default image that will show up if you do not add a featured image. In our example we named ours default-prod-thumb-img.jpg
  • The image size we are using is 333px x 333px. If you are going to use another image size then you must adjust the CSS to compensate for this.

That’s It. Enjoy!

Hope you find this tutorial useful. If you have any questions feel free to let us know in the comments below.

  • Tomás Canale

    Hi Justin, Thank you for this amazing tutorial!

    I’m did it all but it’s not working on my theme. It might be a problem when I activate the jQuery code. Where does this code goes?

    autoScrollingMode: “onStart”,
    touchScrolling: true,
    autoScrollingInterval: 30



    • Tomás Canale

      It is working know! I think putting the Activation Code under the footer made it work.

      Now I have another Issue with the CSS. It’s overriding the Child style.css. Do you think could be a problem with the IDs and Classes?

      • Hey Tomas, glad you were able to get it working. The script to activate needs to run after all the other scripts for the smooth div scroll and jQuery are loaded, which is why putting it in the footer got it it to work. As far as the CSS issue goes, if you want to send me the URL of the site you are working on I can take a look and see what the issue is.