V2 is here!

Pretty Vue.js lightbox inspired by fancybox
with zoom, swipe, captions and videos supported.

Important: loop only works when effect is swipe

Getting started

Installation

via npm

npm install --save vue-cool-lightbox

via CDN

<!-- the lightbox uses body-scroll-lock as a dependency -->
<script src="https://cdn.jsdelivr.net/npm/body-scroll-lock/lib/bodyScrollLock.min.jsx"></script>
<script src="https://unpkg.com/vue-cool-lightbox"></script>

<link rel="stylesheet" media="all" href="https://unpkg.com/vue-cool-lightbox/dist/vue-cool-lightbox.min.css" />

Basic Usage

via npm

// use the component
import CoolLightBox from 'vue-cool-lightbox'
import 'vue-cool-lightbox/dist/vue-cool-lightbox.min.css'
 
export default {
  components: {
    CoolLightBox,
  },
}

// or register it globally
import Vue from 'Vue'
import CoolLightBox from 'vue-cool-lightbox'
import 'vue-cool-lightbox/dist/vue-cool-lightbox.min.css'

Vue.use(CoolLightBox)

via CDN

<script>
// register globally
Vue.component('vue-cool-lightbox', window.CoolLightBox.default)
</script>

Examples

Basic

You can swipe the slides, when you swipe to up or to down the lightbox is going to close.

<template>
  <div id="app">
    <CoolLightBox 
      :items="items" 
      :index="index"
      @close="index = null">
    </CoolLightBox>

    <div class="images-wrapper">
      <div
        class="image"
        v-for="(image, imageIndex) in items"
        :key="imageIndex"
        @click="index = imageIndex"
        :style="{ backgroundImage: 'url(' + image + ')' }"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      items: [
        'https://cosmos-images2.imgix.net/file/spina/photo/20565/191010_nature.jpg?ixlib=rails-2.1.4&auto=format&ch=Width%2CDPR&fit=max&w=835',
        'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/nature-quotes-1557340276.jpg?crop=0.666xw:1.00xh;0.168xw,0&resize=640:*',
      ],
      index: null
    };
  },
};
</script>

Fade effect

<template>
  <div id="app">
    <CoolLightBox 
      :items="items" 
      :index="index"
      :effect="'fade'"
      @close="index = null">
    </CoolLightBox>

    <div class="images-wrapper">
      <div
        class="image"
        v-for="(image, imageIndex) in items"
        :key="imageIndex"
        @click="index = imageIndex"
        :style="{ backgroundImage: 'url(' + image + ')' }"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      items: [
        'https://cosmos-images2.imgix.net/file/spina/photo/20565/191010_nature.jpg?ixlib=rails-2.1.4&auto=format&ch=Width%2CDPR&fit=max&w=835',
        'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/nature-quotes-1557340276.jpg?crop=0.666xw:1.00xh;0.168xw,0&resize=640:*',
      ],
      index: null
    };
  },
};
</script>

With captions

<template>
  <div id="app">
    <CoolLightBox 
      :items="items" 
      :index="index"
      @close="index = null">
    </CoolLightBox>

    <div class="images-wrapper">
      <div
        class="image"
        v-for="(image, imageIndex) in items"
        :key="imageIndex"
        @click="index = imageIndex"
        :style="{ backgroundImage: 'url(' + image.src + ')' }"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      items: [
        {
          title: 'In nature, nothing is perfect and everything is perfect',
          description: "Photo by Lucas",
          src: 'https://cosmos-images2.imgix.net/file/spina/photo/20565/191010_nature.jpg?ixlib=rails-2.1.4&auto=format&ch=Width%2CDPR&fit=max&w=835',
        },
        {
          title: 'a beautiful mountain view',
          description: "Photo by Facundo",
          src: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/nature-quotes-1557340276.jpg?crop=0.666xw:1.00xh;0.168xw,0&resize=640:*',
        },
      ],
      index: null
    };
  },
};
</script>

Zoom example

Important: The zoom is only activated when the image is bigger than the height or width of the screen. On mobile sizes is disabled at the moment.

<template>
  <div id="app">
    <CoolLightBox 
      :items="items" 
      :index="index"
      @close="index = null">
    </CoolLightBox>

    <div class="images-wrapper">
      <div
        class="image"
        v-for="(image, imageIndex) in items"
        :key="imageIndex"
        @click="index = imageIndex"
        :style="{ backgroundImage: 'url(' + image.src + ')' }"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      items: [
        {
          title: 'In nature, nothing is perfect and everything is perfect',
          description: "Photo by Lucas",
          src: 'https://images.unsplash.com/photo-1420593248178-d88870618ca0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80',
        },
        {
          title: 'A beautiful mountain view',
          description: "Photo by Facundo",
          src: 'https://upload.wikimedia.org/wikipedia/commons/4/42/Shaqi_jrvej.jpg',
        },
      ],
      index: null
    };
  },
};
</script>

Zoom bar

