Zooming image (simple lightbox - medium.com style)

Author's picture
Lindus One
Author
Lindus One
Publication date:
Last update:

∼ 20 lines of vanilla javascript with no additional libraries, and we have image zooming similar to medium.com with a fallback when javascript is not present. A few zoom alternatives transition styles. Ultra light lightbox as an example of combining javascript with CSS.

HTML, CSS and javascript

HTML

HTML code to make zoom-in works.

<!-- Link to the full image and "u-blowUpImg" class. If javascript is not present user will get full picture without transition. -->
<a class="u-blowUpImg" href="full-size-img.png">
    <!-- Thumbnail -->
    <img src="thumbnail.png" alt="Image description">
</a>

CSS

.u-blowUpImg:hover {
  cursor: zoom-in; /* magnifying glass icon on thumbnail */
}

Javascript

Script to apply into head section. Every element with .u-blowUpImg class get click listener with zoom-in feature.

Full image is downloaded after click. To avoid display delay on slower network, prealoder animation can be added. Example further.

<script>
    // After site is loaded
    document.addEventListener("DOMContentLoaded", function() {
        // Element to display full image as background
        let backgroundCanvas = document.createElement("div");
        // CSS styles for zoom transition
        backgroundCanvas.style.cssText = "position: fixed; top: 50%; left: 50%; width: 0; height: 0; z-index: 1; \
        background: rgba(0,0,0,0.9) none center/contain no-repeat; transition: all .8s ease-out; cursor: zoom-out;";
        // Last child of <body>
        document.body.appendChild(backgroundCanvas);
        // Closing full image (width:0; height:0)
        backgroundCanvas.onclick = function() { 
            backgroundCanvas.style.inset = "50% auto auto 50%"; //top right bottom left
            backgroundCanvas.style.width = "0";
            backgroundCanvas.style.height = "0";
        };
        // Array of all thumbnails (elements with .u-u-blowUpImg class)
        let zoomInImgLinks = document.getElementsByClassName("u-blowUpImg");
        // click event handling on every thumbnail
        for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
            e.preventDefault();// Prevent link from opening and passing handler to javascript
            // Display and animate zoom (transition: all .8s ease-out;)
            backgroundCanvas.style.backgroundImage = "url('"+e.target.parentNode.href+"')";
            backgroundCanvas.style.inset = "0 auto auto 0";
            backgroundCanvas.style.width = "100%";
            backgroundCanvas.style.height = "100%";
        })
    })
</script>

Live examples

Panorama of Cracow

Kraków, Poland Photo Dawida Łabno on Unsplash

Enlarge the best part

Pizza in Warsaw restaurant Photo Zuza Reinhard on Unsplash

Kazimierz Górski’s National Stadium, Warsaw, Poland

Zooming with preloader. On fast networks hardly noticable. Further a bunch of SVG animation examples.

To display SVG before full image is downloaded we can use Image API. Steps:

  • Variable declaration for full image;
  • Displaying preloader;
  • Assigning full image url to variable;
  • Browser starts downloading image and in the end “onload” event gets fired;
  • Hiding preloder, displaying full picture
Spinning quarter on the circle
Animation shown when image is downloaded

Stadion Narodowy, Warszawa Photo Henryk Niestrój on Pixabay

HTML, CSS, Javascript
    <style>
