Powerful and Multi-Functional jQuery Lightbox Plugin - Magnific Popup

File Size: 314 KB
Views Total: 25247
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Powerful and Multi-Functional jQuery Lightbox Plugin - Magnific Popup

Magnific Popup is a responsive lightbox and dialog jQuery plugin that opens images, iframes, inline HTML, and Ajax content in a centered overlay.

Magnific Popup is officially deprecated. The author no longer accepts feature requests—only critical or security fixes. For new projects, the author recommends the native <dialog> element for basic modals or PhotoSwipe for advanced image galleries.

Features:

  • Content inside the lightbox resizes via CSS.
  • CSS3 based open/close animations.
  • Images display before they finish loading.
  • Supports image, iframe, inline, and ajax content.
  • Switch between items with arrow navigation, keyboard support, and configurable lazy-loading of adjacent items.
  • Built-in retina module swaps image sources based on window.devicePixelRatio.
  • Optional zoom module animates the popup open from a thumbnail element.
  • Accepts a pixel-width threshold or a custom function.
  • A micro-template engine reuses DOM elements across popups that share the same structure.
  • All user-facing strings are configurable.

Basic Usage:

1. Load the latest jQuery library and Magnific Popup Plugin in the HTML document.

<!-- Magnific Popup stylesheet -->
<link rel="stylesheet" href="/path/to/magnific-popup.css">

<!-- jQuery Library -->
<script src="/path/to/cdn/jquery.min.js"></script>

<!-- Magnific Popup core script -->
<script src="/path/to/jquery.magnific-popup.js"></script>

2. Create a basic image lightbox.

<a href="example.jpg" class="photo-trigger">View Photo</a>
$(document).ready(function() {
  $('.photo-trigger').magnificPopup({
    type: 'image' // Tell the plugin to treat the href as an image source
  });
});

3. To build a gallery lightbox, initialize on the parent container and set delegate to the child selector. Pass gallery: { enabled: true } to activate arrow navigation.

<div class="project-gallery">
  <a href="1.jpg">Photo 1</a>
  <a href="2.jpg">Photo 2</a>
  <a href="3.jpg">Photo 3</a>
  ...
</div>
$('.project-gallery').magnificPopup({
  delegate: 'a',
  type: 'image',
  gallery: {
    enabled: true, 
    preload: [1, 2]
  },
  image: {
    titleSrc: 'title'
  }
});

4. You can store the popup content anywhere in the HTML. Add `mfp-hide` to keep it hidden until triggered.

<!-- Hidden popup content -->
<div id="contact-modal" class="popup-container mfp-hide">
  <h3>Get in Touch</h3>
  <p>Fill out the form below and we'll respond within 24 hours.</p>
  <input type="text" placeholder="Your name">
</div>

<!-- Trigger link -->
<a href="#contact-modal" class="modal-trigger">Open Contact Form</a>
/* Style the popup wrapper */
.popup-container {
  position: relative;
  background: #fff;
  padding: 30px;
  width: auto;
  max-width: 520px;
  margin: 20px auto;
  border-radius: 4px;
}
$('.modal-trigger').magnificPopup({
  type: 'inline',
  midClick: true
});

5. Display YouTube/Vimeo videos or any iframe content in the lightbox.

<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" class="video-trigger">Watch Demo</a>
$('.video-trigger').magnificPopup({
  type: 'iframe',
  iframe: {
    // YouTube and Vimeo patterns are pre-configured
    // autoplay=1 is appended to the embed URL by default
    patterns: {
      youtube: {
        index: 'youtube.com/',
        id: 'v=',
        src: '//www.youtube.com/embed/%id%?autoplay=1'
      },
      vimeo: {
        index: 'vimeo.com/',
        id: '/',
        src: '//player.vimeo.com/video/%id%?autoplay=1'
      }
    }
  }
});

6. The plugin also supports AJAX content:

<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" class="video-trigger">Watch Demo</a>
$('.ajax-trigger').magnificPopup({
  type: 'ajax',
  callbacks: {
    parseAjax: function(mfpResponse) {
      // Filter the loaded HTML to display only the #detail-panel element
      mfpResponse.data = $(mfpResponse.data).find('#detail-panel');
    },
    ajaxContentAdded: function() {
      // Content is now in the DOM — safe to bind events here
      console.log('Ajax content ready:', this.content);
    }
  }
});

7. Call $.magnificPopup.open() directly to trigger a popup from JavaScript:

