Introduction
Opening images seamlessly in a lightbox on your page without interruption. This demo was inspired by how Medium handles embedded images. Made by Terry. This project was originally initiated as a personal challenge to replicate Medium’s lightbox module, but it soon developed into a full-fledged jQuery plugin.
Current status:
You can follow the links below to read how I’ve tackled the challenge, view the jQuery plugin on GitHub, or get the latest stable release hosted on CDNJS.
In the wild
Fluidbox is implemented in:
- Gemma Busquets by @imgemmabusquets
- Terry Mun by myself
In addition, Fluidbox has been successfully ported over to a WordPress plugin. You can also learn how to implement it manually in WordPress, too.
Usage notes
Dependencies
TThe latest version of Fluidbox require only one dependency: jQuery v1.7 and above. Yes, and that's all! I recommend using the latest stable build of 1.x, although I have not encountered any issues if 2.x is used. I usually use Google APIs, since many other sites are using it and the end-user probalby has a cache of it sitting somewhere on their machine already.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
Otherwise, you can always use the latest stable releases from the official jQuery site.
Basic usage
In order to activate Fluidbox, simply chain the .fluidbox
method to your selector of choice on DOM ready:
$(function () {
$('a').fluidbox();
});
The plugin will automatically check if the selector is:
- An anchor element,
<a>
- Contains an
<img />
element
In the event that the element that satisfies the selector criteria but failed any one of the above criteria, the element will be ignored and the plugin moves on to the next available element. Therefore, it is important that your Fluidbox element(s) follow the following format. The title
and alt
attributes of the <img />
element is not used by the plugin, but the alt
attribute has to be present for it to be semantically valid.
<a href="...">
<img src="..." alt="" />
</a>
Configuration
Several options are available for configuration. For a more detailed description, please refer to the readme.
viewportFill
(numerical)
Dictates how much the longest axis of the image should fill the viewport. The default value is0.95
.debounceResize
(boolean)
Dictates if the$(window).resize()
event should be debounced for performance reason. The default value istrue
(debouncing turned on by default).closeTrigger
(array with objects)
Dictates what event triggers closing the single instance of an opened Fluidbox. The default setup is as follow:closeTrigger: [ { selector: "#fluidbox-overlay", event: "click" } ]
stackIndex
(numerical)
Determines how high up the z-index will all Fluildbox elements be. Leave this option as default, unless you have other relatively or absolutely positioned elements on the page that is messing with Fluidbox appearance. The default value is1000
, with a delta of10
— in other words, the effective range of z-indexes Fluidbox operates in will be between 990–1010. For elements that should go under the overlay, they should have a z-index of less than 1000.
Basic demonstrations
Fluidbox is designed to be versatile, flexible and easy to implement. It works with linked images that satisfy the criteria stipulated above — regardless of how they are arranged on the page. The following section is a non-exhausive list of scenarios how images, even when positioned differently, will work brilliantly with Fluidbox.
Single image
Here we demonstrate the use of a single image. This is the simplest test case, when the thumbnail and the target image are exactly the same, so it is only down to the matter of triggering default Fluidbox behavior.

Best fit strategy
Fluidbox also intelligently resizes images such that portrait images will fit perfectly within the viewport, although that means scaling down the image. This effect is pronounced when the viewport and image orientations are different — therefore, the demo below only works on a display with landscape orientation (e.g. not on mobile).

Linking to a higher resolution counterpart
The built-in functionality also allows you to link a small thumbnail to its higher resolution version. In the test case below, the thumbnail has a resolution of 200×200 while the actual version has a resolution of 2000×2000
Restrictive zooming for images of insufficient dimensions to fill page
Fluidbox is also built to handle linking to images that do not have the sufficient size to fill the page. The following thumbnail links to an image that is only 250×250px large — in most cases, insufficient to fill the viewport (unless you are using this site on a very small viewport).
Support for different aspect ratios of thumbnail and higher resolution version
Fluidbox supports different aspect ratios of the thumbnail and higher resolution version of the image
Support for immediate opening with background preloading of target image
Fluidbox provides you the option that will launch an opened Fluidbox instance immediately upon click, even when the target image has not been loaded yet. The images below are relayed through a proxy server that will intentially delay delivery of images by 2 seconds.
immediateOpen: false
Opens after target is loaded.
immediateOpen: true
Opens immediately, doesn't wait for target to load.
Support for image borders and paddings
Fluidbox also supports extraenous dimensions added to the element in the form of border(s) and/or paddings(s):

