Skip to content

Slides ​

Slides is a swipeable carousel that shows one slide at a time, with optional arrows, pagination bullets, a scrollbar, autoplay, looping, and a fade effect.

IonSlides is the carousel; each IonSlide inside it is one full-size slide that centers its content. This is a port of Ionic's legacy ion-slides (which wraps Swiper): only one slide per view is supported — Swiper's slidesPerView, free mode, zoom, and 3D effects are not ported, and there is no options object; the supported options are parameters.

Basic usage ​

IonSlides fills its parent (width and height 100%), so give it — or its parent — a definite height. Slides follow a mouse or touch drag, resist past the first and last slide, and on release snap to the next slide when the drag covered half a slide or was a quick flick. A mostly vertical drag is left to the scroll container. AllowTouchMove="false" turns dragging off.

razor
@* IonSlides fills its parent (100% × 100%), so give it — or its parent — a height. *@
<IonSlides Style="@(new Style { Height = Length.Px(240) })">
    <IonSlide><h2>Welcome</h2></IonSlide>
    <IonSlide><h2>Swipe to continue</h2></IonSlide>
    <IonSlide><h2>All set</h2></IonSlide>
</IonSlides>

Put the IonSlides directly in IonSlides (a @foreach is fine): the slide count is taken from the IonSlide elements at the top level of its content.

Navigation adds previous/next arrows (disabled at the first/last slide unless Loop is set), Pagination adds one bullet per slide (tap a bullet to jump to it), and Scrollbar adds a bar whose thumb marks the current position.

razor
<IonSlides Navigation="true" Pagination="true" Scrollbar="true"
           Style="@(new Style { Height = Length.Px(240) })">
    <IonSlide>Slide 1</IonSlide>
    <IonSlide>Slide 2</IonSlide>
    <IonSlide>Slide 3</IonSlide>
</IonSlides>

Active slide ​

ActiveIndex is the current slide (0-based; clamped to the slide count). @bind-ActiveIndex reports every change — drag, arrow, bullet, or autoplay — and moves the carousel when the page changes the value. Without a binding the carousel tracks its own position; a re-render of the parent moves it only when the ActiveIndex you pass changes.

razor
@* @bind-ActiveIndex reports drags, arrows, bullets and autoplay, and moves the slides from code. *@
<IonSlides @bind-ActiveIndex="_index" Pagination="true"
           Style="@(new Style { Height = Length.Px(240) })">
    @foreach (var step in _steps)
    {
        <IonSlide><h2>@step</h2></IonSlide>
    }
</IonSlides>

<IonButton Disabled="@(_index == 0)" OnClick="@(() => _index--)">Back</IonButton>
<IonButton Disabled="@(_index == _steps.Length - 1)" OnClick="@(() => _index++)">Next</IonButton>

@code {
    private readonly string[] _steps = { "Account", "Profile", "Done" };
    private int _index;
}

IonSlides also has public SlideToAsync, SlideNextAsync, SlidePrevAsync, StartAutoplay, and StopAutoplay methods and SlideCount, IsBeginning, and IsEnd properties, reachable through @ref (<IonSlides @ref="_slides"> with an IonSlides? _slides field). When the position is also bound with @bind-ActiveIndex, the binding follows these calls; without it, a re-render of the declaring component returns the carousel to the ActiveIndex it passes.

Loop and autoplay ​

Autoplay advances every AutoplayDelay milliseconds (default 3000); the timer restarts after every change and pauses while the user drags. Without Loop, autoplay stops at the last slide. Loop wraps past either end — the wrap animates back across the intermediate slides rather than continuing seamlessly as Swiper's cloned track does.

razor
@* Advances every AutoplayDelay ms; Loop wraps from the last slide back to the first. *@
<IonSlides Autoplay="true" AutoplayDelay="4000" Loop="true" Pagination="true"
           Style="@(new Style { Height = Length.Px(240) })">
    <IonSlide>Featured 1</IonSlide>
    <IonSlide>Featured 2</IonSlide>
    <IonSlide>Featured 3</IonSlide>
</IonSlides>

Fade effect ​

Effect="fade" stacks the slides and cross-fades between them instead of sliding the track. Unknown Effect values fall back to "slide".

