ACF Swiper Slider in WordPress - createIT
Get a free advice now!

    Pick the topic
    Developer OutsourcingWeb developingApp developingDigital MarketingeCommerce systemseEntertainment systems

    Thank you for your message. It has been sent.

    ACF Swiper Slider in WordPress

    December 22, 2022
    Last update: August 29, 2024
    6 min read
    184
    0
    0
    ACF Swiper Slider in WordPress

    CHALLENGE: to add a WordPress image slider with captions and admin edit interface

    SOLUTION: to implement a Swiper touch slider on frontend and ACF custom fields on backend

    Adding a Carousel/Slider with images in WordPress is a common solution to highlight the most popular contents to website visitors. There are sophisticated ready-to-use slider plugins that include a lot of features. However, sometimes they are difficult to configure and performance is not quite as good as expected. Let’s create a simple WordPress slider from scratch with ACF slider. It will be displayed on the homepage.

    ACF fields

    The backend part will be handled by the Advanced Custom Fields plugin. In Wp-admin / Custom Fields / Fields Groups, we’re going to add a new group called ‘Home’ with “Flexible Content” defined. We will configure the fields via the admin panel interface:

    Admin panel interface

    We will keep the fields definition in a PHP file: Wp-admin / Custom Fields / Tools / Generate PHP. After adding the code below to functions.php, we can deactivate the ‘Field Group’ defined in the admin panel before (Field Group Settings / Active – No). WordPress will read fields’ definitions directly from PHP:

    <?php
    // functions.php
    if( function_exists('acf_add_local_field_group') ):
        acf_add_local_field_group(array(
            'key' => 'group_611e88dd093c7',
            'title' => 'Home',
            'fields' => array(
                array(
                    'key' => 'field_611f63c119aa4',
                    'label' => 'slider',
                    'name' => 'slider',
                    'type' => 'flexible_content',
                    'instructions' => '',
                    'required' => 0,
                    'conditional_logic' => 0,
                    'wrapper' => array(
                        'width' => '',
                        'class' => '',
                        'id' => '',
                    ),
                    'layouts' => array(
                        'layout_611e891769e8f' => array(
                            'key' => 'layout_611e891769e8f',
                            'name' => 'slide',
                            'label' => 'Slide',
                            'display' => 'block',
                            'sub_fields' => array(
                                array(
                                    'key' => 'field_611f641c19aa5',
                                    'label' => 'link',
                                    'name' => 'link',
                                    'type' => 'text',
                                    'instructions' => '',
                                    'required' => 0,
                                    'conditional_logic' => 0,
                                    'wrapper' => array(
                                        'width' => '',
                                        'class' => '',
                                        'id' => '',
                                    ),
                                    'default_value' => '',
                                    'placeholder' => '',
                                    'prepend' => '',
                                    'append' => '',
                                    'maxlength' => '',
                                ),
                                array(
                                    'key' => 'field_611f643219aa6',
                                    'label' => 'image',
                                    'name' => 'image',
                                    'type' => 'image',
                                    'instructions' => '',
                                    'required' => 0,
                                    'conditional_logic' => 0,
                                    'wrapper' => array(
                                        'width' => '',
                                        'class' => '',
                                        'id' => '',
                                    ),
                                    'return_format' => 'id',
                                    'preview_size' => 'full',
                                    'library' => 'all',
                                    'min_width' => '',
                                    'min_height' => '',
                                    'min_size' => '',
                                    'max_width' => '',
                                    'max_height' => '',
                                    'max_size' => '',
                                    'mime_types' => '',
                                ),
                                array(
                                    'key' => 'field_611f644319aa7',
                                    'label' => 'mobile image',
                                    'name' => 'mobile_image',
                                    'type' => 'image',
                                    'instructions' => '',
                                    'required' => 0,
                                    'conditional_logic' => 0,
                                    'wrapper' => array(
                                        'width' => '',
                                        'class' => '',
                                        'id' => '',
                                    ),
                                    'return_format' => 'id',
                                    'preview_size' => 'full',
                                    'library' => 'all',
                                    'min_width' => '',
                                    'min_height' => '',
                                    'min_size' => '',
                                    'max_width' => '',
                                    'max_height' => '',
                                    'max_size' => '',
                                    'mime_types' => '',
                                ),
                                array(
                                    'key' => 'field_611f647919aa8',
                                    'label' => 'description',
                                    'name' => 'description',
                                    'type' => 'text',
                                    'instructions' => '',
                                    'required' => 0,
                                    'conditional_logic' => 0,
                                    'wrapper' => array(
                                        'width' => '',
                                        'class' => '',
                                        'id' => '',
                                    ),
                                    'default_value' => '',
                                    'placeholder' => '',
                                    'prepend' => '',
                                    'append' => '',
                                    'maxlength' => '',
                                ),
                            ),
                            'min' => '',
                            'max' => '',
                        ),
                    ),
                    'button_label' => 'Add slide',
                    'min' => '',
                    'max' => '',
                ),
            ),
            'location' => array(
                array(
                    array(
                        'param' => 'page_template',
                        'operator' => '==',
                        'value' => 'tpl-homepage.php',
                    ),
                ),
            ),
            'menu_order' => 0,
            'position' => 'normal',
            'style' => 'default',
            'label_placement' => 'top',
            'instruction_placement' => 'label',
            'hide_on_screen' => '',
            'active' => true,
            'description' => '',
        ));
    endif;

    Enqueuing slider assets

    Swiper is a touch slider plugin written in javascript. With over 20 000 stars on GitHub, it’s a popular open-source solution for displaying images as carousel. Let’s enqueue CSS and JS files that are required for the slider to work. The compiled source code can be downloaded from: https://unpkg.com/swiper@7/

    // functions.php
    add_action( 'wp_enqueue_scripts', 'ct_slider_scripts', 10 );
    function ct_slider_scripts() {
        $assets_version = '3';
        if (is_page_template('tpl-homepage.php')) {
            wp_enqueue_style( 'ct-swiper-css', get_template_directory_uri() . '/assets/lib/swiper/swiper-bundle.min.css', '', $assets_version );
            wp_enqueue_script( 'ct-swiper-js', get_template_directory_uri() . '/assets/lib/swiper/swiper-bundle.min.js', array(), $assets_version, true );
        }
    }

    Initialize JS slider

    Plugin initialization should be added to the custom .js file. We will have two sliders working as one: the main slider with images and a thumb slider with text captions.

    // main.js
    // initialize slider
    if(document.getElementById("js-main-slider")) {
        var galleryThumbs = new Swiper('#js-main-slider-thumbs', {
            slidesPerView: 1.5,
            watchSlidesVisibility: true,
            watchSlidesProgress: true,
            spaceBetween: 0,
            breakpoints: {
                768: {
                    slidesPerView: 3
                },
                1200: {
                    slidesPerView: 5
                },
                1024: {
                    slidesPerView: 5
                }
            }
        });
        var galleryTop = new Swiper('#js-main-slider', {
            spaceBetween: 0,
            preloadImages: false,
            lazy: true,
            thumbs: {
                swiper: galleryThumbs
            },
            autoplay: {
                delay: 15000,
                disableOnInteraction: true
            },
            breakpoints: {
                320: {
                    pagination: {
                        el: ".swiper-pagination",
                        clickable: true
                    }
                }
            }
        });
    }

    Adding Home Template

    We need to fetch ACF custom fields and generate an HTML markup for the slider. We will prepare a WordPress PHP template called ‘Home’, which will use the get_template_part() to render content partially.

    <?php
    /**
     * // tpl-homepage.php
     * Template name: Home
     */
    get_header(); ?>
        <div id="primary" class="content-area">
            <main id="main" class="site-main my-1 my-lg-4 py-3" role="main">
                <div class="entry-content">
                    <?php get_template_part( 'template-parts/home/main-slider' ); ?>
                </div>
            </main><!-- #main -->
        </div><!-- #primary -->
    <?php
    get_footer();

    The ACF function have_rows() iterates through flexible content elements and fetches data from the database. The lazy loading option enabled will make slider loading faster on frontend.

    <?php
    /**
     * /template-parts/home/main-slider.php
     */
    if( have_rows('slider') ):
        $section1 = array();
        while ( have_rows('slider') ) : the_row();
            if( get_row_layout() == 'slide' ):
                $item = new stdClass();
                $item->link = get_sub_field('link');
                $item->image = wp_get_attachment_image_src( get_sub_field('image'), 'full' );
                $item->mobile_image = wp_get_attachment_image_src( get_sub_field('mobile_image'), 'full' );
                $item->description = get_sub_field('description');
                $section1[] = $item;
            endif;
        endwhile;
    endif;
    ?>
    <div class="slider-main">
        <div class="swiper-container slider-main__slides gallery-top" data-role="carousel" id="js-main-slider">
            <div class="swiper-wrapper">
                <?php foreach($section1 as $item): ?>
                    <div class="swiper-slide slider-main__slide"><a href="<?php echo $item->link; ?>">
                            <picture class="slider-main__picture">
                                <source data-srcset="<?php echo $item->mobile_image[0]; ?>"
                                        media="(max-width: 768px)" type="image/jpeg">
                                <img class="slider-main__img swiper-lazy img-fluid"
                                     data-src="<?php echo $item->image[0]; ?>"
                                     alt="<?php echo $item->description; ?>" /></picture>
                            <div class="swiper-lazy-preloader"></div>
                        </a></div>
                <?php endforeach; ?>
            </div>
            <div class="swiper-pagination"></div>
        </div>
        <div class="swiper-container slider-main__nav gallery-thumbs" data-role="carousel-nav" id="js-main-slider-thumbs">
            <div class="swiper-wrapper slider-main__thumbs-wrapper">
                <?php foreach($section1 as $item): ?>
                    <div class="swiper-slide slider-main__nav-button"><?php echo $item->description; ?></div>
                <?php endforeach; ?>
            </div>
        </div>
    </div>

    Optimizing the slider

    Currently, fetching images from the database is not optimal. For every loop iteration, we’re querying the database 2 times to get image paths. Backend performance can be improved by fetching all images in one query. The WPDB method can be used to fetch all elements at once. With 5 sliders added, we will save 9 database queries. Here is the improved code with better performance:

    <?php
    /**
     * /template-parts/home/main-slider.php
     */
    if( have_rows('slider') ):
        $section1 = array();
        $images_ids = array();
        while ( have_rows('slider') ) : the_row();
            if( get_row_layout() == 'slide' ):
                $item = new stdClass();
                $item->link = get_sub_field('link');
                $item->image_id = get_sub_field('image');
                $item->mobile_image_id = get_sub_field('mobile_image');
                $images_ids[] = $item->image_id;
                $images_ids[] = $item->mobile_image_id;
                $item->description = get_sub_field('description');
                $section1[] = $item;
            endif;
        endwhile;
        global $wpdb;
        $qstr =
            "SELECT post_id, meta_value
            FROM $wpdb->postmeta
            WHERE post_id IN  (" . implode(',', $images_ids) . ")". ' AND meta_key = "_wp_attached_file"';
        $images_src = $wpdb->get_results( $qstr, 'OBJECT_K' );
    endif;
    ?>
    <div class="slider-main">
        <div class="swiper-container slider-main__slides gallery-top" data-role="carousel" id="js-main-slider">
            <div class="swiper-wrapper">
                <?php
                $uploads = wp_upload_dir();
                foreach($section1 as $item): ?>
                    <div class="swiper-slide slider-main__slide"><a href="<?php echo $item->link; ?>">
                            <picture class="slider-main__picture">
                                <source data-srcset="<?php echo $uploads['baseurl'] . '/' . $images_src[$item->mobile_image_id]->meta_value; ?>"
                                        media="(max-width: 767px)" type="image/jpeg">
                                <img class="slider-main__img swiper-lazy img-fluid"
                                     data-src="<?php echo $uploads['baseurl'] . '/' . $images_src[$item->image_id]->meta_value; ?>"
                                     alt="<?php echo $item->description; ?>" /></picture>
                            <div class="swiper-lazy-preloader"></div>
                        </a></div>
                <?php endforeach; ?>
            </div>
            <div class="swiper-pagination"></div>
        </div>
        <div class="swiper-container slider-main__nav gallery-thumbs" data-role="carousel-nav" id="js-main-slider-thumbs">
            <div class="swiper-wrapper slider-main__thumbs-wrapper">
                <?php foreach($section1 as $item): ?>
                    <div class="swiper-slide slider-main__nav-button"><?php echo $item->description; ?></div>
                <?php endforeach; ?>
            </div>
        </div>
    </div>

    The last improvements include CSS style adjustments. We have a SASS partial file that will add some look to the slider. Slider pagination bullet nav is only displayed on the mobile version.

    // /assets/scss/elements/_home-slider.scss
    .slider-main__nav {
      display: none;
    }
    @media (min-width: 768px) {
      .slider-main__nav {
        display: block;
      }
      .slider-main__nav-button {
        display: flex;
        align-items: center;
        justify-content: center;
        text-align: center;
        padding: 12px 22px;
        min-height: 75px;
        width: auto;
        cursor: pointer;
        box-sizing: border-box;
        background: #fff;
        color:#333;
        border-top:3px solid transparent;
        &.swiper-slide-thumb-active{
          border-color:blue;
          color:#000;
        }
      }
      .swiper-pagination {
        display: none;
      }
    }
    .swiper-lazy-preloader {
      margin-top:145px;
    }
    .slider-main__img {
      width: 100%;
      display: none;
    }
    .swiper-lazy-loaded {
      display:block;
      margin:0 auto;
    }
    .swiper-pagination-bullet {
      width: 14px;
      height: 14px;
      background: transparent;
      opacity: .5;
      border: 1px solid #fff;
    }
    .swiper-pagination-bullet-active {
      background:#fff;
    }

    Backend edit mode

    The custom meta fields defined in PHP will be displayed on ‘Edit page’ view with the Template set as ‘Home’ ( Edit Page / Page Attributes / Template → Home ). The recommended images sizes are: 1366×454 (desktop), 480×680 (mobile).

    Admin panel window

    Slider preview

    Thinking about performance, we will lazy-load images using the HTML5 picture tag and the srcset data attribute. We also use different images for the mobile version ( < 768px ). Here is a preview of the homepage WordPress slider implemented using SwiperJS.

    Preview
    Preview

    That’s it for today’s tutorial. We are a web development company with experience, that can help you with any software or custom web application development project.

    Do you need someone to implement this solution for you? Check out our specialists for hire in the outsourcing section.

    Support – Tips and Tricks
    All tips in one place, and the database keeps growing. Stay up to date and optimize your work!

    Contact us