Skip to main content

ion-slides

The Slides component is a multi-section container. Each section can be swiped or dragged between. It contains any number of Slide components.

Adopted from Swiper.js: The most modern mobile touch slider and framework with hardware accelerated transitions.

http://www.idangero.us/swiper/

Copyright 2016, Vladimir Kharlampidi The iDangero.us http://www.idangero.us/

Licensed under MIT

Custom Animations#

By default, Ionic slides use the built-in slide animation effect. Custom animations can be provided via the options property. Examples of other animations can be found below.

Coverflow#

const slideOpts = {  slidesPerView: 3,  coverflowEffect: {    rotate: 50,    stretch: 0,    depth: 100,    modifier: 1,    slideShadows: true,  },  on: {    beforeInit() {      const swiper = this;
      swiper.classNames.push(        `${swiper.params.containerModifierClass}coverflow`,      );      swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);
      swiper.params.watchSlidesProgress = true;      swiper.originalParams.watchSlidesProgress = true;    },    setTranslate() {      const swiper = this;      const {        width: swiperWidth,        height: swiperHeight,        slides,        $wrapperEl,        slidesSizesGrid,        $,      } = swiper;      const params = swiper.params.coverflowEffect;      const isHorizontal = swiper.isHorizontal();      const transform$$1 = swiper.translate;      const center = isHorizontal        ? -transform$$1 + swiperWidth / 2        : -transform$$1 + swiperHeight / 2;      const rotate = isHorizontal ? params.rotate : -params.rotate;      const translate = params.depth;      // Each slide offset from center      for (let i = 0, length = slides.length; i < length; i += 1) {        const $slideEl = slides.eq(i);        const slideSize = slidesSizesGrid[i];        const slideOffset = $slideEl[0].swiperSlideOffset;        const offsetMultiplier =          ((center - slideOffset - slideSize / 2) / slideSize) *          params.modifier;
        let rotateY = isHorizontal ? rotate * offsetMultiplier : 0;        let rotateX = isHorizontal ? 0 : rotate * offsetMultiplier;        // var rotateZ = 0        let translateZ = -translate * Math.abs(offsetMultiplier);
        let translateY = isHorizontal ? 0 : params.stretch * offsetMultiplier;        let translateX = isHorizontal ? params.stretch * offsetMultiplier : 0;
        // Fix for ultra small values        if (Math.abs(translateX) < 0.001) translateX = 0;        if (Math.abs(translateY) < 0.001) translateY = 0;        if (Math.abs(translateZ) < 0.001) translateZ = 0;        if (Math.abs(rotateY) < 0.001) rotateY = 0;        if (Math.abs(rotateX) < 0.001) rotateX = 0;
        const slideTransform = `translate3d(${translateX}px,${translateY}px,${translateZ}px)  rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
        $slideEl.transform(slideTransform);        $slideEl[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;        if (params.slideShadows) {          // Set shadows          let $shadowBeforeEl = isHorizontal            ? $slideEl.find('.swiper-slide-shadow-left')            : $slideEl.find('.swiper-slide-shadow-top');          let $shadowAfterEl = isHorizontal            ? $slideEl.find('.swiper-slide-shadow-right')            : $slideEl.find('.swiper-slide-shadow-bottom');          if ($shadowBeforeEl.length === 0) {            $shadowBeforeEl = swiper.$(              `<div class="swiper-slide-shadow-${                isHorizontal ? 'left' : 'top'              }"></div>`,            );            $slideEl.append($shadowBeforeEl);          }          if ($shadowAfterEl.length === 0) {            $shadowAfterEl = swiper.$(              `<div class="swiper-slide-shadow-${                isHorizontal ? 'right' : 'bottom'              }"></div>`,            );            $slideEl.append($shadowAfterEl);          }          if ($shadowBeforeEl.length)            $shadowBeforeEl[0].style.opacity =              offsetMultiplier > 0 ? offsetMultiplier : 0;          if ($shadowAfterEl.length)            $shadowAfterEl[0].style.opacity =              -offsetMultiplier > 0 ? -offsetMultiplier : 0;        }      }
      // Set correct perspective for IE10      if (        swiper.support.pointerEvents ||        swiper.support.prefixedPointerEvents      ) {        const ws = $wrapperEl[0].style;        ws.perspectiveOrigin = `${center}px 50%`;      }    },    setTransition(duration) {      const swiper = this;      swiper.slides        .transition(duration)        .find(          '.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left',        )        .transition(duration);    },  },};

Cube#

const slideOpts = {  grabCursor: true,  cubeEffect: {    shadow: true,    slideShadows: true,    shadowOffset: 20,    shadowScale: 0.94,  },  on: {    beforeInit: function () {      const swiper = this;      swiper.classNames.push(`${swiper.params.containerModifierClass}cube`);      swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);
      const overwriteParams = {        slidesPerView: 1,        slidesPerColumn: 1,        slidesPerGroup: 1,        watchSlidesProgress: true,        resistanceRatio: 0,        spaceBetween: 0,        centeredSlides: false,        virtualTranslate: true,      };
      this.params = Object.assign(this.params, overwriteParams);      this.originalParams = Object.assign(this.originalParams, overwriteParams);    },    setTranslate: function () {      const swiper = this;      const {        $el,        $wrapperEl,        slides,        width: swiperWidth,        height: swiperHeight,        rtlTranslate: rtl,        size: swiperSize,      } = swiper;      const params = swiper.params.cubeEffect;      const isHorizontal = swiper.isHorizontal();      const isVirtual = swiper.virtual && swiper.params.virtual.enabled;      let wrapperRotate = 0;      let $cubeShadowEl;      if (params.shadow) {        if (isHorizontal) {          $cubeShadowEl = $wrapperEl.find('.swiper-cube-shadow');          if ($cubeShadowEl.length === 0) {            $cubeShadowEl = swiper.$('<div class="swiper-cube-shadow"></div>');            $wrapperEl.append($cubeShadowEl);          }          $cubeShadowEl.css({ height: `${swiperWidth}px` });        } else {          $cubeShadowEl = $el.find('.swiper-cube-shadow');          if ($cubeShadowEl.length === 0) {            $cubeShadowEl = swiper.$('<div class="swiper-cube-shadow"></div>');            $el.append($cubeShadowEl);          }        }      }
      for (let i = 0; i < slides.length; i += 1) {        const $slideEl = slides.eq(i);        let slideIndex = i;        if (isVirtual) {          slideIndex = parseInt($slideEl.attr('data-swiper-slide-index'), 10);        }        let slideAngle = slideIndex * 90;        let round = Math.floor(slideAngle / 360);        if (rtl) {          slideAngle = -slideAngle;          round = Math.floor(-slideAngle / 360);        }        const progress = Math.max(Math.min($slideEl[0].progress, 1), -1);        let tx = 0;        let ty = 0;        let tz = 0;        if (slideIndex % 4 === 0) {          tx = -round * 4 * swiperSize;          tz = 0;        } else if ((slideIndex - 1) % 4 === 0) {          tx = 0;          tz = -round * 4 * swiperSize;        } else if ((slideIndex - 2) % 4 === 0) {          tx = swiperSize + round * 4 * swiperSize;          tz = swiperSize;        } else if ((slideIndex - 3) % 4 === 0) {          tx = -swiperSize;          tz = 3 * swiperSize + swiperSize * 4 * round;        }        if (rtl) {          tx = -tx;        }
        if (!isHorizontal) {          ty = tx;          tx = 0;        }
        const transform$$1 = `rotateX(${          isHorizontal ? 0 : -slideAngle        }deg) rotateY(${          isHorizontal ? slideAngle : 0        }deg) translate3d(${tx}px, ${ty}px, ${tz}px)`;        if (progress <= 1 && progress > -1) {          wrapperRotate = slideIndex * 90 + progress * 90;          if (rtl) wrapperRotate = -slideIndex * 90 - progress * 90;        }        $slideEl.transform(transform$$1);        if (params.slideShadows) {          // Set shadows          let shadowBefore = isHorizontal            ? $slideEl.find('.swiper-slide-shadow-left')            : $slideEl.find('.swiper-slide-shadow-top');          let shadowAfter = isHorizontal            ? $slideEl.find('.swiper-slide-shadow-right')            : $slideEl.find('.swiper-slide-shadow-bottom');          if (shadowBefore.length === 0) {            shadowBefore = swiper.$(              `<div class="swiper-slide-shadow-${                isHorizontal ? 'left' : 'top'              }"></div>`,            );            $slideEl.append(shadowBefore);          }          if (shadowAfter.length === 0) {            shadowAfter = swiper.$(              `<div class="swiper-slide-shadow-${                isHorizontal ? 'right' : 'bottom'              }"></div>`,            );            $slideEl.append(shadowAfter);          }          if (shadowBefore.length)            shadowBefore[0].style.opacity = Math.max(-progress, 0);          if (shadowAfter.length)            shadowAfter[0].style.opacity = Math.max(progress, 0);        }      }      $wrapperEl.css({        '-webkit-transform-origin': `50% 50% -${swiperSize / 2}px`,        '-moz-transform-origin': `50% 50% -${swiperSize / 2}px`,        '-ms-transform-origin': `50% 50% -${swiperSize / 2}px`,        'transform-origin': `50% 50% -${swiperSize / 2}px`,      });
      if (params.shadow) {        if (isHorizontal) {          $cubeShadowEl.transform(            `translate3d(0px, ${swiperWidth / 2 + params.shadowOffset}px, ${              -swiperWidth / 2            }px) rotateX(90deg) rotateZ(0deg) scale(${params.shadowScale})`,          );        } else {          const shadowAngle =            Math.abs(wrapperRotate) -            Math.floor(Math.abs(wrapperRotate) / 90) * 90;          const multiplier =            1.5 -            (Math.sin((shadowAngle * 2 * Math.PI) / 360) / 2 +              Math.cos((shadowAngle * 2 * Math.PI) / 360) / 2);          const scale1 = params.shadowScale;          const scale2 = params.shadowScale / multiplier;          const offset$$1 = params.shadowOffset;          $cubeShadowEl.transform(            `scale3d(${scale1}, 1, ${scale2}) translate3d(0px, ${              swiperHeight / 2 + offset$$1            }px, ${-swiperHeight / 2 / scale2}px) rotateX(-90deg)`,          );        }      }
      const zFactor =        swiper.browser.isSafari || swiper.browser.isUiWebView          ? -swiperSize / 2          : 0;      $wrapperEl.transform(        `translate3d(0px,0,${zFactor}px) rotateX(${          swiper.isHorizontal() ? 0 : wrapperRotate        }deg) rotateY(${swiper.isHorizontal() ? -wrapperRotate : 0}deg)`,      );    },    setTransition: function (duration) {      const swiper = this;      const { $el, slides } = swiper;      slides        .transition(duration)        .find(          '.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left',        )        .transition(duration);      if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) {        $el.find('.swiper-cube-shadow').transition(duration);      }    },  },};

Fade#

const slideOpts = {  on: {    beforeInit() {      const swiper = this;      swiper.classNames.push(`${swiper.params.containerModifierClass}fade`);      const overwriteParams = {        slidesPerView: 1,        slidesPerColumn: 1,        slidesPerGroup: 1,        watchSlidesProgress: true,        spaceBetween: 0,        virtualTranslate: true,      };      swiper.params = Object.assign(swiper.params, overwriteParams);      swiper.params = Object.assign(swiper.originalParams, overwriteParams);    },    setTranslate() {      const swiper = this;      const { slides } = swiper;      for (let i = 0; i < slides.length; i += 1) {        const $slideEl = swiper.slides.eq(i);        const offset$$1 = $slideEl[0].swiperSlideOffset;        let tx = -offset$$1;        if (!swiper.params.virtualTranslate) tx -= swiper.translate;        let ty = 0;        if (!swiper.isHorizontal()) {          ty = tx;          tx = 0;        }        const slideOpacity = swiper.params.fadeEffect.crossFade          ? Math.max(1 - Math.abs($slideEl[0].progress), 0)          : 1 + Math.min(Math.max($slideEl[0].progress, -1), 0);        $slideEl          .css({            opacity: slideOpacity,          })          .transform(`translate3d(${tx}px, ${ty}px, 0px)`);      }    },    setTransition(duration) {      const swiper = this;      const { slides, $wrapperEl } = swiper;      slides.transition(duration);      if (swiper.params.virtualTranslate && duration !== 0) {        let eventTriggered = false;        slides.transitionEnd(() => {          if (eventTriggered) return;          if (!swiper || swiper.destroyed) return;          eventTriggered = true;          swiper.animating = false;          const triggerEvents = ['webkitTransitionEnd', 'transitionend'];          for (let i = 0; i < triggerEvents.length; i += 1) {            $wrapperEl.trigger(triggerEvents[i]);          }        });      }    },  },};

Flip#

const slideOpts = {  on: {    beforeInit() {      const swiper = this;      swiper.classNames.push(`${swiper.params.containerModifierClass}flip`);      swiper.classNames.push(`${swiper.params.containerModifierClass}3d`);      const overwriteParams = {        slidesPerView: 1,        slidesPerColumn: 1,        slidesPerGroup: 1,        watchSlidesProgress: true,        spaceBetween: 0,        virtualTranslate: true,      };      swiper.params = Object.assign(swiper.params, overwriteParams);      swiper.originalParams = Object.assign(        swiper.originalParams,        overwriteParams,      );    },    setTranslate() {      const swiper = this;      const { $, slides, rtlTranslate: rtl } = swiper;      for (let i = 0; i < slides.length; i += 1) {        const $slideEl = slides.eq(i);        let progress = $slideEl[0].progress;        if (swiper.params.flipEffect.limitRotation) {          progress = Math.max(Math.min($slideEl[0].progress, 1), -1);        }        const offset$$1 = $slideEl[0].swiperSlideOffset;        const rotate = -180 * progress;        let rotateY = rotate;        let rotateX = 0;        let tx = -offset$$1;        let ty = 0;        if (!swiper.isHorizontal()) {          ty = tx;          tx = 0;          rotateX = -rotateY;          rotateY = 0;        } else if (rtl) {          rotateY = -rotateY;        }
        $slideEl[0].style.zIndex =          -Math.abs(Math.round(progress)) + slides.length;
        if (swiper.params.flipEffect.slideShadows) {          // Set shadows          let shadowBefore = swiper.isHorizontal()            ? $slideEl.find('.swiper-slide-shadow-left')            : $slideEl.find('.swiper-slide-shadow-top');          let shadowAfter = swiper.isHorizontal()            ? $slideEl.find('.swiper-slide-shadow-right')            : $slideEl.find('.swiper-slide-shadow-bottom');          if (shadowBefore.length === 0) {            shadowBefore = swiper.$(              `<div class="swiper-slide-shadow-${                swiper.isHorizontal() ? 'left' : 'top'              }"></div>`,            );            $slideEl.append(shadowBefore);          }          if (shadowAfter.length === 0) {            shadowAfter = swiper.$(              `<div class="swiper-slide-shadow-${                swiper.isHorizontal() ? 'right' : 'bottom'              }"></div>`,            );            $slideEl.append(shadowAfter);          }          if (shadowBefore.length)            shadowBefore[0].style.opacity = Math.max(-progress, 0);          if (shadowAfter.length)            shadowAfter[0].style.opacity = Math.max(progress, 0);        }        $slideEl.transform(          `translate3d(${tx}px, ${ty}px, 0px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`,        );      }    },    setTransition(duration) {      const swiper = this;      const { slides, activeIndex, $wrapperEl } = swiper;      slides        .transition(duration)        .find(          '.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left',        )        .transition(duration);      if (swiper.params.virtualTranslate && duration !== 0) {        let eventTriggered = false;        // eslint-disable-next-line        slides.eq(activeIndex).transitionEnd(function onTransitionEnd() {          if (eventTriggered) return;          if (!swiper || swiper.destroyed) return;
          eventTriggered = true;          swiper.animating = false;          const triggerEvents = ['webkitTransitionEnd', 'transitionend'];          for (let i = 0; i < triggerEvents.length; i += 1) {            $wrapperEl.trigger(triggerEvents[i]);          }        });      }    },  },};

Usage#

import { Component } from '@angular/core';
@Component({  selector: 'slides-example',  template: `    <ion-content>      <ion-slides pager="true" [options]="slideOpts">        <ion-slide>          <h1>Slide 1</h1>        </ion-slide>        <ion-slide>          <h1>Slide 2</h1>        </ion-slide>        <ion-slide>          <h1>Slide 3</h1>        </ion-slide>      </ion-slides>    </ion-content>  `,})export class SlideExample {  // Optional parameters to pass to the swiper instance.  // See http://idangero.us/swiper/api/ for valid options.  slideOpts = {    initialSlide: 1,    speed: 400,  };  constructor() {}}
/* Without setting height the slides will take up the height of the slide's content */ion-slides {  height: 100%;}

Properties#

mode#

DescriptionThe mode determines which platform styles to use.
Attributemode
Type"ios" \| "md"
Defaultundefined

options#

DescriptionOptions to pass to the swiper instance.
See http://idangero.us/swiper/api/ for valid options
Attributeoptions
Typeany
Default{}

pager#

DescriptionIf true, show the pagination.
Attributepager
Typeboolean
Defaultfalse

scrollbar#

DescriptionIf true, show the scrollbar.
Attributescrollbar
Typeboolean
Defaultfalse

Events#

NameDescription
ionSlideDidChangeEmitted after the active slide has changed.
ionSlideDoubleTapEmitted when the user double taps on the slide's container.
ionSlideDragEmitted when the slider is actively being moved.
ionSlideNextEndEmitted when the next slide has ended.
ionSlideNextStartEmitted when the next slide has started.
ionSlidePrevEndEmitted when the previous slide has ended.
ionSlidePrevStartEmitted when the previous slide has started.
ionSlideReachEndEmitted when the slider is at the last slide.
ionSlideReachStartEmitted when the slider is at its initial position.
ionSlidesDidLoadEmitted after Swiper initialization
ionSlideTapEmitted when the user taps/clicks on the slide's container.
ionSlideTouchEndEmitted when the user releases the touch.
ionSlideTouchStartEmitted when the user first touches the slider.
ionSlideTransitionEndEmitted when the slide transition has ended.
ionSlideTransitionStartEmitted when the slide transition has started.
ionSlideWillChangeEmitted before the active slide has changed.

Methods#

getActiveIndex#

DescriptionGet the index of the active slide.
SignaturegetActiveIndex() => Promise<number>

getPreviousIndex#

DescriptionGet the index of the previous slide.
SignaturegetPreviousIndex() => Promise<number>

getSwiper#

DescriptionGet the Swiper instance.
Use this to access the full Swiper API.
See https://idangero.us/swiper/api/ for all API options.
SignaturegetSwiper() => Promise<any>

isBeginning#

DescriptionGet whether or not the current slide is the first slide.
SignatureisBeginning() => Promise<boolean>

isEnd#

DescriptionGet whether or not the current slide is the last slide.
SignatureisEnd() => Promise<boolean>

length#

DescriptionGet the total number of slides.
Signaturelength() => Promise<number>

lockSwipeToNext#

DescriptionLock or unlock the ability to slide to the next slide.
SignaturelockSwipeToNext(lock: boolean) => Promise<void>

lockSwipeToPrev#

DescriptionLock or unlock the ability to slide to the previous slide.
SignaturelockSwipeToPrev(lock: boolean) => Promise<void>

lockSwipes#

DescriptionLock or unlock the ability to slide to the next or previous slide.
SignaturelockSwipes(lock: boolean) => Promise<void>

slideNext#

DescriptionTransition to the next slide.
SignatureslideNext(speed?: number \| undefined, runCallbacks?: boolean \| undefined) => Promise<void>

slidePrev#

DescriptionTransition to the previous slide.
SignatureslidePrev(speed?: number \| undefined, runCallbacks?: boolean \| undefined) => Promise<void>

slideTo#

DescriptionTransition to the specified slide.
SignatureslideTo(index: number, speed?: number \| undefined, runCallbacks?: boolean \| undefined) => Promise<void>

startAutoplay#

DescriptionStart auto play.
SignaturestartAutoplay() => Promise<void>

stopAutoplay#

DescriptionStop auto play.
SignaturestopAutoplay() => Promise<void>

update#

DescriptionUpdate the underlying slider implementation. Call this if you've added or removed
child slides.
Signatureupdate() => Promise<void>

updateAutoHeight#

DescriptionForce swiper to update its height (when autoHeight is enabled) for the duration
equal to 'speed' parameter.
SignatureupdateAutoHeight(speed?: number \| undefined) => Promise<void>

CSS Custom Properties#

NameDescription
--bullet-backgroundBackground of the pagination bullets
--bullet-background-activeBackground of the active pagination bullet
--progress-bar-backgroundBackground of the pagination progress-bar
--progress-bar-background-activeBackground of the active pagination progress-bar
--scroll-bar-backgroundBackground of the pagination scroll-bar
--scroll-bar-background-activeBackground of the active pagination scroll-bar
View Source