razor
<IonSlides Effect="fade" Navigation="true"
           Style="@(new Style { Height = Length.Px(240) })">
    <IonSlide>Morning</IonSlide>
    <IonSlide>Afternoon</IonSlide>
    <IonSlide>Evening</IonSlide>
</IonSlides>

Speed (milliseconds, default 300) is the duration of every slide change: arrows, bullets, autoplay, ActiveIndex changes, the settle after a drag, and the fade.

API ​

Every component also accepts Class (extra CSS classes), Style (an inline Style object) and Id (the root element's id) — see Conventions.

IonSlides ​

ParameterTypeDefaultDescription
ActiveIndexint0Index of the active slide shown in the viewport. Mirrors Swiper's initialSlide / activeIndex; supports two-way binding via ActiveIndexChanged. Two-way bindable: @bind-ActiveIndex.
AllowTouchMovebooltrueIf false, the slides cannot be dragged (Swiper's allowTouchMove).
AutoplayboolfalseIf true, advance automatically every AutoplayDelay milliseconds (Swiper's autoplay). Inert when no MikoDispatcher is available (a bare unit test), since there is no render loop to marshal the tick onto.
AutoplayDelayint3000Milliseconds between automatic advances (Swiper's autoplay.delay).
Effectstring"slide"The transition effect: "slide" (default, the track slides horizontally) or "fade" (slides stack and cross-fade). Unknown values fall back to "slide".
LoopboolfalseIf true, advancing past the last slide wraps to the first and vice versa (Swiper's loop), and the arrows are never disabled. The wrap animates back across the intermediate slides; there is no seamless cloned track as in Swiper.
NavigationboolfalseIf true, render the previous/next navigation arrows (Swiper's navigation). Unless Loop is set, the arrow at the first / last slide is disabled.
PaginationboolfalseIf true, render the pagination bullets (Swiper's pagination).
ScrollbarboolfalseIf true, render the scrollbar (Swiper's scrollbar).
Speedint300Duration in milliseconds of every slide change (Swiper's speed): the settle after a drag, arrow, bullet, autoplay and ActiveIndex changes, and the fade cross-fade.
EventTypeDescription
ActiveIndexChangedEventCallback<int>Raised when the active slide changes, whether by drag, arrow, bullet or autoplay.
SlotTypeDescription
ChildContentRenderFragment?Content placed between the component's tags.

IonSlide ​

SlotTypeDescription
ChildContentRenderFragment?Content placed between the component's tags.

Styling ​

Theme tokens ​

Theme token IonicTheme.Slides (SlidesToken). Assign only the values you want to change — the rest keep the mode defaults below. App-wide: builder.AddIonic(o => o.Theme.Slides = new SlidesToken { … }); for one subtree: a ConfigProvider. See Theming.

TokenTypemdios
BulletBackgroundColor#333333#333333
BulletBackgroundActiveColor#0054e9#0054e9
NavigationColorColor#0054e9#0054e9
ScrollBarBackgroundColorrgba(0, 0, 0, 0.1)rgba(0, 0, 0, 0.1)
ScrollBarBackgroundActiveColorrgba(0, 0, 0, 0.5)rgba(0, 0, 0, 0.5)

CSS classes ​

App stylesheet rules always win over Ionic's own rules (see Theming), so these classes can be targeted directly from GlobalStyles.cs.

SelectorElement
.swiper-containerThe IonSlides host (also slides-md / slides-ios, swiper-horizontal, and the mode class).
.swiper-fadeEffect="fade".
.swiper-navigation-disabledNavigation is off.
.swiper-wrapperThe track that moves; also carries swiper-wrapper-at-{index}.
.swiper-slideAn IonSlide (centers its content, 18px text). swiper-slide-active marks the visible slide under the fade effect.
.swiper-button-prev, .swiper-button-nextThe arrows; .swiper-button-disabled at an end.
.swiper-pagination, .swiper-pagination-bullet, .swiper-pagination-bullet-activeThe bullets.
.swiper-scrollbar, .swiper-scrollbar-dragThe scrollbar and its thumb.
csharp
// GlobalStyles.cs — left-aligned, padded slide content: <IonSlides Class="onboarding">…</IonSlides>
[".swiper-container.onboarding .swiper-slide"] = new()
{
    JustifyContent = JustifyContent.FlexStart,
    TextAlign = TextAlign.Left,
    Padding = new Padding(24),
},

Released under the MIT License.