<template>
  <div id="app">
    <CoolLightBox 
      :items="items" 
      :index="index"
      :useZoomBar="true"
      @close="index = null">
    </CoolLightBox>

    <div class="images-wrapper">
      <div
        class="image"
        v-for="(image, imageIndex) in items"
        :key="imageIndex"
        @click="index = imageIndex"
        :style="{ backgroundImage: 'url(' + image + ')' }"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      items: [
        'https://cosmos-images2.imgix.net/file/spina/photo/20565/191010_nature.jpg?ixlib=rails-2.1.4&auto=format&ch=Width%2CDPR&fit=max&w=835',
        'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/nature-quotes-1557340276.jpg?crop=0.666xw:1.00xh;0.168xw,0&resize=640:*',
      ],
      index: null
    };
  },
};
</script>

Fullscreen

<template>
  <div id="app">
    <CoolLightBox 
      :items="items" 
      :index="index"
      :fullScreen="true"
      @close="index = null">
    </CoolLightBox>

    <div class="images-wrapper">
      <div
        class="image"
        v-for="(image, imageIndex) in items"
        :key="imageIndex"
        @click="index = imageIndex"
        :style="{ backgroundImage: 'url(' + image + ')' }"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      items: [
        'https://cosmos-images2.imgix.net/file/spina/photo/20565/191010_nature.jpg?ixlib=rails-2.1.4&auto=format&ch=Width%2CDPR&fit=max&w=835',
        'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/nature-quotes-1557340276.jpg?crop=0.666xw:1.00xh;0.168xw,0&resize=640:*',
      ],
      index: null
    };
  },
};
</script>

Videos

<template>
  <div id="app">
    <CoolLightBox 
      :items="items" 
      :index="index"
      @close="index = null">
    </CoolLightBox>

    <div class="images-wrapper">
      <div
        class="image"
        v-for="(image, imageIndex) in items"
        :key="imageIndex"
        @click="index = imageIndex"
        :style="{ backgroundImage: 'url(' + image.thumb + ')' }"
      ></div>
    </div>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      items: [
        {
          title: 'In nature, nothing is perfect and everything is perfect',
          description: "Photo by Lucas",
          thumb: 'https://cosmos-images2.imgix.net/file/spina/photo/20565/191010_nature.jpg?ixlib=rails-2.1.4&auto=format&ch=Width%2CDPR&fit=max&w=835',
          src: 'https://www.youtube.com/watch?v=d0tU18Ybcvk',
        },
        {
          title: 'A beautiful mountain view',
          description: "Photo by Facundo",
          src: 'https://vimeo.com/43338103',
          thumb: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/nature-quotes-1557340276.jpg?crop=0.666xw:1.00xh;0.168xw,0&resize=640:*',
        },
        {
          title: 'In nature, nothing is perfect and everything is perfect',
          description: "Photo by Lucas",
          thumb: 'https://scx1.b-cdn.net/csz/news/800/2019/1-nature.jpg',
          src: '/video.mp4',
        },
      ],
      index: null
    };
  },
};
</script>

API

Items attributes

NameDescription
srcUrl of the image/video
altalt attribute of the image
titleSlide title
descriptionSlide description
thumbThumb url used in thumbs block
mediaTypeDefines media type
autoplaySetting it to true it will work with youtube, vimeo or any web video format.

Props

NameTypeDefaultDescription
indexNumberIndex of items to open
itemsArrayArray of images/videos
loopBooleantrueEnables looping through items
effectStringswipeEffect on slide, could be swipe or fade
fullScreenBooleanfalseAllow users to fullscreen mode
slideshowBooleantrueEnables lighbox slideshow
slideshowColorBarString#fa4242Color of the slideshow progress bar
slideshowDurationNumber3000Duration of slides when slideshow is running (in ms)
srcNameStringsrcName of the prop to use as image/video url
srcThumbStringthumbName of the prop to use as image/video thumb
overlayColorStringrgba(30, 30, 30, .9)Overlay color
zIndexNumber9999.cool-lightbox z-index
thumbsPositionStringrightDefines thumbs position, could be right or bottom
youtubeCookiesBooleantrueif is setted to false it will use https://www.youtube-nocookie.com/embed/YOUTUBE_ID for youtube videos
useZoomBarBooleanfalseenables a zoom bar similar with the zoom as in Slack
enableWheelEventBooleanfalseenables change slides on mouse wheel events
closeOnClickOutsideMobileBooleanfalseenables close lightbox when the user clicks outside the image/video/iframe on mobile devices
srcMediaTypeString'mediaType'media type src for each item
dirString'ltr'if you set it to 'rtl' it will work fine with sites where the body or any wrapper has direction: rtl
enableScrollLockBooleantrueBy default when the lightbox is open the body is locked
translationsObject

{
  previous: 'Previous',
  next: 'Next',
  showThumbNails: 'Show thumbnails',
  playSlideShow: 'Play slideshow',
  fullScreen: 'Fullscreen',
  close: 'Close' 
} 

Translation to allow simple locale settings

Events

NameAttributesListen toDescription
OnChange(indexItem)@on-changeEmitted when the lightbox changes the item index
OnOpen(indexItem)@on-openEmitted when the lightbox is opened
Close(indexItem)@closeEmitted when the lightbox is closed

Slots

NameDescription
icon-previousPrevious icon
icon-nextNext icon
closeClose icon
loadingLoading animation

Acknowledgements

Thanks to all these people who helped me to do some great features :)

Online examples

It makes me really happy to see online sites that are using the component: