Our Blog

Lightbox galleries using Magnific Popup

by Harris Konstantourakis on March 27, 2015 21 comments

Learn how to create amazing lightbox effects and galleries using the popular Magnific Popup javascript library.

Many years have passed since the original Lightbox plugin was first released, with a plethora of scripts following up offering similar functionality. In this tutorial we dive into the world of the popular Magnific Popup library created by Dmitry Semenov and explore its features and functionality.

For this tutorial, we will assume the reader has some basic experience with html and javascript – enough to add a script to his html document and to add classed to the html elements of his choice. First grab the the latest versions of the library javascript and css from here ( you can get the latest compiled versions from the /dist project folder ) and add them to your project. Do not forget to include jQuery too, as it is needed as a prerequisite.

Having included the necessary scripts and styles, create a new javascript file and add the following to the documents ready event inside the script:

$('.magnific').magnificPopup({
  type:'image',
  removalDelay: 300,
  mainClass: 'mfp-fade'
});

$('.magnific-youtube').magnificPopup({
  disableOn: 700,
  type: 'iframe',
  mainClass: 'mfp-fade',
  removalDelay: 300,
  preloader: false,
  fixedContentPos: false
});

The above script serves two purposes: It locates all elements in your document that have a class magnific and opens their destination in an image popup. It also locates all elements that have a class magnific-youtube and opens their destination in an iframe. This will serve us well if we want to open a whole video inside a lightbox.

Having implemented our scripts, we are ready to add some content to our html document!
Paste the following code somewhere inside your html file:

<p>
  Clicking this link will open an image in a magnific popup
</p>
<a href="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-2.jpg" class="magnific">
  Open image popup
</a>
 <p>
  Clicking this image will open a video in a magnific popup
</p>
<a href="https://www.youtube.com/watch?v=pzot1TWuutY" class="magnific-youtube">
   <img src="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-2.jpg" width="300" height="200" />
</a>

What did we do in the code above ? First, we wrap an anchor around the element that we want to serve as our lightbox trigger. This means that when the visitor of the page clicks on this element, the lightbox popup will appear. This element can be anything. In the code above as you can see we used some simple text as the first trigger element, and an image as the second trigger element.

But what kind of lightbox are we going to open for each element ? We have to specify that in the anchor that we wrap around it. How ? By giving it a class ! This is where the class selectors in the script we added earlier come into play. Give the anchor a magnific class in order to instruct it that it will need to open an image in the lightbox. By giving it a magnific-youtube class ( as we did in the second anchor ) you are telling magnific that this anchor will need to open an iframe and render a video.

As you can probably guess by now, the href in each anchor tag specifies the item that will appear in our lightbox. So in the first scenario, we link to an image, but we link to a youtube video in the second scenario. You can try the above example along with further combinations in the plunker below:

See the Pen ogmOZm by Harris (@harconst) on CodePen.

Now that we know how to display a magnific popup anywhere in our document, it’s time to move on to more fancy stuff : Galleries!

Modify the script you created earlier and append the following to the documents ready event:

$('.magnific-gallery').each(function(index , value){
  var gallery = $(this);
  var galleryImages = $(this).data('links').split(',');
    var items = [];
    for(var i=0;i<galleryImages.length; i++){
      items.push({
        src:galleryImages[i],
        title:''
      });
    }
    gallery.magnificPopup({
      mainClass: 'mfp-fade',
      items:items,
      gallery:{
        enabled:true,
        tPrev: $(this).data('prev-text'),
        tNext: $(this).data('next-text')
      },
      type: 'image'
    });
});

The above code adds new functionality to our script: Any anchor that has the class magnific-gallery will be able to open a gallery popup containing multiple images upon clicking the containing trigger element. The containing element can still be any element of our choice. The script expects the links to the images as comma-separated links in the data-links attribute of the anchor.

Lets insert a gallery to our html document:

<p>
  Clicking this image will open a lightbox gallery in a magnific popup
</p>
<a data-links="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-2.jpg,http://www.oxygenna.com/wp-content/uploads/2014/11/blog-0.jpg,http://www.oxygenna.com/wp-content/uploads/2014/11/blog-1.jpg,http://www.oxygenna.com/wp-content/uploads/2014/11/blog-3.jpg" class="magnific-gallery">
  <img src="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-0.jpg" width="350"/>
</a>

The same basic principles stand: We inserted a trigger element ( a simple image in this case ), and we wrapped an anchor around it, with the class magnigic-gallery. Having done that, we inserted the links to four images separated by commas in the data-links attribute of the anchor. That’s it! You can play around with this example in the plunker below:

