💾 Archived View for sylvaindurand.org › overlay-image-in-pure-css › index.gmi captured on 2022-04-29 at 11:23:06. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2022-04-28)
-=-=-=-=-=-=-
There is no native solution within browsers to display, on click, a full screen image. Several Javascript libraries have come to fill this gap: Lightbox (which was a precursor, to the point of giving its name to the concept), Fancybox, PhotoSwipe...
These solutions are sometimes heavy, whereas if you are only looking for a simple behavior, a few lines of CSS are enough, and no Javascript code is required.
We will use the CSS selector `:target`, which allows to apply a style to an element when its identifier (`id=""`) is the one of the anchor (`#`) in the page URL. To take an example:
<a href="#myid">Click to color in red!</a> <div id="myid">Hello World!</div> <style> div:target { color: red; } </style>
Note that this selector actually allows you to add a lot of interactive elements to a page without Javascript, such as showing and hiding an element or a navigation bar.
According to developer.mozilla.org and caniuse.com, the `:target` selector is supported by all browsers released since 2008, and especially since Internet Explorer 9.
For each image, the HTML markup will be as simple as possible:
<!-- The link that, when clicked, will display the image in full screen --> <a href="#img-id"> <img src="image-thumbnail.png" alt="Thumbnail"> </a> <!-- The full screen image, hidden by default --> <a href="#_" class="overlay" id="img-id"> <img src="image-fullscreen.png" alt="Fullscreen"> </a>
The first line, customizable at will, will display the image in full screen thanks to the link to `#img-id`. The second, hidden by default, contains the corresponding identifier.
If several images are present on the page, it will obviously be necessary to give them a unique identifier for each one, and to match the link.
The link to `#_` has no particular meaning, and could have been replaced by `#anything`. It simply aims to cause `#img-id` to lose the status `:target` and therefore to close the full screen when clicking.
The overlay is nothing more than a `div` with a fixed position, located at the top left and covering the entire page. We add a `flex` property to it to place the image in the center of it:
.overlay { /* Display over the entire page */ position: fixed; z-index: 99; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); /* Horizontal and vertical centering of the image */ display: flex; align-items: center; text-align: center; /* We hide all this by default */ visibility: hidden; } .overlay img{ /* Maximum image size */ max-width: 90%; max-height: 90%; /* We keep the ratio of the image */ width: auto; height: auto; }
As we have seen previously, we now have to add a `visibility: visible` with the selector `:target` to display all this when you click on the trigger link.
.overlay:target { visibility: visible; outline: none; cursor: default; }
We add an `outline: none` to avoid the border that is displayed, by default, on several browsers. In addition, `cursor: default`, optional, avoids having a "hand" in place of the cursor on the entire page.
The Javascript libraries mentioned above allowed to have a nice fade effect when opening. Never mind: CSS allows almost any kind of madness in terms of animation.
We're going to stay sober here, with a slight bland effect, with a very small zoom effect on the image.
.overlay { opacity: 0; transition: opacity .3s; } .overlay img { transform: scale(0.95); transition: transform .3s; } .overlay:target img { transform: scale(1); }
Finally, our CSS code became:
.overlay { position: fixed; z-index: 99; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); display: flex; align-items: center; text-align: center; visibility: hidden; opacity: 0; transition: opacity .3s; } .overlay img{ max-width: 90%; max-height: 90%; width: auto; height: auto; transform: scale(0.95); transition: transform .3s; } .overlay:target { visibility: visible; outline: none; cursor: default; } .overlay:target img { transform: scale(1); }
With the static website generator Hugo, you can easily automate the process with a shortcode. To do so, we create a `img.html` file in `layouts/shortcodes/` :
<a href="#{{ anchorize (.Get "src") }}"> <img src="{{.Get "src" }}" alt="{{.Get "alt" }}" /> </a> <a href="#_" class="overlay" id="{{ anchorize (.Get "src") }}"> <img src="{{.Get "src" }}" alt="{{.Get "alt" }}"> </a> {{ .Inner }}
Then, you just have to add, in your articles:
{{</* img src="image.jpg" alt="Description" /*/>}}