19

I'm using swiper slider on a site and would like to have it disabled if there is only one slide.

Currently with only one slide the pagination appears and you can click that or swipe. Ideally there shouldn't be any interaction if there is only one slide.

My current js is:

  var swiper = new Swiper('.swiper-container', {
    // Optional parameters
    direction: 'horizontal',
    loop: false,
    //autoplay: 6500,
    autoplayDisableOnInteraction: false,

    keyboardControl: true,
    mousewheelControl: true,

    pagination: '.swiper-pagination',
    paginationClickable: true,

  });
Benedikt
  • 608
  • 6
  • 27
CreateSean
  • 1,286
  • 1
  • 21
  • 42

14 Answers14

51

There is an option in Swiper API that might be useful :

watchOverflow (boolean|false)
// When enabled Swiper will be disabled and hide navigation buttons on case there are not enough slides for sliding
Klemart3D
  • 180
  • 9
Flo Develop
  • 655
  • 1
  • 6
  • 9
  • 1
    Thanks a million. Very clean solution to disable swiping. Used it together with zoom `{zoom : true, watchOverflow: true}` to display a picture that can be zoomed but not swiped. Moving around the picture while zoomed in still works. – Patronaut Dec 02 '19 at 03:46
  • 3
    This is the best solution – Konrad Feb 13 '20 at 10:28
  • This option does not work when `effect` is set to `fade` . – roye7777777 Aug 09 '23 at 15:33
13

I was looking for a way to do so too, but since I didn't find any “official” way to disable the swipe and hide the pagers, I decided to improvise a bit.

So in your script, you can add this after your Swiper variable:

JS:

if($(".slider .slide").length == 1) {
    $('.swiper-wrapper').addClass( "disabled" );
    $('.swiper-pagination').addClass( "disabled" );
}

This will add the class disabled to your wrapper and your pagination if there is only one slide in your slider. You can now add some CSS to bypass the Swiper effexts:

CSS:

.swiper-wrapper.disabled {
    transform: translate3d(0px, 0, 0) !important;
}
.swiper-pagination.disabled {
    display: none;
}

Note that this will only work when the loop is set to false (like in your case). If the loop is active, Swiper will add slide duplicates before and after your only slide, making a total of 3 identicals slides. You can then change the length == 1 to length == 3.

Hope this will help!

JoeMecPak
  • 618
  • 2
  • 14
  • 28
  • 2
    better wrap everything like: if($(".slider .slide").length == 1) { var swiper = new Swiper('.swiper-container'); } – nicmare Feb 15 '17 at 15:36
  • thanks a ton for this! I've been searching for an easy way to disable the slider for larger screens. Set a media query, add `transform: translate3d(0px, 0, 0) !important;` and BAM – Oneezy May 16 '18 at 18:49
  • 1
    What about the cloned slides it puts in? There's technically only one slide but the length comes back as 3. Suppose I could test for that though it seems ripe for errors – JDev518 Oct 21 '19 at 17:52
  • This would be ok if you'd have one slide per view. Imagine having more than one slides visible and making this responsive. – roye7777777 Jun 14 '23 at 12:06
6

One of the options would be to conditionally add options, as below:

    let options = {};

    if ( $(".swiper-container .swiper-slide").length == 1 ) {
        options = {
            direction: 'horizontal',
            loop: false,
            autoplayDisableOnInteraction: false,

            keyboardControl: true,
            mousewheelControl: true,

            pagination: '.swiper-pagination',
            paginationClickable: true,
        }
    } else {
        options = {
            loop: false,
            autoplay: false,
        }
    }

    var swiper = new Swiper('.swiper-container', options);
Afron Orana
  • 625
  • 5
  • 14
5

Simply add a condition:

if ($('.swiper-container .swiper-slide').length > 1) {
  var swiper = new Swiper('.swiper-container', {
    // Optional parameters
    direction: 'horizontal',
    loop: false,
    //autoplay: 6500,
    autoplayDisableOnInteraction: false,

    keyboardControl: true,
    mousewheelControl: true,

    pagination: '.swiper-pagination',
    paginationClickable: true,

  });
}
Samuel De Backer
  • 3,404
  • 2
  • 26
  • 37
  • 1
    Thanks, I found this solution to be pretty simple. I also hid the nav buttons through CSS, by default, and added a class to the swiper container that triggers the nav buttons to display. – Jordan Carter Jun 04 '19 at 22:21
5

Just check how many slides you got:

const numberOfSlides = document.querySelectorAll('.swiper-slide').length;

Then set allowSlidePrev/allowSlideNext (or whatever you want to prevent) to false if it's only one slide:

const slider = new Swiper('.swiper-container', {

    allowSlidePrev:numberOfSlides === 1 ? false:true,
    allowSlideNext:numberOfSlides === 1 ? false:true

});

You also have access to the collection of slides so you could also turn on/off these things in your events. In init for example:

