Responsive CSS3 Modal Gallery (with JavaScript on-demand images)

This is version 2. Also see all other versions to see how this gallery evolved.

This version 2 responsive gallery is a progression of its CSS-only counterpart (version 1) and uses a few lines of JavaScript to load the larger images on demand only, instead of during initial page load. This has the benefit of speeding up the web page to optimise front-end performance. A <noscript> fallback is provided for when JavaScript is turned off. Please read the Notes section for details about JavaScript enhancement and knock-on UX considerations.

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;

Please view the source of this web page to grab the JS, CSS and HTML markup.

Pros

Cons

Notes (JavaScript to load larger images on demand)

The main change to the CSS-only version of the gallery is the inclusion of an "onclick" event on hyperlinks (on the thumbnail image, and on "previous", "next" and "close" controls), and a corresponding "id" on the <img> tag that holds the larger image. All href attributes (except those supporting IE7/8 and <noscript>) have also been removed, turning gallery navigation links into placeholder links. URL hashes are instead handled in the onclick load() function, with the location.replace() method;

<!--[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]-->
<noscript><a href="/path/to/big/image.jpg" target="_blank"></noscript>
    <img src="/path/to/small/thumb.jpg" width="252" height="160" alt="" />
    <span><b>Preview</b></span>
</a>
<div id="pic-1" class="overlay">
    <img id="img-1" data-src="/path/to/big/image.jpg" alt="" /> <!-- no size attributes - keep it responsive -->
    <div>
        <p>Here is an interesting caption for the big image.</p>
    </div>
    ...

Also note HTML5's "data-src" attribute which is now referencing the larger image instead of a standard "src" attribute. With "data-src" in place, the image will not load until the snippet of JavaScript below changes it to "src" when the corresponding link is clicked, and so the large image is only loaded when it is requested;

function load(myimg){ // load larger img
    var img = document.getElementById(myimg); // get img id
    img.src = img.getAttribute("data-src"); // switch "data-src" to "src" on corresponding img
    id = myimg.replace(/^\D+/g, ''); // get number id from img id ("#img-1")
    location.replace('#pic-'+id); // go to hashed url without affecting browser history

    }

By also including the following 2 lines of JavaScript, you can capture the hash on the end of an URL, strip it back to the "id" of the larger image, and load it in via a link or bookmark when the page loads. Without them you would not be able to bookmark a larger image because the targeted URL wouldn't include the onclick JavaScript call that changes "data-src" to "src" in the <img> tag. However, even without these extra 2 lines of script, you could still link to a larger image if you include the onclick JavaScript call in the anchor <a> tag (e.g. href="gallery-modal-rwd-js.htm#pic-1" onclick="load('img-1')";

var id = window.location.hash.substr(1).replace(/^\D+/g, ''); // get hash from url ("#pic-1") and get number id
if (id) { load('img-'+id); } // load larger img

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]-->
<noscript><a href="/path/to/big/image.jpg" target="_blank"></noscript>
    <img src="/path/to/small/thumb.jpg" width="252" height="160" alt="" />
    <span><b>Preview</b></span>
</a>

The main issue when JavaScript is off is that the CSS :target-powered modal overlay/lightbox will still open, but there will be no script-powered image enlargement inside. Yuk! So, the best UX workaround I can come up with in CSS is to stop the empty #gallery .overlay from opening, and disable visual cues on thumbs (i.e. hover effect, cursor and pointer-events);

#gallery .overlay:target { /* width:auto; height:auto; bottom:0; right:0; */ padding:0.5em 0 5em }
/* overlay size/position disabled - see below for when js is on */
...
/* #### - extra css for js enhancement - #### */
#gallery li a { pointer-events:none; cursor:default } /* disable pointer-events and cursor on gallery thumbs ... */
.js #gallery li a { pointer-events:auto; cursor:pointer } /* ... and enable them again when js is on */
#gallery li a:hover span { display:none } /* disable hover effect on gallery thumbs ... */
.js #gallery li a:hover span { display:inline-block } /* ... and enable it again when js is on */
.js #gallery .overlay:target { width:auto; height:auto; bottom:0; right:0 } /* overlay enabled when js is on */

Unfortunately, pointer-events are unsupported in IE10 and under, so for IE9/10 users who also have JavaScript disabled, they'll rack up void URLs in the browser history if they click on the, now seemingly inactive, thumbs.

IE7/8 fairs better here, and users will be unaffected if they have JS disabled due to the alternative markup; IE conditional comments for hyperlinks that open larger images in a new window. The only consideration for IE7/8 now is to reverse the above CSS in a conditional stylesheet so that users still see the thumb image hover effects and pointy-fingered link cursor;

<!--[if lt IE 9]>
...
#gallery li a { cursor:pointer } /* reverse the extra css used for js enhancement */
#gallery li a:hover span { display:inline-block } /* reverse the extra css used for js enhancement */
<![endif]-->

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!

Compatibility

* 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]-->
<noscript><a href="/path/to/big/image.jpg" target="_blank"></noscript>
    <img src="/path/to/small/thumb.jpg" width="252" height="160" alt="" />
    <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.

Related

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.