CreateIT
CreateIT
BLOG

ACF Swiper Slider in WordPress

WordPress
TAGS: WordPress

ACF Swiper Slider in WordPress

SHARE

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

Advanced Custom Fields

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/[email protected]/

// 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).

WordPress

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.

WordPress slider

WordPress

That’s it for today’s tutorial. Make sure to follow us for other useful tips and guidelines.

Need help?

  • Looking for support from experienced programmers?

  • Need to fix a bug in the code?

  • Want to customize your webste/application?

ADD COMMENT

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

createIT Contact