See the Pen wBNbNx by Harris (@harconst) on CodePen.

We can now open multiple images in a single popup as a gallery! But what if we wanted to grab both images and videos from anchors all over our page and display them in the same gallery? Edit your script file again and append the following code:

$('.magnific-all').each(function() {
  var $container = $(this);
  var $imageLinks = $container.find('.item');

  var items = [];
  $imageLinks.each(function() {
  	var $item = $(this);
    var type = 'image';
    if ($item.hasClass('magnific-youtube')) {
      type = 'iframe';
    }
    var magItem = {
      src: $item.attr('href'),
      type: type
    };
    magItem.title = $item.data('title');
    items.push(magItem);
	});

  $imageLinks.magnificPopup({
    mainClass: 'mfp-fade',
    items: items,
    gallery:{
        enabled:true,
        tPrev: $(this).data('prev-text'),
        tNext: $(this).data('next-text')
    },
    type: 'image',
    callbacks: {
      beforeOpen: function() {
        var index = $imageLinks.index(this.st.el);
        if (-1 !== index) {
          this.goTo(index);
        }
      }
    }
  });
});

The above script adds the functionality I mentioned. It looks for a container element in your page ( an element that has the class mangific-all ) and finds all the anchors that wrap around a trigger element. The anchors inside this container must now have an extra class ( in order for the script to distinguish them from other anchors ) item.

We are almost done! Lets add some content to our document. We will add the usual anchors (that now have the new class item as well ) with their containing elements and we will wrap a section around all those elements that will serve as a container, by giving it the class magnific-all :

<section class="magnific-all">
  <div class="half left">
    <a href="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-1.jpg" class="magnific item" data-title="item 1">
      Open image popup
    </a>
    <p></p>
    <a href="https://www.youtube.com/watch?v=pzot1TWuutY" class="magnific-youtube item" data-title="item 2">
      <img src="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-2.jpg" width="300" height="200" />
    </a>
  </div>
  <div class="half right">
    <a href="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-3.jpg" class="magnific item" data-title="item 3">Open video popup</a>
    <p></p>
    <a href="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-4.jpg" class="magnific item" data-title="item 4">
      <img src="http://www.oxygenna.com/wp-content/uploads/2014/11/blog-3.jpg" width="300" height="200" />
    </a>
  </div>
</section>

Notice that we added a new attribute to the anchors called data-title that the script picks up in order to render a caption below each element!

You can fiddle around with the last example in the plunker below:

See the Pen VYgJvM by Harris (@harconst) on CodePen.

That’s it! We hope you enjoyed this tutorial and find it helpful, as the possibilities and use cases are endless! You can view implementations of the functionality demonstrated in this tutorial in all of our themes. Take a look!

Harris KonstantourakisLightbox galleries using Magnific Popup

Related Posts

Take a look at these posts

21 comments

