Images
Images can be embedded with <img> and with the CSS background-image.
| Supported formats | PNG, JPEG, WebP |
|---|---|
What src may contain | A local relative or absolute path, an http(s) URL, or a data: URI |
SVG and GIF are not supported.
<img>
<img src="logo.png" width="120">
<img src="https://example.com/chart.png" alt="Sales over time">
<img src="data:image/png;base64,iVBORw0…">
- An
<img>sits on the line as an inline replaced element. Give itdisplay: blockto put it on a line of its own - The
widthandheightattributes and the CSSwidthandheightare both honoured. With neither, the intrinsic size is used; with only one, the other is derived while keeping the aspect ratio - An image that cannot be fetched or decoded leaves just that element empty; it does not stop the document from being produced. Pass
--load-media-error-handling abortto stop instead - However many times the same image is used, it is fetched, decoded, and embedded once
object-fit and object-position
These control how the image is fitted into the box you give it.
img.thumb {
width: 120px;
height: 80px;
object-fit: cover; /* fill | contain | cover | none | scale-down */
object-position: 50% 50%;
}
Background images
.watermark {
background-image: url("stamp.png");
background-position: center;
background-size: contain;
background-repeat: no-repeat;
}
Only url() is accepted in background-image. Gradient functions such as linear-gradient() and comma separated multiple backgrounds are not supported. By default the image is tiled at its intrinsic size.
When border-radius is combined with a background image, the image is not clipped to the rounded corners; the radius applies only to the background colour.
Fetching remote images
This is off by default. Turn it on explicitly with --allow-remote-assets.
sghtmltopdf report.html --allow-remote-assets
Even when enabled, requests to destinations that are not globally reachable are always blocked. The rule is to allow only global unicast; the following are rejected.
| Kind | Ranges |
|---|---|
| Loopback | 127.0.0.0/8, ::1 |
| Private | 10/8, 172.16/12, 192.168/16, fc00::/7 |
| Link-local | 169.254/16 (including the cloud metadata endpoint 169.254.169.254), fe80::/10 |
| CGNAT | 100.64.0.0/10 (cloud-internal load balancers and the like) |
| Other non-global | 0.0.0.0/8, 192.0.0.0/24, 198.18.0.0/15, 240.0.0.0/4, multicast, documentation |
| IPv6 special-purpose | Teredo 2001::/32, 2001:db8::/32, ORCHIDv2 2001:20::/28, 100::/64 |
IPv6 forms that embed an IPv4 address (IPv4-mapped ::ffff:a.b.c.d, IPv4-compatible ::a.b.c.d, NAT64 64:ff9b::/96, 6to4 2002::/16) are judged by the embedded IPv4 address. Letting them through would allow the IPv4 filter to be bypassed.
The check is applied to the result of name resolution, so DNS rebinding and redirect-based bypasses are prevented by the same mechanism.
Private
Ranges
sghtmltopdf untrusted.html --allow /var/app/assets
JPEG is embedded as is
JPEG images are not decoded. Only their dimensions are read, and the data goes into the PDF unchanged, as DCTDecode. Nothing is re-encoded, so quality is preserved and conversion is faster.
The trade-off is that --grayscale leaves JPEG and CMYK images in colour, since there is no decoder for them. If you need them in greyscale, convert the images before rendering.
PNG and WebP are fully decoded, and an alpha channel is carried through as transparency.
Loading no images at all
sghtmltopdf invoice.html --no-images
This stops both <img> and the CSS background-image from being loaded.