Carousel

A Slideshow for cycling images in confined spaces

Because images can take a few seconds to load (or not at all), use the image container to specify a precisely sized container so that your layout isn't broken because of image loading or image errors - Bulma image.

<template>
    <b-carousel>
        <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
            <section :class="`hero is-medium is-${carousel.color}`">
                <div class="hero-body has-text-centered">
                    <h1 class="title">{{carousel.text}}</h1>
                </div>
            </section>
        </b-carousel-item>
    </b-carousel>
</template>

<script>
export default {
    data(){
        return {
            carousels: [
                { text: 'Slide 1', color: 'primary' },
                { text: 'Slide 2', color: 'info' },
                { text: 'Slide 3', color: 'success' },
                { text: 'Slide 4', color: 'warning' },
                { text: 'Slide 5', color: 'danger' }
            ]
        }
    }
}
</script>

# Custom

<template>
    <section>

        <div class="example-component">
            <b-field grouped group-multiline>
                <div class="control">
                    <b-switch v-model="autoPlay">Autoplay</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="pauseHover" :disabled="!autoPlay">Pause on hover</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="pauseInfo" :disabled="!pauseHover">Pause info</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="drag">Drag event</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="repeat" :disabled="!autoPlay">Repeat</b-switch>
                </div>
            </b-field>
            <b-field grouped group-multiline>
                <b-field label="Value">
                    <b-numberinput v-model="carousel" min="0" :max="carousels.length - 1" controls-position="compact"/>
                </b-field>
                <b-field label="Interval">
                    <b-numberinput v-model="interval" min="0" controls-position="compact" step="1000" :disabled="!autoPlay"/>
                </b-field>
                <b-field label="Animated">
                    <b-field>
                        <b-radio-button v-model="animated"
                            native-value="fade">
                            Fade
                        </b-radio-button>
                        <b-radio-button v-model="animated"
                            native-value="slide">
                            Slide
                        </b-radio-button>
                    </b-field>
                </b-field>
                <b-field label="Pause Type">
                    <b-select v-model="pauseType" :disabled="!pauseInfo">
                        <option value="is-white">is-white</option>
                        <option value="is-dark">is-dark</option>
                        <option value="is-primary">is-primary</option>
                    </b-select>
                </b-field>
            </b-field>
        </div>

        <b-carousel
            v-model="carousel"
            :animated="animated"
            :has-drag="drag"
            :autoplay="autoPlay"
            :pause-hover="pauseHover"
            :pause-info="pauseInfo"
            :pause-info-type="pauseType"
            :interval="interval"
            :repeat="repeat"
            @change="info($event)">
            <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
                <section :class="`hero is-medium is-${carousel.color} is-bold`">
                    <div class="hero-body has-text-centered">
                        <h1 class="title">{{carousel.title}}</h1>
                        <b-input :placeholder="carousel.title"></b-input>
                        <p>A link that <a href="#arrow">goes to arrow</a></p>
                    </div>
                </section>
            </b-carousel-item>
        </b-carousel>
    </section>
</template>

<script>
export default {
    data() {
        return {
            carousel: 0,
            animated: 'fade',
            drag: false,
            autoPlay: false,
            pauseHover: false,
            pauseInfo: false,
            repeat: false,
            pauseType: 'is-primary',
            interval: 3000,
            carousels: [
                { title: 'Slide 1', color: 'dark' },
                { title: 'Slide 2', color: 'primary' },
                { title: 'Slide 3', color: 'info' },
                { title: 'Slide 4', color: 'success' },
                { title: 'Slide 5', color: 'warning' },
                { title: 'Slide 6', color: 'danger' }
            ]
        }
    },
    methods: {
        info(value) {
            this.carousel = value
            this.$buefy.toast.open({
                message: `This Slide ${value} !`,
                type: 'is-info'
            })
        }
    }
}
</script>

# Arrow