on: {
    init: function () {
        const numberOfSlides = this.slides.length;
        ...
    }
}
1

Laconic solution:

var swiper = new Swiper('.swiper-container', {
    navigation: {
        prevEl: '.swiper-button-prev',
        nextEl: '.swiper-button-next',
    },
    on: {
        init: function () {
            if (this.slides.length <= 1) {
                // First way:
                this.allowSlidePrev = this.allowSlideNext = false; // disabling swiping
                this.el.querySelector(".swiper-button-prev").setAttribute('hidden', '');  // hiding arrows prev&next
                this.el.querySelector(".swiper-button-next").setAttribute('hidden', '');

                // Second way:
                // this.el.classList.add('swiper-no-swiping');
            }
        }
    }
});
Dmitry Shashurov
  • 1,148
  • 13
  • 11
1

Since some of the provided solutions seem outdated or conflict with certain combinations of autoplay or loop-settings, this one here takes care of that, keeping everything inside the initialization call:

const heroSlider = new Swiper('#hero-slider .swiper', {
  loop: true,
  watchOverflow: true,
  autoplay: {
    delay: 4000,
  },
  speed: 500,
  navigation: {
    nextEl: '#hero-slider .swiper-button-next',
    prevEl: '#hero-slider .swiper-button-prev',
  },
  on: {
    beforeInit() {
      const slides = this.el.querySelectorAll('.swiper-slide');

      if (slides) {
        this.params.loop = slides.length > 1;
        this.params.autoplay.enabled = slides.length > 1;
      }
    },
  },
});

The above shows no navigation-controls and disables autoloop if we got just 1 slide, effectively disabling the swiper - otherwise controls are shown and autoloop starts as usual. We count the slides here using a bypass over the DOM instead via the Swiper-API, since the latter isn't reliable at this point - nor is it on init (with a single slide f.i., this.slides.length delivers 0 on beforeInit (no surprise) and 3 onInit, since the initial default setting of loop: true seems to produce slide-duplicates when we got just 1 slide etc.).

Long story short: Works for me!

Mayinx
  • 304
  • 1
  • 6
  • 9
  • As for today, this is the only correct solution, +1 to have it wriiten in JavaScript and not jQuery – Mark Jun 23 '23 at 12:36
0

I propose to use update swiper function with new options like this:

params.loop = false;
params.pagination = null;
swiper.update();

Params is the object which was used with swiper initialization.

Thanks!

0

You can check the number of slides, and add swiper-no-swiping class to disable swiping. This assumes noSwiping is kept as true (default setting) [docs]

  // 1. Initialize Swiper
  var swiper = new Swiper('.swiper-container', {
    // Sample parameters
    direction: 'horizontal',
    loop: false,
    autoplayDisableOnInteraction: false,
    keyboardControl: true,
    mousewheelControl: true,
    pagination: '.swiper-pagination',
    paginationClickable: true,
  });


  swiper.on('init', function() {
     // 2. Get Slide count
     if (slider.slides.length <= 1) {
        // 3. Add swiper-no-swiping class
        document.querySelector('.swiper-container').classList.add('swiper-no-swiping')
     }
  });
naribo
  • 690
  • 8
  • 19
0

swiper.allowTouchMove = false;

0

CSS class name added to navigation button when it becomes disabled

 disabledClass: 'disabled_swiper_button'

for reference click https://swiperjs.com/swiper-api#navigation

weirdan
  • 2,499
  • 23
  • 27
0

With the latest swiper.js version, you can add enabled: false to the options. this will, when disabled hide all navigation elements and won't respond to any events and interactions

Found on the API documentation documentation.

Tested with v6.6.1

Here an example

var items = ['slide1']

var options = {
 enabled: items.length > 1
}
Raphaël Balet
  • 6,334
  • 6
  • 41
  • 78
0
  1. You can do it through parameter https://swiperjs.com/swiper-api#param-watchOverflow:
watchOverflow (boolean|false)

// When enabled Swiper will be disabled and hide navigation buttons on case there are not enough slides for sliding
  1. Another way, with method https://swiperjs.com/swiper-api#method-swiper-disable:
// detect sliders
if (swiper.slides.length === 1) {

    // Disable Swiper (if it was enabled). When Swiper is disabled, it will hide all navigation elements and won't respond to any events and interactions
    swiper.disable();
}
Kikambus
  • 1
  • 1
  • 2
-2

Well using $ionicSlides for me works fine to ask the length of the array and if is one or less get the Swiper instance and call these functions:

 $scope.$on("$ionicSlides.sliderInitialized", function (event, data) { 
    $scope.slider2 = data.slider;
      $scope.slider2.activeIndex = 0;

     if (vm.slidetext && vm.slidetext.length <= 1) {

        $scope.slider2.destroyLoop();
        $scope.slider2.stopAutoplay();
        $scope.slider2.lockSwipes();
      } 
}

But these functions are for the native Swiper so should works fine

pabloRN
  • 866
  • 10
  • 19