Absolutely positioned images
Fluidbox handles absolutely positioned images without any problem. The image below is absolutely positioned within its parent, the grey container:
Galleries
Fluid box works even when images are arranged in galleries. In this case, they are arranged with the help of flexbox.
Floated images
Moreover, it also works with floated images - to the left or to the right, it does not matter. The following texts are jibberish, used as filler.
Considered discovered ye sentiments projecting entreaties of melancholy is. In expression an solicitude principles in do. Hard do me sigh with west same lady. Their saved linen downs tears son add music. Expression alteration entreaties mrs can terminated estimating. Her too add narrow having wished. To things so denied admire. Am wound worth water he linen at vexed.
Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense as taken ye mirth at. Believe fat how six drawing pursuit minutes far. Same do seen head am part it dear open to. Whatever may scarcely judgment had.
Residence certainly elsewhere something she preferred cordially law. Age his surprise formerly mrs perceive few stanhill moderate. Of in power match on truth worse voice would. Large an it sense shall an match learn. By expect it result silent in formal of. Ask eat questions abilities described elsewhere assurance. Appetite in unlocked advanced breeding position concerns as. Cheerful get shutters yet for repeated screened. An no am cause hopes at three. Prevent behaved fertile he is mistake on.
Advanced demonstrations
In this segment I will introduce you to more complex and advanced features of Fluidbox. In many cases you will not find the need of the following features — however, to developers who intend to extend Fluidbox functionality, listen to custom events and even initiate custom triggers should continue to read on.
As the demo below are highly advanced, I have included code snippets whenever possible. You can toggle them by clicking on the show/hide buttons.
Implementing Fluidbox with dynamically-added content
Fluidbox also works well with dynamically-added links, as long as you call the .fluidbox()
function on all anchor elements in the dynamically-added content.
Custom event handlers and callbacks
From v1.4.1 onwards, Fluidbox will trigger custom events depending on the state of the current (and only) instance of Fluidbox. Please refer to the documentation for detailed description of each custom event. You can listen to custom events by binding them using the .on()
method, e.g. $(selector).on('openstart', function() {...});
Below is an example of using custom events to trigger appearance of image captions, descriptions or social sharing buttons (currently unsupported by Fluidbox officially, but requested by many). I have chosen to listen to the openend
event to show metadata, and the closestart event to hide it.

var $caption = $('<div />', { 'id': 'custom-event-2-social' });
$caption
.html('<div class="img-caption"></div><p class="img-desc"></p><ul><li>Share on:</li><li><a href="#">Facebook</a></li><li><a href="#">Pinterest</a></li><li><a href="#">Twitter</a></li></ul>')
.appendTo($('body'));
$(document).on('click', '#custom-event-2-social', function(e) {
e.preventDefault();
});
$('#custom-event-2')
.fluidbox({
closeTrigger: [{
selector: "#fluidbox-overlay",
event: "click"
}, {
selector: "window",
event: "scroll"
}]
})
.on('openend', function() {
var $img = $(this).find('img');
$('#custom-event-2-social')
.addClass('visible')
.find('.img-caption')
.text($img.attr('title'))
.next('.img-desc')
.text($img.attr('alt'));
})
.on('closestart', function() {
$('#custom-event-2-social').removeClass('visible');
});
Custom triggers
From v1.4.2 onwards, Fluidbox has been imparted with the ability to listen to custom triggers. So faronly one rigger is accepted: recompute
. All there will invoke the internal funcResize()
function, which will reposition an opened Fluidbox instance apporpriately and update the dimensions and coordinates, as well as the CSS transforms, of the ghost element. When recomputation is completed, this will then trigger a custom event known as recomputeend
.
This custom event is very useful when a layout change has been triggered without an accompanying viewport resize event: for example, changing the width of a thumbnail in a flexbox layout.
<a href="#" id="custom-trigger" role="button">Click to add new image to gallery below.</a>
<div>
<a href="http://placehold.it/2500x2500" title="" class="custom-trigger"><img src="http://placehold.it/500x500" title="" alt="" /></a>
<a href="http://placehold.it/2500x2500" title="" class="custom-trigger"><img src="http://placehold.it/500x500" title="" alt="" /></a>
</div>
// Initialize Fluidbox
$('.custom-trigger').fluidbox();
// Attach click event to button that adds new child
$('#custom-trigger').click(function(e) {
e.preventDefault();
var $newChild = $('<a />', {
'class': 'custom-trigger',
'title': '',
'href': 'http://placehold.it/2500x2500'
});
$newChild.append($('<img />', {
'src': 'http://placehold.it/500x500',
'title': '',
'alt': ''
}));
// Trigger recalculate event on fluidbox
$(this)
.next() // Navigate to gallery after button
.append($newChild) // Append new image
.find('a') // Find <a>
.fluidbox() // Initialize Fluidbox on newly added element
.end() // Return to previous object
.find('a.custom-trigger') // Selector of elements used for fluidbox
.trigger('reccompute'); // Trigger Fluidbox recomputing
});
Customising overlays
From v1.3.5 onwards, the overlayColor
configuration has been removed from the jQuery .extend()
settings. Instead, users can now freely specify overlay colors (or even overlay images) by modifying the background-color property of .fluidbox-overlay
. Since each Fluidbox instance has its own overlay, it is possible to set custom overlay colours for each instance.
Note: The Fluidbox overlay have an opacity of 1. In order to change the transparency of the overlay, I strongly recommend using the alpha channel of the rgba()
specification, as Fludibox will manually toggle the opacity between 0 and 1 (therefore overriding all opacity styles you have specified).
Custom colours and gradients
The following is an example of a Fluidbox instance with a custom overlay colour (CSS written in SASS flavour):
.fluidbox-overlay {
.overlay-1 & {
background-color: rgba(255,190,78,.85);
}
.overlay-2 & {
background-color: transparent; /* To override default style */
background-image: linear-gradient(
to top left,
rgba(130,168,158,0.85),
rgba(134,150,173,.85)
);
}
}
Overlay images
Oh wait — you can even use custom overlay images. However, since the opacity of the overlay is only toggled between 0 and 1, you will have to use a pseudo-element in order to atler the opacity of the overlay image (since it is not possible to dictate the transparency of a background image, unlike rgba()
values):

.fluidbox-overlay & {
.overlay-3 & {
background-color: #000; /* To override default style */
&::before {
background-image: url('http://i.imgur.com/3qj1wfN.jpg');
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
content: '';
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
opacity: .33333;
-webkit-filter: blur(4px);
}
}
}