<template>
    <section>
        <div class="example-component">
            <b-field grouped group-multiline>
                <div class="control">
                    <b-switch v-model="arrow"><strong>Arrow</strong></b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="arrowBoth" :disabled="!arrow">Both</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="arrowHover" :disabled="!arrow">Hover</b-switch>
                </div>
            </b-field>
            <b-field grouped group-multiline>
                <b-field label="Icon Pack">
                    <b-input v-model="iconPack" placeholder="e.g. mdi, fa or other"/>
                </b-field>
                <b-field label="Icon Size">
                    <b-select v-model="iconSize">
                        <option value="">default</option>
                        <option value="is-small">is-small</option>
                        <option value="is-medium">is-medium</option>
                        <option value="is-large">is-large</option>
                    </b-select>
                </b-field>
                <b-field label="Icon Prev">
                    <b-input v-model="iconPrev"/>
                </b-field>
                <b-field label="Icon Next">
                    <b-input v-model="iconNext"/>
                </b-field>
            </b-field>
        </div>

        <b-carousel
            :arrow="arrow"
            :repeat="arrowBoth"
            :arrow-hover="arrowHover"
            :icon-pack="iconPack"
            :icon-prev="iconPrev"
            :icon-next="iconNext"
            :icon-size="iconSize">
            <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
                <section :class="`hero is-medium is-${carousel.color}`">
                    <div class="hero-body has-text-centered">
                        <h1 class="title">{{carousel.title}}</h1>
                    </div>
                </section>
            </b-carousel-item>
        </b-carousel>
    </section>
</template>

<script>
export default {
    data() {
        return {
            arrow: true,
            arrowBoth: false,
            arrowHover: false,
            iconPack: 'mdi',
            iconPrev: 'arrow-left',
            iconNext: 'arrow-right',
            iconSize: '',
            carousels: [
                { title: 'Slide 1', color: 'info' },
                { title: 'Slide 2', color: 'success' },
                { title: 'Slide 3', color: 'warning' },
                { title: 'Slide 4', color: 'danger' }
            ]
        }
    }
}
</script>

# Progress

<template>
    <section>
        <div class="example-component">
            <b-field grouped group-multiline>
                <div class="control">
                    <b-switch v-model="progress"><strong>Progress</strong></b-switch>
                </div>
                <b-field label="Type" label-position="on-border">
                    <b-select v-model="progressType" :disabled="!progress">
                        <option value="is-primary">is-primary</option>
                        <option value="is-info">is-info</option>
                        <option value="is-success">is-success</option>
                        <option value="is-warning">is-warning</option>
                        <option value="is-danger">is-danger</option>
                        <option value="is-white">is-white</option>
                        <option value="is-light">is-light</option>
                        <option value="is-dark">is-dark</option>
                    </b-select>
                </b-field>
            </b-field>
        </div>

        <b-carousel
            :progress="progress"
            :progress-type="progressType">
            <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
                <section :class="`hero is-medium is-${carousel.color}`">
                    <div class="hero-body has-text-centered">
                        <h1 class="title">{{carousel.title}}</h1>
                    </div>
                </section>
            </b-carousel-item>
        </b-carousel>
    </section>
</template>

<script>
export default {
    data() {
        return {
            progress: true,
            progressType: 'is-primary',
            carousels: [
                { title: 'Slide 1', color: 'grey' },
                { title: 'Slide 2', color: 'dark' },
                { title: 'Slide 3', color: 'primary' },
                { title: 'Slide 4', color: 'info' }
            ]
        }
    }
}
</script>

# Indicator

