
How to Create a Custom Team Slider in WordPress
Introduction
Hello friends,
In this tutorial, I will show you how to create a Custom Team Slider in WordPress through a custom WordPress plugin.
In this plugin, we will build a custom team slider with carousel slider for team members and add a settings submenu under the Team menu. From this settings page, you can configure the slider options like autoplay, loop, navigation arrows, dots, and speed.
We will also add a copy button for the shortcode so you can easily paste it anywhere in WordPress to display the team slider.
This plugin also supports team member details such as role/designation and social media links (Facebook, Twitter, LinkedIn).
Let’s get started.
1. Folder Structure
We first need the plugin folder and main file inside the plugins
directory.
-- plugins (folder) -- custom-team (folder) -- custom-team.php (file)
After creating this folder and file, we add the plugin header details:
/* Plugin Name: Custom Team Members with Slider Description: Manage Team members with Owl Carousel slider, social icons, and settings. Shortcode: [team_slider] Version: 1.1 Author: Your Name */
2. Steps for the Plugin : Custom Team Slider
We will build this plugin step by step:
- Register Team CPT + thumbnails
- Add Metabox: Role + Social Links
- Register Front-end assets (Owl Carousel, FontAwesome, CSS/JS)
- Create Shortcode:
[team_slider]
- Add Admin submenu: Slider Settings
3. Register Team CPT + Thumbnails
We will create a custom post type called Team.
This allows you to manage team members in the WordPress admin dashboard. You can add, edit, update, and delete team members. Each member supports thumbnails (profile pictures).
// ===================================================== // 1) Register Team CPT + thumbnails // ===================================================== function ct_register_team_cpt() { $labels = array( 'name' => 'Team', 'singular_name' => 'Team Member', 'menu_name' => 'Our Team', 'name_admin_bar' => 'Team Member', 'add_new' => 'Add New', 'add_new_item' => 'Add New Team Member', 'new_item' => 'New Team Member', 'edit_item' => 'Edit Team Member', 'view_item' => 'View Team Member', 'all_items' => 'All Team Members', 'search_items' => 'Search Team Members', ); $args = array( 'labels' => $labels, 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'menu_icon' => 'dashicons-groups', 'supports' => array('title', 'editor', 'thumbnail'), ); register_post_type('team', $args); } add_action('init', 'ct_register_team_cpt'); function ct_enable_team_thumbs() { add_theme_support('post-thumbnails', array('team')); } add_action('after_setup_theme', 'ct_enable_team_thumbs');
4. Metabox: Role + Social Links
Next, we add a custom metabox for each team member.
This includes:
- Role / Designation
- Facebook URL
- Twitter URL
- LinkedIn URL
These details make your team section more professional with proper designations and social links.
// ===================================================== // 2) Metabox: Role + Social Links // ===================================================== function ct_add_team_metabox() { add_meta_box( 'ct_team_details', 'Team Member Details', 'ct_team_metabox_html', 'team', 'normal', 'default' ); } add_action('add_meta_boxes', 'ct_add_team_metabox'); function ct_team_metabox_html($post) { wp_nonce_field('ct_team_save_meta', 'ct_team_nonce'); $role = get_post_meta($post->ID, '_team_role', true); $fb = get_post_meta($post->ID, '_team_fb', true); $twitter = get_post_meta($post->ID, '_team_twitter', true); $linkedin= get_post_meta($post->ID, '_team_linkedin', true); ?> <p> <label><strong>Role / Designation</strong></label><br> <input type="text" name="team_role" value="<?php echo esc_attr($role); ?>" style="width:100%"> </p> <p> <label><strong>Facebook URL</strong></label><br> <input type="url" name="team_fb" value="<?php echo esc_url($fb); ?>" style="width:100%"> </p> <p> <label><strong>Twitter URL</strong></label><br> <input type="url" name="team_twitter" value="<?php echo esc_url($twitter); ?>" style="width:100%"> </p> <p> <label><strong>LinkedIn URL</strong></label><br> <input type="url" name="team_linkedin" value="<?php echo esc_url($linkedin); ?>" style="width:100%"> </p> <?php } function ct_save_team_meta($post_id) { if (!isset($_POST['ct_team_nonce']) || !wp_verify_nonce($_POST['ct_team_nonce'], 'ct_team_save_meta')) { return; } if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return; if (isset($_POST['post_type']) && 'team' === $_POST['post_type']) { if (!current_user_can('edit_post', $post_id)) return; } else { return; } $fields = [ 'team_role' => '_team_role', 'team_fb' => '_team_fb', 'team_twitter' => '_team_twitter', 'team_linkedin'=> '_team_linkedin', ]; foreach ($fields as $form => $meta) { if (isset($_POST[$form])) { update_post_meta($post_id, $meta, sanitize_text_field($_POST[$form])); } } } add_action('save_post', 'ct_save_team_meta');
5. Front-end Assets
We need to load the front-end CSS and JS files required for the team slider.
For this, we register:
- Owl Carousel (for slider functionality)
- Font Awesome (for social icons)
- Custom inline CSS for card styling
This ensures the team slider looks modern and responsive.
// ===================================================== // 3) Front-end assets (Owl Carousel + FontAwesome + styles) // ===================================================== function ct_enqueue_team_assets() { // Owl Carousel wp_enqueue_style('owl-carousel', 'https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.carousel.min.css', array(), '2.3.4'); wp_enqueue_style('owl-theme', 'https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.theme.default.min.css', array('owl-carousel'), '2.3.4'); wp_enqueue_script('owl-carousel', 'https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.min.js', array('jquery'), '2.3.4', true); // Font Awesome wp_enqueue_style('font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css', array(), '6.5.1'); $css = ' .ct-team-card { background:#fff; border:1px solid #eee; border-radius:12px; padding:24px; box-shadow:0 4px 12px rgba(0,0,0,0.06); text-align:center; } .ct-team-card .ct-photo { border-radius:50%; object-fit:cover; display:block; margin:0 auto 12px; } .ct-team-card .ct-name { font-weight:700; font-size:16px; margin:6px 0 0; } .ct-team-card .ct-role { color:#6c757d; font-size:13px; margin-bottom:10px; } .ct-team-card .ct-text { font-size:14px; color:#444; margin:8px 0; } .ct-team-card .ct-social a { margin:0 6px; color:#0073aa; font-size:18px; } .ct-team-card .ct-social a:hover { color:#111; } '; wp_add_inline_style('owl-carousel', $css); } add_action('wp_enqueue_scripts', 'ct_enqueue_team_assets');
6. Shortcode: [team_slider]
We will create the shortcode [team_slider]
.
By using this shortcode, you can display the team members slider anywhere on your site (pages, posts, or widgets). Simply copy and paste the shortcode where you want the team section to appear.
The shortcode will display:
- Team member image (or avatar fallback)
- Name and role
- Bio/description
- Social media icons
// ===================================================== // 4) Shortcode: [team_slider] // ===================================================== function ct_team_slider_shortcode() { $defaults = array( 'items' => 3, 'autoplay' => true, 'loop' => true, 'speed' => 3000, 'nav' => true, 'dots' => true, 'image_size' => 120, ); $settings = wp_parse_args(get_option('ct_team_slider_settings', array()), $defaults); $q = new WP_Query(array( 'post_type' => 'team', 'posts_per_page' => -1, 'post_status' => 'publish', )); // Dummy team members if no posts exist $dummy_team = array( array( 'name' => 'Alice Johnson', 'role' => 'Project Manager', 'text' => 'Alice is responsible for managing projects and ensuring smooth delivery.', 'fb' => '#', 'twitter' => '#', 'linkedin'=> '#', 'image' => plugins_url('images/team1.png', __FILE__), ), array( 'name' => 'Robert Williams', 'role' => 'Lead Developer', 'text' => 'Robert specializes in backend development and WordPress customization.', 'fb' => '#', 'twitter' => '#', 'linkedin'=> '#', 'image' => plugins_url('images/team2.png', __FILE__), ), array( 'name' => 'Sophia Brown', 'role' => 'UI/UX Designer', 'text' => 'Sophia designs user-friendly and attractive web interfaces.', 'fb' => '#', 'twitter' => '#', 'linkedin'=> '#', 'image' => plugins_url('images/team3.png', __FILE__), ), ); ob_start(); ?> <div class="owl-carousel ct-team-slider"> <?php if ($q->have_posts()): while ($q->have_posts()): $q->the_post(); $img = get_the_post_thumbnail_url(get_the_ID(), 'thumbnail'); if (!$img) { $img = 'https://via.placeholder.com/' . intval($settings['image_size']); } $role = get_post_meta(get_the_ID(), '_team_role', true); $fb = get_post_meta(get_the_ID(), '_team_fb', true); $twitter = get_post_meta(get_the_ID(), '_team_twitter', true); $linkedin= get_post_meta(get_the_ID(), '_team_linkedin', true); ?> <div class="ct-team-card"> <img class="ct-photo" src="<?php echo esc_url($img); ?>" alt="<?php echo esc_attr(get_the_title()); ?>" style="width:<?php echo intval($settings['image_size']); ?>px;height:<?php echo intval($settings['image_size']); ?>px;object-fit:cover;border-radius: 50%!important;"> <div class="ct-name"><?php echo esc_html(get_the_title()); ?></div> <?php if ($role): ?> <div class="ct-role"><?php echo esc_html($role); ?></div> <?php endif; ?> <div class="ct-text"><?php echo wp_kses_post(get_the_content()); ?></div> <div class="ct-social"> <?php if ($fb): ?><a href="<?php echo esc_url($fb); ?>" target="_blank"><i class="fab fa-facebook-f"></i></a><?php endif; ?> <?php if ($twitter): ?><a href="<?php echo esc_url($twitter); ?>" target="_blank"><i class="fab fa-twitter"></i></a><?php endif; ?> <?php if ($linkedin): ?><a href="<?php echo esc_url($linkedin); ?>" target="_blank"><i class="fab fa-linkedin-in"></i></a><?php endif; ?> </div> </div> <?php endwhile; wp_reset_postdata(); else: foreach ($dummy_team as $d): ?> <div class="ct-team-card"> <img class="ct-photo" src="<?php echo esc_url($d['image']); ?>" alt="<?php echo esc_attr($d['name']); ?>" style="width:<?php echo intval($settings['image_size']); ?>px;height:<?php echo intval($settings['image_size']); ?>px;object-fit:cover;border-radius: 50%!important;"> <div class="ct-name"><?php echo esc_html($d['name']); ?></div> <div class="ct-role"><?php echo esc_html($d['role']); ?></div> <div class="ct-text"><?php echo esc_html($d['text']); ?></div> <div class="ct-social"> <?php if ($d['fb']): ?><a href="<?php echo esc_url($d['fb']); ?>" target="_blank"><i class="fab fa-facebook-f"></i></a><?php endif; ?> <?php if ($d['twitter']): ?><a href="<?php echo esc_url($d['twitter']); ?>" target="_blank"><i class="fab fa-twitter"></i></a><?php endif; ?> <?php if ($d['linkedin']): ?><a href="<?php echo esc_url($d['linkedin']); ?>" target="_blank"><i class="fab fa-linkedin-in"></i></a><?php endif; ?> </div> </div> <?php endforeach; endif; ?> </div> <script> jQuery(document).ready(function($){ $(".ct-team-slider").owlCarousel({ items: <?php echo intval($settings['items']); ?>, autoplay: <?php echo !empty($settings['autoplay']) ? 'true' : 'false'; ?>, loop: <?php echo !empty($settings['loop']) ? 'true' : 'false'; ?>, nav: <?php echo !empty($settings['nav']) ? 'true' : 'false'; ?>, dots: <?php echo !empty($settings['dots']) ? 'true' : 'false'; ?>, autoplayTimeout: <?php echo intval($settings['speed']); ?>, margin: 20, responsive:{ 0:{items:1}, 768:{items:2}, 1024:{items:<?php echo intval($settings['items']); ?>} } }); }); </script> <?php return ob_get_clean(); } add_shortcode('team_slider', 'ct_team_slider_shortcode');
7. Admin Submenu: Slider Settings
We will add a Slider Settings submenu under the Team menu in WordPress.
From this settings page, you can configure options such as:
- Number of items visible
- Autoplay on/off
- Loop on/off
- Show/hide navigation arrows
- Show/hide dots
- Autoplay speed (in milliseconds)
- Image size (px)
This gives you full control over how the slider behaves.
We also provide a copy button for the [team_slider]
shortcode so you can quickly use it anywhere.
// ===================================================== // 5) Admin submenu: Slider Settings // ===================================================== function ct_register_team_slider_settings_page() { add_submenu_page( 'edit.php?post_type=team', 'Slider Settings', 'Slider Settings', 'manage_options', 'ct-team-slider-settings', 'ct_team_slider_settings_page' ); } add_action('admin_menu', 'ct_register_team_slider_settings_page'); function ct_team_slider_settings_page() { if (isset($_POST['save_ct_team_settings'])) { if (!current_user_can('manage_options')) { return; } $settings = array( 'items' => isset($_POST['items']) ? intval($_POST['items']) : 3, 'autoplay' => !empty($_POST['autoplay']), 'loop' => !empty($_POST['loop']), 'speed' => isset($_POST['speed']) ? intval($_POST['speed']) : 3000, 'nav' => !empty($_POST['nav']), 'dots' => !empty($_POST['dots']), 'image_size' => isset($_POST['image_size']) ? max(40, intval($_POST['image_size'])) : 120, ); update_option('ct_team_slider_settings', $settings); echo '<div class="updated"><p>Settings Saved.</p></div>'; } $defaults = array( 'items' => 3, 'autoplay' => true, 'loop' => true, 'speed' => 3000, 'nav' => true, 'dots' => true, 'image_size' => 120, ); $settings = wp_parse_args(get_option('ct_team_slider_settings', array()), $defaults); ?> <div class="wrap"> <h1>Team Slider Settings</h1> <form method="post"> <table class="form-table"> <tr> <th scope="row">Items Visible</th> <td><input type="number" name="items" min="1" max="10" value="<?php echo esc_attr($settings['items']); ?>"></td> </tr> <tr> <th scope="row">Autoplay</th> <td><input type="checkbox" name="autoplay" <?php checked($settings['autoplay'], true); ?>></td> </tr> <tr> <th scope="row">Loop</th> <td><input type="checkbox" name="loop" <?php checked($settings['loop'], true); ?>></td> </tr> <tr> <th scope="row">Show Navigation Arrows</th> <td><input type="checkbox" name="nav" <?php checked($settings['nav'], true); ?>></td> </tr> <tr> <th scope="row">Show Dots</th> <td><input type="checkbox" name="dots" <?php checked($settings['dots'], true); ?>></td> </tr> <tr> <th scope="row">Autoplay Speed (ms)</th> <td><input type="number" name="speed" min="1000" step="100" value="<?php echo esc_attr($settings['speed']); ?>"></td> </tr> <tr> <th scope="row">Image Size (px)</th> <td><input type="number" name="image_size" min="40" max="300" value="<?php echo esc_attr($settings['image_size']); ?>"></td> </tr> </table> <p><input type="submit" name="save_ct_team_settings" class="button-primary" value="Save Settings"></p> </form> <h2>Use this Shortcode</h2> <p> <input type="text" value="[team_slider]" id="ct-team-shortcode" readonly style="width:260px;"> <button type="button" class="button" onclick="navigator.clipboard.writeText(document.getElementById('ct-team-shortcode').value)">Copy</button> </p> </div> <?php }
Conclusion : Custom Team Slider
That’s it! We have created a Custom Team Members Slider Plugin in WordPress that includes:
- A custom post type (CPT) for team members
- Extra fields for role/designation and social links
- Front-end assets (Owl Carousel + FontAwesome)
- A shortcode
[team_slider]
to display the slider anywhere - A settings page to configure slider options
If you want to learn more about WordPress customization, you can check my related posts.
If you need any help, feel free to connect with me — I will be available for you.
Thank you.