HTML5-like responsive background images in CSS (sort of …)
The purpose of responsive-images-css is to ease the creation process of responsive background images in CSS. It provides similar semantics as responsive images via <img srcset="…" sizes="…">
in HTML5.
The rendering sequence of a standard HTML5 responsive (foreground) image is a highly complex process. It's impossible to fully predict which exact image candidate a browser will pick as some decisions may depend on environment settings that are only available at runtime (such as the network performance).
In contrast, responsive-images-css generates CSS code on the server-side — that is, long before the browser gets to interpret the generated output. To make this work, some asumptions have to be made:
- The generator needs a fixed em to pixel ratio in order to predictably deal with
em
/rem
values. - The generator utilizes the specified breakpoints only, even if the image candidates suggest additional steps.
- The device densities (resolutions) for which the CSS should be rendered must be explictly provided.
Creating a responsive background image always starts with a fresh Generator
instance:
use Jkphl\Respimgcss\Ports\Generator;
$breakpoints = ['24em', '36em', '48em']; // CSS Breakpoints
$emToPixel = 16; // EM to PX ratio
$generator = new Generator($breakpoints, $emToPixel);
As you see in the example, the Generator
accepts a list of CSS breakpoints and an em
to px
ratio as constructor arguments. The latter defaults to 16
if omitted. The breakpoints only get used in combination with a width based image candidates set and a sizes
specification (you can pass in an empty array in all other cases).
Next, you have to register a couple of image candidates for the various states of the responsive image. The file names don't get validated in any way — they will be used as-is for the generated CSS.
// Use a `srcset`-like combined file name + width descriptor string ...
$generator->registerImageCandidate('small-400.jpg 400w');
// ... or an explicit width / resolution descriptor as second argument
$generator->registerImageCandidate('medium-800.jpg', '800w');
$generator->registerImageCandidate('large-1200.jpg', '1200w');
As with HTML5 responsive images, you can use resolution or width based descriptors for the image candidates, but be aware that you're not allowed to mix them within a single image candidate set.
$generator->registerImageCandidate('small-400.jpg', '1x');
$generator->registerImageCandidate('medium-800.jpg', '2x');
Finally, to create the responsive image CSS, call the generator's make()
method and apply a CSS selector of your choice to the resulting CSS ruleset:
$cssRuleset = $generator->make([1.0, 2.0]);
echo $cssRuleset->toCss('.respimg-container');
The list of floating point numbers passed to the make()
method are the device pixel densities / resolutions you want the CSS to be rendered for. If you omit this argument, only the default density 1.0
will be considered. The output will look something like this (not pretty-printed):
.respimg-container {
background-image: url("small-400.jpg");
}
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi),(min-resolution: 2ddpx) {
.respimg-container {
background-image: url("medium-800.jpg");
}
}
As you see in the example, only the background-image
property is specified for the image candidates. For a fully functional responsive image you will need some more lines of CSS — in order to give you full control, however, it's up to you to add this to your overall CSS.
A minimal, all-things-inlined HTML / PHP example document with responsive background image could look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example document with responsive background image</title>
<style>
.respimg {
padding-bottom: 75%; /* 4:3 aspect ratio */
background-repeat: no-repeat;
background-position: top left;
background-size: cover;
}
<?php
$generator = new Jkphl\Respimgcss\Ports\Generator();
$generator->registerImageCandidate('small-400.jpg', '1x');
$generator->registerImageCandidate('medium-800.jpg', '2x');
echo $generator->make([1, 2])->toCss('.respimg');
?>
</style>
</head>
<body>
<div class="respimg"></div>
</body>
</html>
A very powerful feature of HTML5 responsive images is the sizes
attribute which lets you further describe the way your image gets displayed. responsive-images-css aims to support the sizes
specification to a reasonable extent so that you can use the same values as you would for <img srcset="…" sizes="…">
:
$cssRuleset = $generator->make(
[1, 2], // Device resolutions
'(min-width: 400px) 50vw, (min-width: 800px) 33.33vw, 100vw' // Image sizes
);
The Generator
will try to calculate the anticipated image sizes for the registered breakpoints and select the appropriate image candidates accordingly. Please be aware that
sizes
may only be used in combination with width based image candidates sets,- you must provide breakpoints to the
Generator
constructor when usingsizes
and that - the breakpoints used for the
sizes
value should match the registered global breakpoints.
This library requires PHP 7.1 or later. I recommend using the latest available version of PHP as a matter of principle. It has no userland dependencies. It's installable and autoloadable via Composer as jkphl/responsive-images-css.
composer require jkphl/responsive-images-css
Alternatively, download a release or clone this repository, then require or include its autoload.php
file.
To run the unit tests at the command line, issue composer install
and then phpunit
at the package root. This requires Composer to be available as composer
, and PHPUnit to be available as phpunit
.
This library attempts to comply with PSR-1, PSR-2, and PSR-4. If you notice compliance oversights, please send a patch via pull request.
Found a bug or have a feature request? Please have a look at the known issues first and open a new issue if necessary. Please see contributing and conduct for details.
If you discover any security related issues, please email joschi@kuphal.net instead of using the issue tracker.
Copyright © 2018 Joschi Kuphal / joschi@kuphal.net. Licensed under the terms of the MIT license.