Integrating "Retina" images into web pages presents an ongoing challenge for developers, who suffer from poor browser support, delayed standards implementation, a fragmented market and complex intermediate solutions.
In contrast, switching in high-DPI images for fullscreen browser display is both a necessity and relatively easy:
- Thumbnail images will look awful when expanded to fullscreen size on most screens, demanding a solution.
- In most cases fullscreen mode will be used to display just a few images, allowing us to concentrate on edge cases rather than trying to code a solution for every image on the site.
- Fullscreen mode must be engaged by the user, allowing plenty of opportunity to preload images before user interaction.
- Fullscreen mode is not yet supported on mobile devices, so we don’t have to worry about crushing bandwidth.
Broadly speaking there are two solutions for switching in images with the Fullscreen API: CSS and JavaScript.
The CSS Approach
While the Fullscreen API is completely JavaScript, it makes one addition to CSS: the :fullscreen pseudo-selector, which is only active when the selected element is displayed in fullscreen mode. Rather oddly, this pseudo-selector is both hyphenated and vendor-prefixed in current browsers, resulting in :-webkit-full-screen, :-moz-full-screen, etc.
While it’s possible to use :full-screen on an image directly to alter its appearance on a page, it can’t be used to swap out an image in that way. A better solution is to place the HiDPI as an alternative to the background, revealing it when the parent of element is promoted to fullscreen display:
In this case, I’ll place the image content inside a header:
header { display: block; width:80%; max-width: 1000px; margin: 0 auto;
background: url(medusa-lores.jpg');
background-size: contain; }
header img { width: 100%; opacity: 0; }
I’ll provide the container element with a copy of the image in order to maintain the correct aspect ratio. This copy is made completely transparent via CSS to show the version that is the background image.
<header>
<img src="medusa-lores.jpg" alt="Medusa">
</header>
When fullscreen mode is initiated, we can use the :fullscreen pseudo-selector to swap out the background image:
:-moz-full-screen, :-webkit-full-screen, :fullscreen { width: 100%; background: url('medusa-hirres.jpg'); }
(Of course, you would also need the UI and JavaScript to initiate fullscreen mode, which I’ve covered in a previous article).
While this works, it doesn’t scale well: you’d need to write a separate rule for each thumbnail/HiDPI pair. The technique also downloads the high-resolution version of the image regardless of device, platform, or user interaction. You could get around the first two issues by placing the background image in a media query, while using an opportunity to make a further test that the screen has enough pixels to show the high resolution version of the image: there’s no point in loading it if that is not the case. Assuming that the hi-res version is 1600 pixels wide, our test would be that the screen is at least that wide, or a HiDPI display. You could do this within a media query:
@media screen and (min-device-width: 1600px) or (-webkit-min-device-pixel-ratio: 2) or (-moz-min-device-pixel-ratio: 2) or (min-device-pixel-ratio: 2) {
:-moz-full-screen, :-webkit-full-screen, :fullscreen {
width: 100%; background: url('medusa-hirres.jpg'); }
}
… but it’s still not a great solution for anything more than one or two images. A better, albeit more complex alternative, is JavaScript.
The JavaScript Method
The equivalent, albeit more complex JavaScript alternative involves rolling the test into the fullscreen JavaScript function with a matchMedia test. Assuming that the original thumbnail image is inside an element with a id of #bigpic that will request fullscreen display:
function launchFullscreen(element) {
if (element.requestFullScreen) {
element.requestFullScreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullScreen) {
element.webkitRequestFullScreen();
} else if (element.msRequestFullScreen) {
element.msRequestFullScreen();
}
if (screen.width >= 1600 || window.matchMedia("(-webkit-min-device-pixel-ratio: 2) or (-moz-min-device-pixel-ratio: 2) or (min-device-pixel-ratio: 2)")) {
document.querySelector("#bigpic img").setAttribute("src", "medusa-hires.jpg"); }
}
And in your HTML:
<figure id="bigpic">
<img src="medusa-hires.jpg" alt="Medusa">
<figcaption><button onclick="launchFullscreen(document.querySelector('#bigpic'))">
Fullscreen Image</button></figcaption>
</figure>
You’ll notice that when returning to normal display mode, the image is kept in the high-resolution version, assuming that your screen was large enough to switch the image. We'll look at improving the script, resetting the effect correctly and better UI controls for fullscreen displays in the next article.