<template>
    <section>
        <div class="example-component">
            <b-field grouped group-multiline>
                <div class="control">
                    <b-switch v-model="indicator"><strong>Indicator</strong></b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="indicatorBackground" :disabled="!indicator">Background</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="indicatorInside" :disabled="!indicator">Inside</b-switch>
                </div>
            </b-field>
            <b-field grouped group-multiline>
                <b-field label="Position" :disabled="!indicator">
                    <b-select v-model="indicatorPosition">
                        <option value="is-bottom">is-bottom</option>
                        <option value="is-top">is-top</option>
                    </b-select>
                </b-field>
                <b-field label="Mode">
                    <b-field>
                        <b-radio-button v-model="indicatorMode" native-value="click" :disabled="!indicator">
                            <span>Click</span>
                        </b-radio-button>
                        <b-radio-button v-model="indicatorMode" native-value="hover" :disabled="!indicator">
                            <span>Hover</span>
                        </b-radio-button>
                    </b-field>
                </b-field>
                <b-field label="Style">
                    <b-field>
                        <b-radio-button v-model="indicatorStyle" native-value="is-boxes" :disabled="!indicator">
                            <span>Boxes</span>
                        </b-radio-button>
                        <b-radio-button v-model="indicatorStyle" native-value="is-dots" :disabled="!indicator">
                            <span>Dots</span>
                        </b-radio-button>
                        <b-radio-button v-model="indicatorStyle" native-value="is-lines" :disabled="!indicator">
                            <span>Lines</span>
                        </b-radio-button>
                    </b-field>
                </b-field>
            </b-field>
        </div>

        <b-carousel
            :indicator="indicator"
            :indicator-background="indicatorBackground"
            :indicator-inside="indicatorInside"
            :indicator-mode="indicatorMode"
            :indicator-position="indicatorPosition"
            :indicator-style="indicatorStyle">
            <b-carousel-item v-for="(carousel, i) in carousels" :key="i">
                <section :class="`hero is-medium is-${carousel.color}`">
                    <div class="hero-body has-text-centered">
                        <h1 class="title">{{carousel.title}}</h1>
                    </div>
                </section>
            </b-carousel-item>
        </b-carousel>
    </section>
</template>

<script>
export default {
    data() {
        return {
            indicator: true,
            indicatorBackground: true,
            indicatorInside: true,
            indicatorMode: 'hover',
            indicatorPosition: 'is-top',
            indicatorStyle: 'is-lines',
            carousels: [
                { title: 'Slide 1', color: 'info' },
                { title: 'Slide 2', color: 'success' },
                { title: 'Slide 3', color: 'warning' },
                { title: 'Slide 4', color: 'danger' }
            ]
        }
    }
}
</script>

Some source by Picsum and Images from Unsplash.


# Custom Indicators

When there are more than 6 images, add indicator-custom
If you want custom indicator to stay big, use is-medium on indicator-custom-size
<template>
    <b-carousel :indicator-inside="false">
        <b-carousel-item v-for="(item, i) in 6" :key="i">
            <b-image class="image" :src="getImgUrl(i)"></b-image>
        </b-carousel-item>
        <template #indicators="props">
            <b-image class="al image" :src="getImgUrl(props.i)" :title="props.i"></b-image>
        </template>
    </b-carousel>
</template>

<script>
export default {
    methods: {
      getImgUrl(value) {
          return `https://picsum.photos/id/43${value}/1230/500`
      }
    }
}
</script>

<style>
.is-active .al img {
    filter: grayscale(0%);
}
.al img {
    filter: grayscale(100%);
}
</style>

You may also want to add the is-clipped modifier to a containing element (usually html) to stop scroll overflow.

<template>
    <b-carousel :autoplay="false" indicator-custom :indicator-inside="false" :overlay="gallery" @click="switchGallery(true)">
        <b-carousel-item v-for="(item, i) in 20" :key="i">
            <a class="image ">
                <img :src="getImgUrl(i)">
            </a>
        </b-carousel-item>
        <span v-if="gallery" @click="switchGallery(false)" class="modal-close is-large"/>
        <template #indicators="props">
            <figure class="al image" :draggable="false">
                <img :draggable="false" :src="getImgUrl(props.i)" :title="props.i">
            </figure>
        </template>
    </b-carousel>
</template>

<script>
export default {
    data() {
        return {
            gallery: false
        }
    },
    methods: {
        getImgUrl(value) {
            value += 50
            return `https://picsum.photos/id/10${value}/1230/500`
        },
        switchGallery(value) {
            this.gallery = value
            if (value) {
                return document.documentElement.classList.add('is-clipped')
            } else {
                return document.documentElement.classList.remove('is-clipped')
            }
        }
    }
}
</script>

