Zooming image (simple lightbox - medium.com style)
- 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
Photo Dawida Łabno on Unsplash
Enlarge the best part
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
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.
Zoom transition variations
Smiling eyes, shutter extended up-down
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.
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
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 -->