.u-BlowUpImgPreload:hover {
    cursor: zoom-in;
}    
</style>
<script>
    document.addEventListener("DOMContentLoaded", function() {
        var backgroundCanvas = document.createElement("div");
        backgroundCanvas.style.cssText = "position: fixed; top: 50%; left: 50%; width: 0; height: 0; z-index: 2; \
        background: rgba(0,0,0,0.9) none 50% 50%/contain no-repeat; transition: all .8s ease-out; cursor: zoom-out;";
        document.body.appendChild(backgroundCanvas);
        // Background canvas for prealoder animation
        var preloaderBackgroundCanvas = document.createElement("div");
        // Styles
        preloaderBackgroundCanvas.style.cssText = "position: fixed; top: 50%; left: 50%; width: 15vmin; height: 15vmin; \
        background-repeat: no-repeat; background-position: center; background-size: 100%; z-index: 1; display: none;";
        // Background SVG declared directly in HTML code to avoid latency due to loading image file. 
        preloaderBackgroundCanvas.style.backgroundImage = "url('" + 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" version="1.1" viewBox="0 0 40 40"> \
        <title>Spinning quarter on the circle</title> \
        <circle cx="20" cy="20" r="16" fill="none" stroke="%23ee4e19" stroke-opacity=".2" stroke-width="5"/> \
        <path d="m1.39 20h4.97c0-8.56 7.05-13.6 13.6-13.6v-5.03c-9.99 0-18.6 8.33-18.6 18.6z" fill="%23ee4e19"> \
            <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 20 20" to="360 20 20" dur="0.6s" repeatCount="indefinite"/> \
        </path></svg>' + "')";
        document.body.appendChild(preloaderBackgroundCanvas);
        // Full version of image
        var fullPicture = new Image();
        backgroundCanvas.onclick = function() { 
            backgroundCanvas.style.top = "50%";
            backgroundCanvas.style.left = "50%";
            backgroundCanvas.style.width = "0";
            backgroundCanvas.style.height = "0";
        };
        var zoomInImgLinks = document.getElementsByClassName("u-BlowUpImgPreload");
        for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
            e.preventDefault();
            // Displaying preloader. If full picture already present in cache, hardly noticable
            preloaderBackgroundCanvas.style.display = "block";
            // Onload event gets fired after src value is assigned, even when url does not change (e.g. multiple click)
            // Image in cache - onload event otherwise downloading starts
            fullPicture.src = e.target.parentNode.href;
            // After image have been downloaded event onload gets fired. Prealoder gets hidden, full image is shown
            fullPicture.onload = function() {
                preloaderBackgroundCanvas.style.display = "none"; // Disable preloader
                backgroundCanvas.style.backgroundImage = "url(" + fullPicture.src + ")";
                backgroundCanvas.style.top = "0";
                backgroundCanvas.style.left = "0";
                backgroundCanvas.style.width = "100%";
                backgroundCanvas.style.height = "100%";
            }
        })
    })
</script>
<!-- HTML -->
<a class="u-BlowUpImgPreload" href="img/stadion-1398391_1920.jpg">
    <img src="img/stadion-1398391_640.jpg" width="640" height="462" alt="Stadion Narodowy, Warszawa">
</a>
<!-- HTML -->

Animated SVG Preloaders

Several examples of animation. As of and update, colors have been declared as custom properties and adjust to dark/light theme accordingly.

Spinning quarter on the circle Spinning half-circle Spinning beams Spinning fading circles Closing circle circumference Spinning 1/8-circle 3 shrinking hanging vertical bars Expanding circles Size-changing rotating hoop slice Bullets spinning on a circle

Zoom transition variations

Smiling eyes, shutter extended up-down

The smiling girl Photo Michael Dam on Unsplash

HTML, CSS, Javascript
    
<style>
.u-ShutterUpDown:hover {
    cursor: zoom-in;
}    
</style>
<script>
    document.addEventListener("DOMContentLoaded", function() {
        var backgroundCanvas = document.createElement("div");
        backgroundCanvas.style.cssText = "position: fixed; top: 50%; left: 0; width: 100%; height: 0; z-index: 1; background: rgba(0,0,0,0.9) none center/auto 100vmin no-repeat; transition: all .8s ease-out; cursor: zoom-out;";
        document.body.appendChild(backgroundCanvas);
        backgroundCanvas.onclick = function() { 
            backgroundCanvas.style.top = "50%";
            backgroundCanvas.style.left = "0";
            backgroundCanvas.style.width = "100%";
            backgroundCanvas.style.height = "0";
        };
        var zoomInImgLinks = document.getElementsByClassName("u-ShutterUpDown");
        for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
            e.preventDefault();
            backgroundCanvas.style.backgroundImage = "url('"+e.target.parentNode.href+"')";
            backgroundCanvas.style.top = "0";
            backgroundCanvas.style.left = "0";
            backgroundCanvas.style.width = "100%";
            backgroundCanvas.style.height = "100%";
        })
    })
</script>
<!-- HTML -->
<a class="u-ShutterUpDown" href="img/michael-dam-mEZ3PoFGs_k-unsplash.jpg">
    <img src="img/michael-dam-mEZ3PoFGs_k-unsplash-min.jpg" alt="The smiling girl">
</a>
<!-- HTML -->
    

Muffin recipe, curtains from the middle to the sides, png animation (apng)

