- How to Create an Image Lightbox in Pure CSS
- In this article
- The :target Selector#
- Building The Lightbox#
- Wrap-up#
- How TO — Lightbox
- Lightbox (Modal Image Gallery)
- Create A Lightbox
- Example
- Example
- Example
- Lightbox
- Initialize with HTML
- Options
- Browser support
- License
- Help
- Have a question about how to use Lightbox?
- Found a bug?
How to Create an Image Lightbox in Pure CSS
In this article
Cascading Style Sheets (CSS) is the language used to describe the presentation of a web page, which is where it stops for most of us. However, CSS can also be used to for stateful components, in place of JavaScript.
Today, we’ll demonstrate how to build an image lightbox in pure CSS and HTML, no JavaScript required.
See the Pen Pure CSS Lightbox by Gregory Schier (@gschier) on CodePen.
Here are the requirements for the lightbox:
- Must show lightbox when clicking thumbnail
- Must load image after lightbox is shown
- Must hide lighbox after clicking enlarged image
The :target Selector#
The stateful nature of this implementation comes from the :target selector. It’s what allows us to keep the lightbox visible after the click has ended.
The target selector can be used in CSS to style elements like this.
The selector becomes active when the img element contains an id attribute equal to the URL fragment (eg. https://codesalad.dev/#some-id ).

The lightbox takes advantage of this by doing the following:
- Include
thumbnail on page
- Wrap thumbnail in link .
- Include hidden lightbox below thumbnail with id=some-hash
- Use CSS to show lightbox when it is the :target
- Wrap lightbox in to unset the target on click
NOTE: We use #_ instead of # to unset the URL hash because browsers will interpret # as an instruction to scroll to the top of the document.
Building The Lightbox#
So, here’s what the HTML will look like for our lightbox. We’ll need to add both the thumbnail and lightbox to make it work. When adding multiple lightboxes, ensure they use different id attributes.
And here’s the CSS to go along with it. I added some comments to explain what’s going on.
.lightbox < /* Default to hidden */ display: none; /* Overlay entire screen */ position: fixed; z-index: 999; top: 0; left: 0; right: 0; bottom: 0; /* A bit of padding around image */ padding: 1em; /* Translucent background */ background: rgba(0, 0, 0, 0.8); >/* Unhide the lightbox when it's the target */ .lightbox:target < display: block; >.lightbox span < /* Full width and height */ display: block; width: 100%; height: 100%; /* Size and position background image */ background-position: center; background-repeat: no-repeat; background-size: contain; >
Wrap-up#
That’s all it takes to create a stateful lightbox in pure CSS. Here’s the full working example, included below. Be sure to observe how the URL changes when showing and hiding the lightbox.
I hope that was helpful in showcasing some of CSS’s lesser-known uses. Note that this implementation was meant for learning purposes and isn’t recommended for production use, mostly for accessibility reasons.
How TO — Lightbox
Learn how to create a modal image gallery (lightbox) with CSS and JavaScript.
Lightbox (Modal Image Gallery)
Click on one of the images to open the lightbox:
Create A Lightbox
The following example combines code from Modals and Slideshows to create the lightbox.
Step 1) Add HTML:
Example
Step 2) Add CSS:
Example
.row > .column <
padding: 0 8px;
>
.row:after content: «»;
display: table;
clear: both;
>
/* Create four equal columns that floats next to eachother */
.column float: left;
width: 25%;
>
/* The Modal (background) */
.modal display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: black;
>
/* Modal Content */
.modal-content position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
width: 90%;
max-width: 1200px;
>
/* The Close Button */
.close color: white;
position: absolute;
top: 10px;
right: 25px;
font-size: 35px;
font-weight: bold;
>
.close:hover,
.close:focus color: #999;
text-decoration: none;
cursor: pointer;
>
/* Hide the slides by default */
.mySlides display: none;
>
/* Next & previous buttons */
.prev,
.next cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -50px;
color: white;
font-weight: bold;
font-size: 20px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
>
/* Position the «next button» to the right */
.next right: 0;
border-radius: 3px 0 0 3px;
>
/* On hover, add a black background color with a little bit see-through */
.prev:hover,
.next:hover background-color: rgba(0, 0, 0, 0.8);
>
/* Number text (1/3 etc) */
.numbertext color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
>
/* Caption text */
.caption-container text-align: center;
background-color: black;
padding: 2px 16px;
color: white;
>
img.hover-shadow transition: 0.3s;
>
.hover-shadow:hover box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
>
Step 3) Add JavaScript:
Example
// Close the Modal
function closeModal() document.getElementById(«myModal»).style.display = «none»;
>
var slideIndex = 1;
showSlides(slideIndex);
// Next/previous controls
function plusSlides(n) showSlides(slideIndex += n);
>
// Thumbnail image controls
function currentSlide(n) showSlides(slideIndex = n);
>
function showSlides(n) var i;
var slides = document.getElementsByClassName(«mySlides»);
var dots = document.getElementsByClassName(«demo»);
var captionText = document.getElementById(«caption»);
if (n > slides.length)
if (n < 1)
for (i = 0; i < slides.length; i++) slides[i].style.display = "none";
>
for (i = 0; i < dots.length; i++) dots[i].className = dots[i].className.replace(" active", "");
>
slides[slideIndex-1].style.display = «block»;
dots[slideIndex-1].className += » active»;
captionText.innerHTML = dots[slideIndex-1].alt;
>
Tip: Also check out Modals and Slideshows.
Lightbox
- Download a zip of the latest release (or any previous one) from the Github Releases page.
npm install lightbox2 --save
- If you already use jQuery on your page, make sure it is loaded before lightbox.js . jQuery 1.7 or greater is required, and since the effects module is utilized, the jQuery slim build is not supported.
- If you are not currently using jQuery, I’ve created a packaged file that includes both Lightbox and jQuery. Include dist/js/lightbox-plus-jquery.js instead of lightbox.js .
Initialize with HTML
- Single images. Add a data-lightbox attribute to any image link to enable Lightbox. For the value of the attribute, use a unique name for each image. For example:
- Add a data-title attribute if you want to show a caption.
- Add a data-alt attribute if you want to set the alt attribute of the linked image.
Options
If you want to change any of the default options, call the option method.
Option | Default | Description |
---|---|---|
alwaysShowNavOnTouchDevices | false | If true, the left and right navigation arrows which appear on mouse hover when viewing image sets will always be visible on devices which support touch. |
albumLabel | «Image %1 of %2» | The text displayed below the caption when viewing an image set. The default text shows the current image number and the total number of images in the set. |
disableScrolling | false | If true, prevent the page from scrolling while Lightbox is open. This works by settings overflow hidden on the body. |
fadeDuration | 600 | The time it takes for the Lightbox container and overlay to fade in and out, in milliseconds. |
fitImagesInViewport | true | If true, resize images that would extend outside of the viewport so they fit neatly inside of it. This saves the user from having to scroll to see the entire image. |
imageFadeDuration | 600 | The time it takes for the image to fade in once loaded, in milliseconds. |
maxWidth | If set, the image width will be limited to this number, in pixels. Aspect ratio will not be maintained. | |
maxHeight | If set, the image height will be limited to this number, in pixels. Aspect ratio will not be maintained. | |
positionFromTop | 50 | The distance from top of viewport that the Lightbox container will appear, in pixels. |
resizeDuration | 700 | The time it takes for the Lightbox container to animate its width and height when transition between different size images, in milliseconds. |
showImageNumberLabel | true | If false, the text indicating the current image number and the total number of images in set (Ex. «image 2 of 4») will be hidden. |
wrapAround | false | If true, when a user reaches the last image in a set, the right navigation arrow will appear and they will be to continue moving forward which will take them back to the first image in the set. |
Browser support
Lightbox2 has been tested successfully in the following browsers:
- Internet Explorer.
The lightbox-plus-jquery.js file includes jQuery v2.x and supports IE 9+. If you want to support IE 6, 7, and 8, use your own copy of jQuery v1.x with lightbox.js . - Chrome
- Safari
- Firefox
- iOS Safari
- iOS Chrome
- Android Browser
- Android Chrome
License
Lightbox2 is licensed under The MIT License.
- 100% Free. Lightbox is free to use in both commercial and non-commercial work.
- Attribution is required. This means you must leave my name, my homepage link, and the license info intact. None of these items have to be user-facing and can remain within the code.
Help
Have a question about how to use Lightbox?
Follow the steps below to get help. Make sure you have read the documentation on this page and looked at the included example first.
- Search Stackoverflow to see if other people have run into the same issue you are having.
- If your issue is unique, then post a new question on Stackoverflow. Use the lightbox2 tag.
Do not use Github Issues to report personal support requests.
Found a bug?
If you find a bug, please file a Github issue.