<style>
.is-active .al img {
    border: 1px solid #fff;
    filter: grayscale(0%);
}
.al img {
    border: 1px solid transparent;
    filter: grayscale(100%);
}
</style>

An imposing carousel list to showcase viewer something.

Since0.8.9

<template>
    <section>
        <div class="example-component">
            <b-field grouped group-multiline>
                <div class="control">
                    <b-switch v-model="arrow">Arrow</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="arrowHover" :disabled="!arrow">Arrow on hover</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="drag">Drag event</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="gray" :disabled="opacity">Grayscale</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="opacity" :disabled="gray">Opacity</b-switch>
                </div>
                <div class="control">
                    <b-switch v-model="repeat">Repeat</b-switch>
                </div>
            </b-field>
            <b-field grouped group-multiline>
                <b-field label="Value">
                    <b-numberinput v-model="values" min="0" :max="items.length - 1" controls-position="compact"/>
                </b-field>
                <b-field label="Items to Show">
                    <b-numberinput v-model="perList" min="1" :max="items.length" controls-position="compact"/>
                </b-field>
                <b-field label="Items to List">
                    <b-numberinput v-model="increment" min="1" :max="items.length - 1" controls-position="compact"/>
                </b-field>
            </b-field>
        </div>
        <b-carousel-list
            v-model="values"
            :data="items"
            :arrow="arrow"
            :arrow-hover="arrowHover"
            :items-to-show="perList"
            :items-to-list="increment"
            :repeat="repeat"
            :has-drag="drag"
            :has-grayscale="gray"
            :has-opacity="opacity" />
    </section>
</template>

<script>
export default {
    data() {
        return {
            arrow: true,
            arrowHover: true,
            drag: true,
            gray: false,
            opacity: false,
            values: 1,
            perList: 4,
            increment: 1,
            repeat: false,
            items: [
                {
                    alt: 'Slide 1',
                    title: 'Slide 1',
                    image: 'https://picsummm.photos/id/0/1230/500',
                    srcFallback: 'https://picsum.photos/id/0/1230/500'
                },
                {
                    title: 'Slide 2',
                    image: 'https://picsum.photos/id/1/1230/500'
                },
                {
                    title: 'Slide 3',
                    image: 'https://picsum.photos/id/2/1230/500'
                },
                {
                    title: 'Slide 4',
                    image: 'https://picsum.photos/id/3/1230/500'
                },
                {
                    title: 'Slide 5',
                    image: 'https://picsum.photos/id/4/1230/500'
                },
                {
                    title: 'Slide 6',
                    image: 'https://picsum.photos/id/5/1230/500'
                },
                {
                    title: 'Slide 7',
                    image: 'https://picsum.photos/id/6/1230/500'
                },
                {
                    title: 'Slide 8',
                    image: 'https://picsum.photos/id/7/1230/500'
                }
            ]
        }
    }
}
</script>

# Custom With Card

<template>
    <b-carousel-list v-model="test" :data="items" :items-to-show="2">
        <template #item="list">
            <div class="card">
                <div class="card-image">
                    <figure class="image is-5by4">
                        <a @click="info(list.index)"><img :src="list.image"></a>
                    </figure>
                    <b-tag type="is-danger" rounded style="position: absolute; top: 0;"><b>50%</b></b-tag>
                </div>
                <div class="card-content">
                    <div class="content">
                        <p class="title is-6">{{ list.title }}</p>
                        <p class="subtitle is-7">@johnsmith</p>
                        <b-field grouped >
                            <p class="control" v-if="list.rating">
                                <b-rate :value="list.rating" show-score disabled/>
                            </p>
                            <p class="control" style="margin-left: auto">
                                <b-button size="is-small" type="is-danger" icon-left="heart" outlined />
                            </p>
                        </b-field>
                    </div>
                </div>
            </div>
        </template>
    </b-carousel-list>
</template>

<script>
export default {
    data() {
        return {
            test: 0,
            items: [
                {
                    title: 'Slide 1',
                    image: 'https://buefy.org/static/img/placeholder-1280x960.png',
                    rating: 4.4
                },
                {
                    title: 'Slide 2',
                    image: 'https://buefy.org/static/img/placeholder-1280x960.png',
                    rating: 3.5
                },
                {
                    title: 'Slide 3',
                    image: 'https://buefy.org/static/img/placeholder-1280x960.png',
                    rating: 5
                },
                {
                    title: 'Slide 4',
                    image: 'https://buefy.org/static/img/placeholder-1280x960.png'
                },
                {
                    title: 'Slide 5',
                    image: 'https://buefy.org/static/img/placeholder-1280x960.png',
                    rating: 5
                },
                {
                    title: 'Slide 6',
                    image: 'https://buefy.org/static/img/placeholder-1280x960.png',
                    rating: 4
                },
                {
                    title: 'Slide 7',
                    image: 'https://buefy.org/static/img/placeholder-1280x960.png',
                    rating: 2.7
                },
                {
                    title: 'Slide 8',
                    image: 'https://buefy.org/static/img/placeholder-1280x960.png',
                    rating: 1.5
                }
            ]
        }
    },
    methods: {
        info(value) {
            this.test = value
        }
    }
}
</script>

# Custom As indicators

With Breakpoint and Switch like a Gallery.

<template>
    <b-carousel
        :autoplay="false"
        with-carousel-list
        :indicator="false"
        :overlay="gallery"
        @click="switchGallery(true)">
        <b-carousel-item v-for="(item, i) in items" :key="i">
            <figure class="image">
                <img :src="item.image">
            </figure>
        </b-carousel-item>
        <span v-if="gallery" @click="switchGallery(false)" class="modal-close is-large"/>
        <template #list="props">
            <b-carousel-list
                v-model="props.active"
                :data="items"
                v-bind="al"
                @switch="props.switch($event, false)"
                as-indicator />
        </template>
        <template #overlay>
            <div class="has-text-centered has-text-white">
                Hello, I'm an overlay!
            </div>
        </template>
    </b-carousel>
</template>

<script>
export default {
    data() {
        return {
            gallery: false,
            al: {
                hasGrayscale: true,
                itemsToShow: 2,
                breakpoints: {
                    768: {
                        hasGrayscale: false,
                        itemsToShow: 4
                    },
                    960: {
                        hasGrayscale: true,
                        itemsToShow: 6
                    }
                }
            },
            items: [
                {
                    title: 'Slide 1',
                    image: 'https://picsum.photos/id/0/1230/500'
                },
                {
                    title: 'Slide 2',
                    image: 'https://picsum.photos/id/1/1230/500'
                },
                {
                    title: 'Slide 3',
                    image: 'https://picsum.photos/id/2/1230/500'
                },
                {
                    title: 'Slide 4',
                    image: 'https://picsum.photos/id/3/1230/500'
                },
                {
                    title: 'Slide 5',
                    image: 'https://picsum.photos/id/4/1230/500'
                },
                {
                    title: 'Slide 6',
                    image: 'https://picsum.photos/id/5/1230/500'
                },
                {
                    title: 'Slide 7',
                    image: 'https://picsum.photos/id/6/1230/500'
                },
                {
                    title: 'Slide 8',
                    image: 'https://picsum.photos/id/7/1230/500'
                }
            ]
        }
    },
    methods: {
        switchGallery(value) {
            this.gallery = value
            if (value) {
                document.documentElement.classList.add('is-clipped')
            } else {
                document.documentElement.classList.remove('is-clipped')
            }
        }
    }
}
</script>

# API

Carousel

Name
Description
Type
Values
Default
v-modelBinding valueNumber0
animatedTransition effectStringfade, slideslide
intervalInterval of the autoplay, in millisecondsNumber3500
has-dragToggle touch dragging, when touch not detected. Auto switch mouse draggingBooleantrue
autoplayWhether to automatically loop the slidesBooleantrue
pause-hoverPause carousel when autoplay and mouse enterBooleantrue
pause-infoShow information about pause when autoplay and pause-hoverBooleantrue
pause-info-typeType (color) of the pause-info, optionalStringis-white, is-black, is-light, is-dark, is-primary, is-info, is-success, is-warning, is-danger, and any other colors you've set in the $colors list on Sassis-white
pause-textText when pauseStringPause
arrow Display the "next" and "prev" actionBooleantrue
arrow-hoverDisplay the "next" and "prev" action when hover, but hidden on mobileBooleantrue
repeatControls whether the carousel loops around at the start and endBooleantrue
icon-packIcon pack to useStringmdi, fa, fas, far, fab, fad, falmdi
icon-sizeArrow icon size, optionalStringis-small, is-medium, is-large
icon-prevIcon to use for previous arrowStringchevron-left
icon-nextIcon to use for next arrowStringchevron-right
indicatorDisplay the indicator for jumping to specific itemBooleantrue
indicator-backgroundAdds background to indicatorBooleanfalse
indicator-customUse when there are more than 6 images so that the indicator is not too smallBooleanfalse
indicator-custom-sizeImage size of the indicator when the indicator-custom is usedStringis-small, is-mediumis-small
indicator-insideDisplay the indicator inside the carouselBooleantrue
indicator-modeTrigger for action indicatorStringclick, hoverclick
indicator-positionPosition indicator only when indicator-insideStringis-bottom, is-topis-bottom
indicator-styleStyle for indicator of carouselStringis-boxes, is-dots, is-linesis-dots
overlaySwitch like a galleryBooleanfalse
progressDisplay the progress item of carouselBooleanfalse
progress-typeType (color) of the progress, optionalStringis-white, is-black, is-light, is-dark, is-primary, is-info, is-success, is-warning, is-danger, and any other colors you've set in the $colors list on Sassis-primary
with-carousel-listUse when indicator custom with b-carousel-listBooleanfalse

Item

Name
Description
Parameters
clickNon-native click event, will trigger only on an element that should normally not be clickable/focusable

List

Name
Description
Type
Values
Default
v-modelBinding valueNumber0
dataCarousel-list data (any b-image prop can be used)Array
has-dragToggle touch dragging, when touch not detected. Auto switch mouse draggingBooleantrue
has-grayscaleGive a grayscale effect to imgBooleanfalse
has-opacityGive an opacity effect to imgBooleanfalse
repeatReturns carousel to start when active item matches length of dataBooleanfalse
items-to-showCount of items to be showed per view (supports a decimal).Number4
items-to-listCount of items to list when using navigation buttonsNumber1-51
as-indicatorSwitch mode to indicator for carouselBooleanfalse
refreshRefresh for carousel overlayBooleanfalse
arrowDisplay the "next" or "prev" action when first or last itemBooleantrue
arrow-hoverDisplay arrow action when hovered. Hidden on mobileBooleantrue
icon-packIcon pack to useStringmdi, fa, fas, far, fab, fad, falmdi
icon-sizeArrow icon size, optionalStringis-small, is-medium, is-large
icon-prevIcon to use for previous arrowStringchevron-left
icon-nextIcon to use for next arrowStringchevron-right

# Variables

You can use these variables to customize this component.

Name
Description
Default
$carousel-min-heightThe carousel default height before image load120px
$carousel-arrow-backgroundThe carousel arrow background$scheme-main
$carousel-arrow-colorThe carousel color border$primary
$carousel-arrow-icon-spacedThe carousel arrow icon spaced left and right1.5rem
$carousel-arrow-topThe carousel position by top50%
$carousel-indicator-backgroundThe carousel indicator backgroundrgba($scheme-invert, 0.45)
$carousel-indicator-borderThe carousel indicator color border$scheme-main
$carousel-indicator-colorThe carousel indicator color$primary
$carousel-indicator-spacedThe carousel indicator spaced.5rem
$carousel-overlay-backgroundThe carousel background when overlayrgba($scheme-invert, 0.86)
$carousel-overlay-zThe carousel z-index for overlay40

This page is open source. Noticed a typo or something's unclear?

Improve this page on GitHub