Join the conversation
  • alvaro rosado - August 21, 2015 reply

    what if i have more than two triggers with data-link, i still get the same gallery.

    Harris Konstantourakis - August 25, 2015 reply

    Hi Alvaro.
    As long as you change the data-link properly, it will work fine for multiple pop-up galleries. See demo here: http://codepen.io/harconst/pen/qdeoMj

  • Brett - September 4, 2015 reply

    Hi

    I’m new to CSS and javascript and these are nube’s questions but 1) Can you test Magnific Popup through your browser alone without having to load everyhing onto a web server? If not why?
    2) I’m confused by your use of href and img src. Do you need two versions of the same image and if so why? When reading your example on occasion you did not supply an img src and left the href on its own and on other occasions did include both eg when you used a utube clip – what is the relationship between the two?

    Thanks for any clarification you can provide. Kind regards Brett.

    Harris Konstantourakis - September 7, 2015 reply

    Hi Brett!
    1) Of course you can test it without a server. You just grab the html, css, and js code I have in my examples above, as well as the magnific library, and add them all in their own files inside the same folder. Then you simply double click at the html file.
    2) The href always specifies what link that will open in the popup. When we wrap the a around an image, the href can have the same link as the image source ( which means that the same image will open in the popup ), or it can be a completely different one. That will allow you to open ( in example ) a youtube video once you click on your image.

    Brett - September 12, 2015 reply

    Hi Harris,
    Thanks very much – I understand now.
    I will try doing what you suggested.
    Kind Regards
    Brett

    Vincent - October 16, 2015 reply

    Hi,is it possible to raolnmdy display catalog gallery (photo and title) in the posts, each time when visitor refresh page? What I mean is, it will be changed the order of the items each time when page is refreshed.Thanks

    Harris Konstantourakis - October 22, 2015

    If I understand correctly Vincent, you want the gallery images from the last example to appear in a random order ? If so, you could replace the following:

    $imageLinks.each(function() ...{

    with something like this:

    $imageLinks.sort(function(){
    return Math.random()*10 > 5 ? 1 : -1;
    }).each(function(){

    in order to randomly sort the images before opening them in a popup. Did not try the above, but that should do the trick!

  • Peter Rambeck - October 14, 2015 reply

    Hi Harris,
    I really like what can be done with the MFP.
    This is super great thanks,
    Unfortunately I’m a little shaky on the functions and implementation part, but would like to as you -> In a WordPress site with Visual Composer editor, somehow both MFP is integrated as well as their own pop up container, ( sorry to say, but absolutely useless. On a smartphone you simply can’t see the image!)
    Though if, or how, can I block or switch off their native container and implement MFP with all the css goodies here?
    I have tried with the plugin but it comes out quite badly visually, unaligned and not functioning well.
    If you can assist I would be grateful,
    Thank, Peter

    Harris Konstantourakis - October 22, 2015 reply

    Hi Peter,
    The css you see in the above examples is the default css that comes with the magnific popup library. If things don’t render properly in your theme, there might be multiple reasons for that :

    • The author might not be including the magnific popup styles for some reason
    • There might be a conflict between magnific and the other container that you mentioned

    I would suggest that you ask the theme authors to help you : Disable the custom image container that you don’t like, and make sure that the magnific popup default css is properly included when your theme loads. That should get you on the right track!

    Peter Rambeck - October 22, 2015 reply

    Thanks Harris.

  • Gunnar - October 21, 2015 reply

    Thanks a lot for your very effective (not time-consuming) mfp-guide! šŸ™‚
    Cheers,
    Gun

    Harris Konstantourakis - October 22, 2015 reply

    Glad you enjoyed it!
    Planning to publish more fun guides soon, stay tuned Gunnar!

  • Brett Pateman - October 27, 2015 reply

    Hi Harris

    When applying your second example – the one with the data-links – Is there a way you can get the image’s title attribute or data-title to appear?

    Regards

    Brett

    Harris Konstantourakis - November 5, 2015 reply

    Hi Brett,

    I don’t see why not. The first thing that comes to mind is doing something like this:
    codepen

    Brett - December 9, 2015 reply

    Hi Harris,

    I have been away and seen this now.

    Thank you very much for this it’s a real education.

    Kind Regards

    Brett

  • athar - March 16, 2016 reply

    Hi , Thank you for this helpful tutorial. I have copy pest your code. All well. But the video is not loading. Whats the problem? Please help me.

  • Chad - February 9, 2017 reply

    Hi Harris,

    How exactly should i structure my html and javascript if i wanted to display a simple image gallery with each image displayed serving as part of the same gallery, all while displaying a title and a description . I know it’s something very simple but i’m very new to javascript and could use some help. I’ve gotten almost everything to work except for two major steps, displaying a description below the title, and following an image to the correct path. For some reason when i click on an image, image 6 for example, my gallery always opens up to image 1. I believe this do to my html structure, but my lack of javascript knowledge makes it difficult to adjust accordingly after i attempt changes.

  • treddinwater - February 23, 2017 reply

    Nice Work. Thanks. The nav arrows on the outside look a little odd on a wide monitor. I searched around and and found by adding: callbacks: {

    buildControls: function() {
    // re-appends controls inside the main container
    this.contentContainer.append(this.arrowLeft.add(this.arrowRight));
    }
    along with a comma after the last call to ‘image’ the arrows are now on top of the image. Hope this helps someone.

  • treddinwater - February 23, 2017 reply

    While I’m thinking about it. How could you add a zoom effect? My attempts are breaking it.

  • Lukas - May 8, 2017 reply

    Hello, I am using wp magnific popup on my site. I really like it, but how can I make it work on ajax loaded pages? For some reason the pop up is not triggered after the page gets loaded with ajax.
    Thank you very much for any help

    Harris Konstantourakis - November 24, 2017 reply

    Hi Lukas,

    apologies for such a late reply, this is something worth commenting on though: Your issue is that at the moment the script executes your content / page / dom has not yet loaded, thus the script can not locate the elements that you want to target.

    If one loads the page through ajax, the script will have to be executed after the page has loaded and the elements are part of the dom.

    Hope that helps someone who stumbles upon this issue in the future.

Join the conversation