Get a free advice now!

    Pick the topic

    Developer OutsourcingWeb developingApp developingDigital MarketingeCommerce systemseEntertainment systems

    Thank you for your message. It has been sent.

    Tags

    ACF Swiper Slider in WordPress

    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 project.

    Do you need someone to implement this solution for you? Check out our specialists for hire in the outsourcing section. Are you considering a global project and are uncertain how to proceed? See how we do it.

    Comments
    0 response

    Add comment

    Your email address will not be published. Required fields are marked *

    Popular news

    eCommerce growth – is your business ready?
    • Services
    • Trends

    eCommerce growth – is your business ready?

    April 8, 2024 by createIT
    Digital marketing without third-party cookies – new rules
    • Technology
    • Trends

    Digital marketing without third-party cookies – new rules

    February 21, 2024 by createIT
    eCommerce healthcheck
    • Services
    • Trends

    eCommerce healthcheck

    January 24, 2024 by createIT
    Live Visitor Count in WooCommerce with SSE
    • Dev Tips and Tricks

    Live Visitor Count in WooCommerce with SSE

    December 12, 2023 by createIT
    Calculate shipping costs programmatically in WooCommerce
    • Dev Tips and Tricks

    Calculate shipping costs programmatically in WooCommerce

    December 11, 2023 by createIT
    Designing a cookie consent modal certified by TCF IAB
    • Dev Tips and Tricks

    Designing a cookie consent modal certified by TCF IAB

    December 7, 2023 by createIT
    Understanding the IAB’s Global Vendor List (GVL)
    • Dev Tips and Tricks

    Understanding the IAB’s Global Vendor List (GVL)

    December 6, 2023 by createIT

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

    Contact us