$('#open-promo-btn').on('click', function() {
  $.magnificPopup.open({
    items: {
      src: '1.jpg'
    },
    type: 'image',
    closeOnContentClick: true
  });
});

8. All configuration options:

General Options

  • type (string): Content type. Accepts 'image', 'iframe', 'inline', or 'ajax'. Default: 'inline'.
  • disableOn (number | function): If the window width is below this pixel value, the popup does not open and the element's default behavior runs. Pass a function that returns true to open or false to block. Default: null.
  • key (string): Unique identifier for a popup group that shares the same DOM structure. Magnific Popup caches the template and reuses it. Default: null.
  • midClick (boolean): When true, the popup opens on a middle-click or Ctrl/Cmd+click. Default: false.
  • mainClass (string): CSS class(es) added to the popup wrapper and the dark overlay. Use this to scope animation or theme styles. Default: ''.
  • preloader (boolean): Shows a status indicator element in the DOM at all times. Its inner text changes based on load state. Default: true.
  • focus (string): CSS selector of the element inside the popup that receives focus on open. Default: '' (focuses the popup itself).
  • closeOnContentClick (boolean): Closes the popup when the user clicks the content area. Recommended for image-only popups. Default: false.
  • closeOnBgClick (boolean): Closes the popup when the user clicks the dark overlay. Default: true.
  • closeBtnInside (boolean): Places the close button inside the popup content. Adds mfp-close-btn-in to the wrapper. Default: true.
  • showCloseBtn (boolean): Controls close button visibility. Default: true.
  • enableEscapeKey (boolean): Controls whether the Escape key closes the popup. Default: true.
  • modal (boolean): When true, sets closeOnContentClick, closeOnBgClick, showCloseBtn, and enableEscapeKey all to false. The popup can only be closed via the API. Default: false.
  • alignTop (boolean): Adds mfp-align-top to the popup, which pins it to the top of the viewport. Default: false.
  • index (number): Starting index for gallery mode. Ignored when initializing from a DOM element. Default: null.
  • fixedContentPos ('auto' | boolean): Position strategy for popup content. 'auto' disables fixed position on browsers that handle it poorly. Default: 'auto'.
  • fixedBgPos ('auto' | boolean): Position strategy for the dark overlay. Set to true when animating the overlay to keep its size small. Default: 'auto'.
  • overflowY (string): Controls the popup's vertical scrollbar. Accepts any CSS overflow-y value ('auto', 'scroll', 'hidden'). Default: 'auto'.
  • removalDelay (number): Milliseconds to wait before removing the popup from the DOM. Match this to your CSS transition duration. Default: 0.
  • closeMarkup (string): HTML string for the close button. %title% is replaced with the tClose value. Default: <button title="%title%" type="button" class="mfp-close">&#215;</button>.
  • prependTo (element): The DOM element the popup appends to. Change this for ASP.NET form scoping. Default: document.body.
  • autoFocusLast (boolean): When true, the element that was focused before the popup opened regains focus after it closes. Default: true.
  • allowHTMLInTemplate (boolean): Allows HTML in the popup's source template (e.g., captions under images). Enable with caution — sanitize user-generated content. Default: false.
  • allowHTMLInStatusIndicator (boolean): Allows HTML in the status indicator text (loading messages, error strings). Default: false.

Gallery Options (nested under gallery: {})

  • enabled (boolean): Activates gallery mode with arrow navigation. Default: false.
  • preload (array): Two-integer array. First value: items to preload before current. Second: items to preload after current. E.g., [1, 3]. Default: [0, 2].
  • navigateByImgClick (boolean): Clicking the image advances to the next item. Default: true.
  • arrowMarkup (string): HTML markup for the navigation arrows. %dir% is replaced with prev or next, %title% with tPrev or tNext. Default: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>'.
  • tPrev (string): title attribute for the left arrow button. Default: 'Previous (Left arrow key)'.
  • tNext (string): title attribute for the right arrow button. Default: 'Next (Right arrow key)'.
  • tCounter (string): Markup for the position counter. Uses %curr% and %total% tokens. Default: '<span class="mfp-counter">%curr% of %total%</span>'.

Image Options (nested under image: {})

  • markup (string): Full HTML markup of the image popup. .mfp-img is replaced with the <img> tag; .mfp-close with the close button.
  • cursor (string | null): CSS class added to <body> to show a zoom-out cursor. Set to null to turn it off. Default: 'mfp-zoom-out-cur'.
  • titleSrc (string | function): Attribute name on the trigger element that holds the caption, or a function that receives the item and returns a string.
  • verticalFit (boolean): Fits the image to the vertical height of the viewport. Default: true.
  • tError (string): Message displayed when an image fails to load. Default: 'The image could not be loaded.'.

Iframe Options (nested under iframe: {})

  • markup (string): HTML markup of the iframe popup. mfp-close is replaced with the close button.
  • patterns (object): An object of service definitions. Each key is a service name with index (URL detection string), id (URL split string or function), and src (embed URL template using %id%). Extend this object to add support for any custom video platform.
  • srcAction (string): Defines which element and attribute receive the embed URL. Default: 'iframe_src' (sets the src attribute on the iframe element).

Ajax Options (nested under ajax: {})

  • settings (object | null): Passed directly to $.ajax(). Use this for headers, cache control, or async settings. Default: null.
  • cursor (string): CSS class added to <body> during the request, typically a loading cursor. Default: 'mfp-ajax-cur'.
  • tError (string): Message displayed when the request fails. May contain %curr% and %total% in gallery mode. Default: 'The content could not be loaded.'.

9. API methods:

// Open a popup directly
// Second argument sets the starting index for gallery mode.
$.magnificPopup.open({
  items: { src: 'photos/hero.jpg' },
  type: 'image'
}, 0);

// Close the currently active popup.
$.magnificPopup.close();

// Access the instance for advanced control.
// The instance is available only after at least one popup has been opened.
var mp = $.magnificPopup.instance;

// Close the popup via the instance.
mp.close();

// Navigate to the next item in the gallery.
mp.next();

// Navigate to the previous item in the gallery.
mp.prev();

// Jump to a specific item index (zero-based).
mp.goTo(2);

// Re-render popup content after programmatically modifying the items array.
mp.updateItemHTML();

// Update the popup's status indicator manually.
// First param: 'loading', 'error', or 'ready'. Second: display text.
mp.updateStatus('error', 'The file could not be found.');

// You can also invoke methods via the jQuery plugin after initialization.
$('.photo-trigger').magnificPopup('open');
$('.photo-trigger').magnificPopup('open', 3); // open at index 3
$('.photo-trigger').magnificPopup('goTo', 1);
$('.photo-trigger').magnificPopup('next');

10. Callbacks & events:

$('.gallery-item').magnificPopup({
  type: 'image',
  callbacks: {

    // Fires at the start of popup initialization, before the DOM is built.
    beforeOpen: function() {
      console.log('Popup initializing');
    },

    // Fires for each target element when its source is being parsed.
    // Use item.src to rewrite the source URL.
    elementParse: function(item) {
      console.log('Parsing source for:', item.el);
    },

    // Fires each time the popup content changes (e.g., gallery navigation).
    change: function() {
      console.log('Active item:', this.currItem);
    },

    // Fires when the popup layout changes height.
    resize: function() {
      console.log('Popup resized');
    },

    // Fires when the popup is fully open and visible.
    open: function() {
      console.log('Popup opened');
    },

    // Fires when close is initiated but before the removal delay timer starts.
    beforeClose: function() {
      console.log('Close initiated');
    },

    // Fires when the removalDelay timer finishes.
    close: function() {
      console.log('Popup removal started');
    },

    // Fires after the popup element is fully removed from the DOM.
    afterClose: function() {
      console.log('Popup removed from DOM');
    },

    // Fires each time content changes. Exposes the template, values, and item.
    markupParse: function(template, values, item) {
      // Modify values to alter rendered markup dynamically
    },

    // Fires when the status indicator state changes.
    // data.status: 'loading' | 'error' | 'ready'. data.text: display string.
    updateStatus: function(data) {
      console.log('Status:', data.status, data.text);
    },

    // Fires when the image in the current popup finishes loading.
    imageLoadComplete: function() {
      console.log('Image ready');
    },

    // Ajax only: fires after the response is received. Modify mfpResponse.data
    // here to filter or transform the loaded HTML.
    parseAjax: function(mfpResponse) {
      mfpResponse.data = $(mfpResponse.data).find('#popup-body');
    },

    // Ajax only: fires after the content is appended to the DOM.
    ajaxContentAdded: function() {
      console.log('Ajax content in DOM:', this.content);
    }
  }
});

// All callbacks are also available as jQuery events on the trigger element.
// Event names are camelCased with "mfp" prefix: 'open' → 'mfpOpen'.
$('.gallery-item').on('mfpOpen', function() {
  console.log('Opened via event listener');
});

$('.gallery-item').on('mfpBeforeClose', function() {
  console.log('About to close');
});

Alternatives:

Changelog:

v1.2.0 (2026-03-12)

  • Bugfixes
  • Update doc

v0.9.9 (2013-10-26)

  • Popup instance object is now available even before the first $.fn.magnificPopup call.
  • Methods _onFocusIn and _setFocus are now public, to allow overriding.

v0.9.8 (2013-10-26)

  • Added figure and figcaption elements to image markup.
  • To avoid "jump" of content background, gap from right side (that "replaces" the scrollbar) is added with help of margin, instead of padding.
  • Function that checks if the clicked element should close popup or not is now public (so it can be overridden with your own logic).
  • Working on a new module: the exact copy of native fullscreen Android/iOS gallery, with touch/zoom/pan e.t.c., will publish branch soon (©Blizzard).

v0.9.7 (2013-10-10)

  • CSS: removed outline on buttons.
  • Allow multiple string tokens to be passed in gallery variables like %curr% of %total% and %title% .
  • A few small changes to Grunt build, grunt-contrib-sass > grunt-sass. 

v0.9.6 (2013-09-30)

  • Fixed bug: options object that you pass to popup gets modified after the initialization
  • Fixed bug: zoom module creates global variable.
  • Fixed bug: gallery from AJAX popups stacks content if it's switched before loading has finished.
  • Indented and combined SCSS classes (thanks to @nschonni).
  • $.magnificPopup.close() now doesn't throw an exception if there's no instance (thanks to @mjlescano).

v0.9.5 (2013-08-22)

  • Fixed bug: built-in tab focus in popup works incorrectly (caused by 0.9.3 update).
  • Fixed bug: error in IE7 when minified version of script is used with some versions of jQuery.
  • Fixed bug: DOM exception in Chrome when using gallery mode with some versions of jQuery.

v0.9.3 (2013-07-17)

  • Fixed blurry arrows in FF (#142)
  • Added lazyLoadError callback.
  • Popup now prevents closing if the clicked element is remvoved from DOM.
  • overflow:hidden is now applied to html instead of body.
  • Increased default z-index to from 500 to 1040.

v0.9.0 (2013-07-03)

  • Added modal option which disables all default ways to close the popup, learn more in docs. 
  • Added beforeClose event.
  • Added imageLoadComplete event.
  • Removed jQuery event alias calls. 
  • Cleaned some duplicate styles in CSS. 

v0.8.9 (2013-06-05)

  • Fix: inline element that is created dynamically causes exception in jQuery 1.8.x.
  • Fix: incorrect detection of _hasScrollBar if body has defined height style.
  • Fix: body styles are kept after popup is closed.
  • Fix: close icon is aligned incorrectly with iframe type.
  • responseText is deprected. Argument of callback parseAjax - obj.responseText is now deprected, but you can still access it via obj.xhr.responseText. Instead of it, please use obj.data to modify your output.
  • Sass: changed variables to be default declarations to support front-loaded settings. i.e. You can override options by adding _settings.scss file near main.scss with your new options.
  • Added: afterClose event.
  • Added: ajaxContentLoaded event.
  • Added: Bower support.

v0.8.8 (2013-05-25)

  • Fix: you can now put link inside popup that will open another popup.
  • Fix: incorrect index when opening popup that is already opened from multiple DOM elements.

v0.8.7 (2013-05-19)

  • Fixed #62 - IE9 HTML5 YouTube player playing audio after pop up closed.

v0.8.6 (2013-05-18)

  • Controls are now removed when there is only one element in gallery.
  • Fixed issue that could cause incorrect main event element.
  • Public property items is now always an array (previously it could be jQuery object collection).
  • Added word-break: break-word to caption.

v0.8.5 (2013-05-15)

  • Fix #43 - In IE8 whole window becomes black when YouTube iframe is closed
  • Fix #51 - In IE9 YouTube HTML5 video keeps playing after iframe is removed from page
  • Bugfix - box-sizing on IMG in low IE behaves incorrectly
  • Fix #57 - padding on body is not added with overflow:Y:'scroll'
  • removalDelay option is now ignored in IE
  • Added an option closeOnBgClick
  • Added BeforeChange callback
  • Added AfterChange callback

 


This awesome jQuery plugin is developed by dimsemenov. For more Advanced Usages, please check the demo page or visit the official website.