Viewer.js : Adding a responsive, feature-rich image viewer to your website might sound complicated, but with libraries like Viewer.js, it’s surprisingly straightforward, even for beginners! Viewer.js is a popular, pure JavaScript image viewer that’s lightweight, flexible, and easy to integrate.
Table of Contents
Viewer.js gives you two powerful ways to display images: the familiar modal mode (like a lightbox) and the versatile inline mode (embedded directly in your page). Understanding both allows you to choose the perfect viewing experience for your users and your website’s design.
In this comprehensive guide, we’ll explore both modal and inline modes offered by Viewer.js. We’ll cover how to set each one up step-by-step using common HTML structures, delve into the key options to customize their behavior, and even touch on handling images that load dynamically.
Whether you have a simple photo gallery, a product page with multiple views, or a complex application displaying user-uploaded images, Viewer.js offers a clean and effective solution.
Let’s dive into the world of Viewer.js and learn how to implement impressive image viewing experiences!
Getting Started with Viewer.js
First things first, you need to include the Viewer.js library in your project.
Step 1: Installation
You can install Viewer.js via npm (if you’re using a build system like Webpack or Parcel):
npm install viewerjs
Alternatively, and often simpler for beginners, you can include it directly in your HTML using CDN links. This method doesn’t require any build tools.
Include the CSS file in the <head>
section of your HTML:
<link href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css" rel="stylesheet">
Citation: The Viewer.js CSS is available via cdnjs.
And include the JavaScript file just before the closing </body>
tag:
<script src="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js"></script>
Citation: The Viewer.js JavaScript is available via cdnjs.
Now you have Viewer.js ready to go!
Step 2: Prepare Your HTML Structure
Viewer.js works by being initialized on an HTML element that either is the image you want to view (for a single image) or contains the images you want to view (for a gallery).
For a single image, it’s simple:
<div>
<img id="singleImage" src="path/to/your-image.jpg" alt="Awesome single image">
</div>
For a gallery of images, the common and recommended structure is a container element (like a div
, ul
, etc.) holding multiple <img>
tags. Your provided HTML structure with a <ul>
is perfect for this:
<div class="image-gallery-container" style="height: 60vh; overflow-y: auto;">
<ul id="images">
<li>
<img class="card-img-top" id="first_image_preview" src="path/to/image1.jpg" alt="First Image">
</li>
<li>
<img class="card-img-top" id="second_image_preview" src="path/to/image2.jpg" alt="Second Image">
</li>
</ul>
</div>
Notice the id="images"
on the <ul>
element. This ID will be crucial for targeting this specific set of images with Viewer.js.
Implementing Viewer.js: Modal Mode (The Classic Lightbox)
Modal mode is the default behavior of Viewer.js. When initialized on an element containing images, clicking any image within that element will open the viewer in a full-screen modal overlay.
Initialization for Modal Mode
To initialize Viewer.js in modal mode on your gallery, you simply select the container element (#images
in your case) and create a new Viewer
instance.
// Wait for the DOM to be fully loaded
document.addEventListener('DOMContentLoaded', function() {
// Get the container element
const galleryElement = document.getElementById('images');
// Check if the element exists to avoid errors
if (galleryElement) {
// Create a new Viewer instance on the container
// Modal mode is the default, so you don't need the 'inline: false' option
const viewer = new Viewer(galleryElement, {
// Optional: Add any other options here
// For example, show the toolbar and navbar
toolbar: true,
navbar: true
});
// The viewer is now active. Clicking any image inside #images
// will open the modal viewer.
} else {
console.error('Gallery element #images not found!');
}
});
In this setup, when a user clicks on first_image_preview
or second_image_preview
(or any other <img>
inside #images
), Viewer.js will take over and display the clicked image within its modal interface. Users can then use the built-in navigation (if enabled via options) to browse through all images found within the #images
container.
Key Options for Modal Mode
While many options apply to both modes, these are particularly relevant or primarily used in modal mode:
backdrop
(Boolean or String, default:true
): Controls the dark overlay behind the modal. Set tofalse
to remove it, or'static'
to prevent clicking the backdrop from closing the viewer.button
(Boolean, default:true
): Shows or hides the close button in the top-right corner.navbar
(Boolean or Number, default:true
): Controls the thumbnail navigation bar at the bottom of the modal. Useful for galleries. Can be set totrue
,false
, or numbers (2
,3
,4
) to control visibility based on screen width.title
(Boolean or Number or Function or Array, default:true
): Displays information about the image (like alt text or dimensions) at the top of the modal. Customizable via function. Similar visibility options asnavbar
.toolbar
(Boolean or Number or Object, default:true
): Controls the main toolbar with zoom, rotate, flip, and navigation buttons. Highly customizable. Can betrue
,false
, numbers for responsive visibility, or an object to configure specific buttons.zIndex
(Number, default:2015
): Sets the CSSz-index
for the modal viewer. Important if you have other fixed or absolute elements on your page.
Modal mode is great for a focused image-viewing experience that temporarily takes over the screen.
Implementing Viewer.js: Inline Mode (Embedded Viewer)
Inline mode is where Viewer.js integrates directly into a container element on your page. The viewer controls and the image itself will appear within the boundaries of that container.
Initialization for Inline Mode
To initialize Viewer.js in inline mode, you select the container element and pass an options object with the inline
property set to true
.
Let’s apply this to your #images
structure. Remember that the div
wrapping your <ul>
has height: 60vh; overflow-y: auto;
. When you initialize Viewer.js in inline mode on the <ul>
, the viewer will take over the content within that <ul>
‘s parent div
, and the viewing area will be confined to that div
‘s dimensions (60vh
height with scrolling).
// Wait for the DOM to be fully loaded
document.addEventListener('DOMContentLoaded', function() {
// Get the container element
const galleryElement = document.getElementById('images');
// Check if the element exists to avoid errors
if (galleryElement) {
// Create a new Viewer instance on the container with inline mode enabled
const viewer = new Viewer(galleryElement, {
inline: true, // <--- THIS enables inline mode
// Optional: Add other inline-specific options here
// For example, control minimum size within the container
minWidth: 300,
minHeight: 200,
// Optional: Customize toolbar/navbar visibility within the inline container
toolbar: true,
navbar: true,
// Optional: You might want to automatically view the first image on load
// This requires waiting for the 'ready' event in inline mode
ready: function() {
// 'this.viewer' refers to the Viewer instance
this.viewer.view(0); // View the first image (index 0)
}
});
// The viewer is now active inline within the container.
// If you set the 'ready' event and view(0), it will show the first image immediately.
// Otherwise, you might need a button or other action to call viewer.view(index).
} else {
console.error('Gallery element #images not found!');
}
});
When inline: true
is set on a container with multiple images, Viewer.js doesn’t wait for a click to open a modal. Instead, it transforms the content within the target element (#images
in this case) into the inline viewer interface. You’ll see the Viewer.js controls and the first image (or the image at initialViewIndex
) appear directly in that spot when the page loads and the Viewer is initialized.
Key Options for Inline Mode
These options are particularly useful when working with inline mode:
inline
(Boolean, default:false
): Crucial – set this totrue
to enable inline mode.container
(Element or String, default:'body'
): This option is ignored in inline mode. The viewer is placed within the element you initialize it on (#images
in your example).minWidth
(Number, default:200
): Defines the minimum width of the inline viewer container.minHeight
(Number, default:100
): Defines the minimum height of the inline viewer container.zIndexInline
(Number, default:0
): Defines the CSSz-index
value for the viewer in inline mode. Useful if you need the inline viewer to appear above or below other elements within its parent container.
You can use other general options like toolbar
, navbar
, title
, loop
, movable
, zoomable
, rotatable
, scalable
, etc., in inline mode as well. They control the behavior of the viewer interface within its container.
Inline mode is perfect for creating a persistent viewing panel within a specific section of your layout.
Handling Dynamic Images with update()
A common scenario in modern web applications is loading content (including images) dynamically, often using technologies like AJAX or frameworks that update parts of the page.
If the images inside your Viewer.js container (#images
) change after you have initialized the Viewer instance (e.g., you load more images into the <ul>
via a script), the Viewer instance won’t automatically be aware of the new images.
To fix this, you need to call the update()
method of your Viewer instance whenever the images in the container are added, removed, or re-ordered.
Here’s a conceptual example:
let viewer; // Declare the viewer variable in a scope accessible later
document.addEventListener('DOMContentLoaded', function() {
const galleryElement = document.getElementById('images');
if (galleryElement) {
// Initialize the viewer (e.g., in inline mode as discussed)
viewer = new Viewer(galleryElement, {
inline: true,
// ... other options
ready: function() {
// View the first image when ready in inline mode
this.viewer.view(0);
}
});
// ... rest of your page initialization
} else {
console.error('Gallery element #images not found!');
}
});
// --- Example of dynamic image loading ---
// This function simulates loading new images and adding them to the #images ul
function loadMoreImages() {
const galleryElement = document.getElementById('images');
if (galleryElement && viewer) { // Check if element and viewer exist
// Simulate adding a new image element
const newImageListItem = document.createElement('li');
const newImage = document.createElement('img');
newImage.src = 'path/to/new-image.jpg'; // Set the new image source
newImage.alt = 'Newly loaded image'; // Set alt text
newImage.className = 'card-img-top'; // Add your existing classes
newImage.style = 'display:block; max-width: 100%; cursor: pointer;height:auto;'; // Add your existing styles
newImageListItem.appendChild(newImage);
galleryElement.appendChild(newImageListItem); // Add the new image to the list
// Tell Viewer.js to update its list of images
viewer.update();
console.log('Viewer.js updated with new images.');
// Optional: View the newly added image (it will be the last one)
// viewer.view(viewer.images.length - 1);
}
}
// You would call loadMoreImages() when your content is loaded dynamically,
// for example, after an AJAX request completes.
// Example: loadMoreImages(); // Call this after new images are added to the DOM
By calling viewer.update()
, you ensure that Viewer.js recognizes the changes in the HTML structure and includes the new images in its gallery for navigation and viewing. This is very likely relevant to your setup, given the div id="loadRecords"
where content seems to be loaded. You would need to initialize the viewer on #images
after the initial record_list.php
content is included, and then call viewer.update()
any time subsequent content is loaded into that section.
Applying Viewer.js to Your Code
Let’s specifically look at the HTML structure you provided and how to apply Viewer.js to it for both modal and inline viewing.
Your HTML:
<div class="col-lg-4">
<div style="height: 60vh; overflow-y: auto;">
<ul id="images">
<li>
<img class="card-img-top" id="first_image_preview" src="" alt="First Image" style="display:block; max-width: 100%; cursor: pointer;height:auto;">
</li>
<li>
<img class="card-img-top" id="second_image_preview" src="" alt="Second Image" style="display:block; max-width: 100%; cursor: pointer;height:auto;">
</li>
</ul>
</div>
</div>
The key element here is the <ul>
with the ID images
. This is the container holding the images you want to view. The parent div
with height: 60vh; overflow-y: auto;
is important as it defines the visual space available for the images and will contain the inline viewer if you choose that mode.
Setup for Modal Mode on your HTML:
document.addEventListener('DOMContentLoaded', function() {
const galleryElement = document.getElementById('images'); // Target the UL
if (galleryElement) {
const viewer = new Viewer(galleryElement, {
// No 'inline: true' option needed for modal mode
// Add options for modal behavior if desired
button: true, // Show close button
navbar: true, // Show thumbnails
toolbar: true, // Show tools
zIndex: 2015 // Default or custom z-index for the modal overlay
// ... other options
});
// The viewer is ready. Clicking any image in the UL will open the modal.
}
});
With this code, when a user clicks on either the “First Image” or “Second Image” within the <ul>
, the Viewer.js modal will pop up, centered over the page, allowing them to navigate between the images in that list. Your .popup
CSS and related HTML/JavaScript would be redundant if you fully adopt Viewer.js modal mode.
Setup for Inline Mode on your HTML:
document.addEventListener('DOMContentLoaded', function() {
const galleryElement = document.getElementById('images'); // Target the UL
if (galleryElement) {
const viewer = new Viewer(galleryElement, {
inline: true, // Enable inline mode
// Add options for inline behavior within the container
minWidth: 200, // Minimum width for the inline viewer
minHeight: 100, // Minimum height for the inline viewer
zIndexInline: 0, // Z-index within the container
toolbar: true, // Show tools within the inline area
navbar: true, // Show thumbnails within the inline area
// ... other options
// Use the ready event to show the first image immediately in inline mode
ready: function() {
this.viewer.view(0); // Automatically show the first image
}
});
// The viewer interface will appear directly inside the UL's parent div
// when the page loads and the viewer is initialized.
}
});
In inline mode with your HTML, the viewer interface will replace the standard display of the images within the <ul>
‘s parent div
. The user will see the Viewer.js controls and the currently viewed image confined to that 60vh
tall scrolling area. Clicking on an image inside the list before the inline viewer is initialized might still trigger other events or your manual popup if they are not removed. Once initialized, Viewer.js handles the clicks on images within its target element (#images
).
Important Consideration: Bootstrap Modals and Dynamic Content
Your HTML includes elements related to Bootstrap modals (#userEventModal
) and a div id="loadRecords"
which suggests dynamic content loading (likely via PHP as indicated by the <?php ... ?>
tags and include('record_list.php')
).
- If your images (
#images
) are initially hidden and loaded inside a Bootstrap Modal: You should initialize Viewer.js after the Bootstrap modal is shown and the images are present in the DOM. You can listen to Bootstrap’s modal events (e.g.,shown.bs.modal
). - If your images within
#loadRecords
(which contains the#images
ul) are loaded dynamically via AJAX: Initialize Viewer.js on#images
after the initial content is loaded. Then, every time you load new images into#images
via AJAX, you must callviewer.update()
to make the new images viewable by the existing Viewer instance.
Initializing Viewer.js on #images
while the images are not yet in the DOM will not work.
Checking Your Setup
Based on the HTML structure you provided, initializing Viewer.js on the <ul id="images">
is the correct approach for creating a gallery viewer that operates on the images within that list.
- Your HTML structure (
<ul>
containing<li>
with<img>
tags) is suitable for Viewer.js to find and manage the images. - The CSS you provided (
.card-img-top
, etc.) styles the initial appearance of your images. Viewer.js adds its own CSS classes and elements to the DOM when it’s active, so its appearance is largely controlled by its own CSS and options, not your custom image styles (though max-width/height and display might influence initial rendering before Viewer.js takes over). - Your
.popup
CSS and associated HTML (<div id="popup">
) suggest you have a separate, manual image popup mechanism. If you use Viewer.js (especially in modal mode), this manual system would likely be redundant and could cause conflicts if not managed properly (e.g., ensuring Viewer.js handles the click instead of your custom popup script). - The parent
div
withoverflow-y: auto
for the#images
ul
is significant. In inline mode, the Viewer.js interface will live inside this scrolling div. If you zoom an image larger than the60vh
height, the scrolling will still apply to the parent div. In modal mode, this parent div’s styles are less relevant as the viewer appears as a full-page overlay. - The most critical part of your setup is the JavaScript initialization timing. If the images in
#images
are loaded dynamically after the page loads, you must ensurenew Viewer(...)
is called after the images are added to the DOM, andviewer.update()
is called whenever the content of#images
changes dynamically thereafter.
In summary, your HTML structure is appropriate. The “correctness” of your setup depends entirely on when and how your JavaScript initializes Viewer.js relative to when your images appear in the #images
<ul>
.
Common Options for Both Modal and Inline Modes
Many of Viewer.js’s powerful options apply regardless of whether you are in modal or inline mode. These control the core behavior of the image viewer itself:
movable
(Boolean, default:true
): Allows the user to drag and move the image around within the viewer area when it’s larger than the container.zoomable
(Boolean, default:true
): Enables zooming the image.zoomOnTouch
(Boolean, default:true
): Enables touch gestures for zooming.zoomOnWheel
(Boolean, default:true
): Enables mouse wheel scrolling for zooming.zoomRatio
(Number, default:0.1
): The increment/decrement amount when zooming with the wheel or controls.minZoomRatio
(Number, default:0.01
): The minimum zoom level allowed (1% of natural size).maxZoomRatio
(Number, default:100
): The maximum zoom level allowed (100x natural size).rotatable
(Boolean, default:true
): Allows rotating the image.scalable
(Boolean, default:true
): Allows flipping the image horizontally or vertically.toggleOnDblclick
(Boolean, default:true
): Double-clicking toggles the image size between its current size and natural size.loop
(Boolean, default:true
): Allows looping through images (going from the last to the first, and vice versa).keyboard
(Boolean, default:true
): Enables keyboard shortcuts for navigation and actions (like arrow keys for next/prev, Escape to close modal/exit full screen). Note that some keyboard controls are modal-specific.url
(String or Function, default:'src'
): Defines where Viewer.js gets the full-resolution image URL. By default, it uses thesrc
attribute of the<img>
tag. You can specify a different attribute (likedata-original-src
) or provide a function to generate the URL dynamically.filter
(Function, default:null
): A function that allows you to exclude certain images within the container from being included in the viewer gallery.
These options provide fine-grained control over how users interact with the images in both modal and inline modes.
Understanding Viewer Events
Viewer.js also provides a set of events you can listen to, allowing you to execute custom code at different points in the viewer’s lifecycle (when it’s ready, shown, hidden, viewing an image, zooming, etc.).
For example, the viewed
event fires after an image has been fully loaded and shown in the viewer. This is a good place to perform actions related to the displayed image.
const viewer = new Viewer(galleryElement, {
// ... options
viewed: function(event) {
// This code runs after an image is fully shown
console.log('Image viewed!', event.detail.image.alt);
// event.detail contains information about the viewed image
}
});
Understanding the Events section in the Viewer.js documentation can help you create more dynamic and integrated experiences. Pay attention to the lifecycle mentioned in the README, as some methods are only available after certain events (ready
, shown
, viewed
).
Conclusion: Choosing Your Viewer.js Path
Viewer.js is a flexible and powerful library for handling image viewing on your website. You now understand the core differences and setup for its two primary modes:
- Use Modal Mode for a traditional lightbox experience that focuses the user’s attention solely on the image(s). It’s great for detail viewing and immersive galleries.
- Use Inline Mode to seamlessly embed the image viewer within a specific container on your page, maintaining the user’s context and integrating the viewer into your existing layout. It’s ideal for dashboards, side panels, or areas with limited space.
By choosing the right mode and leveraging the extensive options Viewer.js provides, you can significantly enhance how users interact with images on your site. Remember the importance of initializing the viewer at the correct time, especially when dealing with dynamic content, and using the update()
method when the images within your container change.
Happy coding and happy image viewing!
Essential Tool for Developers: A Recommended Book
If you’re looking to deepen your JavaScript knowledge to better integrate libraries like Viewer.js and handle dynamic content, a solid foundation is key.
Recommended Product:
Eloquent JavaScript, 3rd Edition: A Modern Introduction to Programming
This widely acclaimed book provides a comprehensive introduction to JavaScript programming, covering everything from the basics to more advanced concepts like asynchronous programming and the browser environment. Understanding these fundamentals will empower you to integrate and manipulate libraries like Viewer.js with confidence.