Four slides. Recipe as overlay text. When javascript not present, recipe under thumbnail.

Cookies preparation Photo and performance by Dorota

HTML, CSS, Javascript
<style>
.u-DrawTheCurtains:hover {
    cursor: zoom-in;
}    
</style>
<script>
    document.addEventListener("DOMContentLoaded", function() {
        var backgroundCanvas = document.createElement("div");
        backgroundCanvas.style.cssText = "position: fixed; top: 0; left: 50%; width: 0; height: 100%; overflow: hidden; text-align: center; z-index: 1; background: rgba(255,255,255,0.95) none center/auto 100vmin no-repeat; transition: all .8s ease-out; cursor: zoom-out;";
        backgroundCanvas.innerHTML = document.getElementById("muffinRecipeDetails").innerHTML;//Content in noscript
        document.body.appendChild(backgroundCanvas);
        backgroundCanvas.onclick = function() { 
            backgroundCanvas.style.top = "0";
            backgroundCanvas.style.left = "50%";
            backgroundCanvas.style.width = "0";
            backgroundCanvas.style.height = "100%";
        };
        var zoomInImgLinks = document.getElementsByClassName("u-DrawTheCurtains");
        for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
            e.preventDefault();
            backgroundCanvas.style.backgroundImage = "url('"+e.target.parentNode.href+"')";
            backgroundCanvas.style.top = "0";
            backgroundCanvas.style.left = "0";
            backgroundCanvas.style.width = "100%";
            backgroundCanvas.style.height = "100%";
        })
    })
</script>
<!-- HTML -->
<a class="u-DrawTheCurtains" href="img/muffins-animated.png">
    <img src="img/muffins-composition-min.png" width="384" height="288" alt="Preparation of cookies">
</a>
<span style="font-size: .8em; display: block;">Photo and performance by Dorota</span>
<noscript id="muffinRecipeDetails">
    <h3>Buckwheat-corn flour muffins</h3>
    <ul style="display: inline-block; text-align:left; color: #000; font-size: 1.1em; margin: 0;">
        <li>buckwheat flour - 120 grams</li>
        <li>corn flour - 80 grams</li>
        <li>lemon peel</li>
        <li>juice of half a lemon</li>
        <li>cooking oil - 100 ml</li>
        <li>milk - 100 ml</li>
        <li>eggs - 2 pcs</li>
        <li>Mix eggs with milk</li>
        <li>Combine mixture with flour</li>
        <li>Pour the dough into the cups</li>
        <li>Bake until golden and cracked</li>
    </ul>
</noscript>
<!-- HTML -->
    

Use your imagination or click, curtain from right to left

Girl in black stockings Photo Jan Szwagrzyk on Unsplash

HTML, CSS, Javascript
    
<style>
    .u-CourtainLeftSlowImg:hover {
        cursor: zoom-in;
    }    
</style>
<script>
    document.addEventListener("DOMContentLoaded", function() {
        var backgroundCanvas = document.createElement("div");
        backgroundCanvas.style.cssText = "position: fixed; top: 0; left: 100%; width: 0; height: 100%; z-index: 1; background: rgba(0,0,0,0.9) none center/auto 100vmin no-repeat; transition: all 6s ease-out; cursor: zoom-out;";
        document.body.appendChild(backgroundCanvas);
        backgroundCanvas.onclick = function() { 
            backgroundCanvas.style.top = "0";
            backgroundCanvas.style.left = "100%";
            backgroundCanvas.style.width = "0";
            backgroundCanvas.style.height = "100%";
        };
        var zoomInImgLinks = document.getElementsByClassName("u-CourtainLeftSlowImg");
        for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
            e.preventDefault();
            backgroundCanvas.style.backgroundImage = "url('"+e.target.parentNode.href+"')";
            backgroundCanvas.style.top = "0";
            backgroundCanvas.style.left = "0";
            backgroundCanvas.style.width = "100%";
            backgroundCanvas.style.height = "100%";
        })
    })
</script>
<!-- HTML -->
<a class="u-CourtainLeftSlowImg" href="img/jan-szwagrzyk-0YbvWz-Wxqw-unsplash.jpg">
    <img src="img/jan-szwagrzyk-0YbvWz-Wxqw-unsplash-min.jpg" width="400" height="495" alt="Girl in black stockings">
</a>
<!-- HTML -->