Responsive CSS3 Modal Gallery (with JavaScript pagination)
This is version 4. Also see all other versions to see how this gallery evolved.
Version 4 of the responsive gallery uses a small amount of JavaScript to split a large gallery into smaller pages, and load ALL images on demand only, instead of during initial page load. Only small images in the first visible page are loaded by default. This improves performance considerably, but (and its a BIG BUT) most of the gallery is inaccessible if JavaScript is turned off.
Like version 3 (JS on-demand images + keyboard controls), left, right and close (Esc) key navigation is included to move through the image enlargement lightbox. Plus, you can cycle through ALL enlargements regardless of which page is visible.
Click on an image below to bring the gallery to life (and resize the browser window for slinky responsiveness)...
Features
A CSS3, responsive image gallery that;
- Includes pagination to split a large gallery into smaller "pages" and make it more manageable
- Opens an image enlargement in a modal overlay/lightbox (by using the :target selector)
- Has "previous" and "next" controls to cycle through the gallery from within the modal overlay/lightbox
- Includes keyboard navigation to move back and forth through the gallery from within the modal overlay/lightbox
- On a small screen, the "previous" and "next" controls become extra large tappable areas for easy finger jabbing
- Uses CSS3 transitions to animate a gentle fade effect (on thumbs and modal overlay/lightbox)
- Includes optional image captions (inside the modal overlay/lightbox)
- Loads ALL images on demand instead of during initial page load (only those in the first page are loaded by default)
- A <noscript> fallback allows image enlargements (of thumbs in the first page) to be opened in a new window when JavaScript is disabled
- Shows a CSS3 loading spinner to indicate that larger images are loading
Please view the source of this web page to grab the JS, CSS and HTML markup, OR see the PHP version.
Pros
- Kind on screen space; Pagination breaks a large gallery into more manageable page chunks.
- Performance friendly; Loads ALL images on demand instead of during initial page load (except those in the first page).
- You can cycle through ALL images in the modal overlay, no matter which page is visible on the screen.
- You can bookmark or link to a larger image and it will load inside the modal overlay/lightbox.
- Browser history is not affected while viewing image enlargements, thanks to JavaScript's location.replace() method.
- A <noscript> fallback allows larger images (of thumbs in the first page) to be opened in a new window when JavaScript is disabled.
Cons
- Extra markup for the IE7/8 workaround. You can use something like Selectivizr to make older IE recognise the :target selector, but that is outside the scope of this demo, although here is a gallery demo using Selectivizr for IE8 support. You also need to set an explicit CSS height on #gallery for IE7.
- Minimal fallback for when JavaScript is disabled; Only image enlargements for thumbs in the first page are accessible.
- Use of "data-src" in place of "src" in the <img> tag invalidates markup.
Notes (JavaScript for on-demand images, keyboard controls + pagination)
I won't go through all the evolutionary changes to the gallery again - this version has everything that version 3 (JS on-demand images + keyboard controls) has so you can recap on the notes there.
The main thing I'd like to draw your attention to is the HTML5 "data-src" attribute which now references ALL images instead of the standard "src" attribute. With "data-src" in place, the images will not load until JavaScript changes it to "src". This happens at a few points in the script so that the small images only load when pagination links are clicked (into the visible "page" only), and larger images only load when thumbs are clicked, or when previous/next controls take your there.
To demonstrate the on-demand image script, see this YSlow component report showing only 4 images downloaded - 3 thumbs from the first page of the gallery, plus the header logo (there are 18 gallery images in total!).
UX consideration 1... what happens when JS is disabled?
The deleted chunk of info below can be ignored now that alternative markup is included in <noscript> tags. Thinking along the same lines as the IE7/8 workaround (more on that later), where those users can open image enlargements in a new browser window instead of the modal overlay/lightbox, we can do something similar for folks with JavaScript turned off;
<!--[if gte IE 9]><!--><a onclick="load('img-1')"><!--<![endif]--> <!-- no href - use location.replace('#pic-'+id); in load() function -->
<!--[if lte IE 8]><a href="/path/to/big/image.jpg" target="_blank"><![endif]-->
<img class="small-img" data-src="/path/to/small/thumb.jpg" width="252" height="160" alt="" />
<noscript>
<a href="/path/to/big/image.jpg" target="_blank">
<img src="/path/to/small/thumb.jpg" width="252" height="160" alt="" />
</noscript>
<span><b>Preview</b></span>
</a>
Please note, this is a minimal fallback that only provides a reduced, token gallery for the first page of thumbnail images - there's a bit of a trade-off between performance, and giving non-JS users something to look at. Just to confirm, and paraphrasing the W3C noscript specs, "the contents of the noscript element will load when JavaScript is unavailable
", hence why here it has only been provided for some of the thumbs (those in the first page), and not all of the thumbs.
Unfortunately, nothing. The gallery relies on JavaScript to switch in the "src" attribute of all images, so there is no fallback for when it isn't available. The CSS below simply hides it in those cases;
/* #### - extra css for js enhancement - #### */
#gallery { display:none } /* hide gallery if js is disabled */
.js #gallery { display:block; overflow:hidden } /* show gallery if js is on */
UX consideration 2... is it loading?
The "on-demand" image script takes care of the performance dilemma (thumbs up for mobile), but it could leave users with slower internet connections wondering when that big ol' image is going to appear on their screen. So let's add a simple loading spinner to indicate something is happening... Add this to the CSS;
@-webkit-keyframes rotation { from {-webkit-transform:rotate(0deg)} to {-webkit-transform:rotate(359deg)} }
@keyframes rotation { from {transform:rotate(0deg)} to {transform:rotate(359deg)} }
#gallery .overlay:before {
content:"";
position:absolute;
top:40%;
margin-top:-0.5em;
left:50%;
margin-left:-2em;
display:block;
height:3em;
width:3em;
border:0.5em solid rgba(255,255,255,.15); border-top:0.5em solid rgba(255,255,255,.5); border-radius:100%;
-webkit-animation:rotation .75s infinite linear; animation:rotation .75s infinite linear
}
This places a CSS pseudo element loading spinner on the #gallery .overlay. It's always present, but then when an image has loaded, the picture will sit in front of the spinner and hide it!
UX consideration 3... how many thumbs?
Although you can have as many thumbnails in a pagination area as you wish, bear in mind that while 20 of them might look pretty spiffy on a desktop monitor, they become a bit unmanageable on small screens - you'll end up with a long column of pics with the pagination links floated way up off the top of the screen. A good way to counteract this (to a degree) is to resize thumbnails using CSS in mobile view, and then reset them for desktop. A happy side-effect of this is that half-size thumbs on small retina displays look ultra crispy! ;) Of course, you still need to be sensible about the number of thumbs to show per page for performance reasons - I'd personally go with 10 or 12 max.
UX consideration 4... where's the grid?
For predictable results, set a max-width on the pagination areas to encourage thumbnail images to fall into a nice neat grid;
#gallery .pagination { max-width:48.75em } /* fix thumbs to grid */
Compatibility
- IE7+ *
- Chrome
- Safari
- Firefox
- Opera
- Android
- iOS
* The :target selector is not supported in IE7/8 but a bit of markup-mashing with IE conditional comments provides a workaround so those users can open image enlargements in a new browser window instead of the modal overlay/lightbox.
<!--[if gte IE 9]><!--><a onclick="load('img-1')"><!--<![endif]--> <!-- no href - use location.replace('#pic-'+id); in load() function -->
<!--[if lte IE 8]><a href="/path/to/big/image.jpg" target="_blank"><![endif]-->
<img class="small-img" data-src="/path/to/small/thumb.jpg" width="252" height="160" alt="" />
<noscript>
<a href="/path/to/big/image.jpg" target="_blank">
<img src="/path/to/small/thumb.jpg" width="252" height="160" alt="" />
</noscript>
<span><b>Preview</b></span>
</a>
* IE7/8 users will not see the magnifying glass icon when they hover over a thumbnail. However, there is fallback for a plain "Preview" bar that they will see instead.
I haven't been able to test in other browsers/devices but feedback is always welcome. Contact me if you spot anything hinky.
Acknowledgement
Inspired by the "CSS3 Modal Popups" tutorial at Script Tutorials. Starter pagination JavaScript sourced via a JSFiddle.
Related
- Version 1: Responsive CSS3 Modal Gallery (no JavaScript)
- Version 2: Responsive CSS3 Modal Gallery (with JavaScript on-demand images)
- Version 3: Responsive CSS3 Modal Gallery (with JavaScript on-demand images + keyboard controls)
- Version 5: PHP Responsive CSS3 Modal Gallery (with JavaScript on-demand images, keyboard controls + pagination)
Freebies
Looking for more freebies for your website? Grab a bunch of free PHP, CSS and JavaScript goodies, from flat file CMS' to RSS managers to responsive CSS menus, galleries and sliders.