Images
Add an image to a post, give it alt text, and see what Statac makes from it.
Put an image beside a post and name it in the content, and Statac publishes it. Statac publishes a JPEG, or a PNG or WebP that isn’t animated, as resized copies to suit different screens.
Add an image to a post
content/
post-1/
index.md
photo-1.jpg
post-2.md
photo-2.jpg
In post-1/index.md:

The text in the brackets is the image’s alt text, for readers who can’t
see it. post-2.md shows photo-2.jpg in the same way.
| Write | What the page shows |
|---|---|
 | The image, where you wrote it: inside its sentence, or on its own in a paragraph. |
@figure("photo-1.jpg", alt="Alt text", caption="Photo 1.") | The image in a <figure>, with its caption beneath. If you leave out alt or caption, the snippet uses the ones in the image’s .yaml file. wide=true adds the class wide to the figure, and decorative=true marks the image as decorative. |
@gallery("photo-1.jpg", "photo-2.jpg") | Several images, each linking to its largest copy. On a page that has a folder of its own, @gallery() with no names shows every JPEG beside the page, and every PNG or WebP there that isn’t animated. |
@figure and @gallery call the site’s own snippets,
snippets/figure.html and snippets/gallery.html: Statac has none of
its own. The table describes the ones in the drop-ins,
which you can copy into snippets/ and change.
How Statac finds a name
| Written as | Where Statac looks |
|---|---|
photo-1.jpg | Beside the file it is written in. |
/img/logo.png | From the top of the site: content/img/logo.png, or static/img/logo.png if that doesn’t exist. |
https:/ | Nowhere. Statac leaves the URL unchanged. |
<img src="photo-1.jpg"> | Nowhere. Statac publishes HTML you write exactly as you wrote it. |
If the site’s URL has a path, such as https:/,
Statac adds the path to an image name that starts with /, so the name
doesn’t need @url(...). A link
does.
Write its alt text, or mark it decorative
The alt text goes in the brackets. For an image under content/, you
can also write it once, in a file beside the image. That file has the
image’s name with .yaml added on the end. In photo-1.jpg.yaml:
alt: A gradient from blue to orange
caption: Photo 1.
credit: A photographer
| Line | What it does |
|---|---|
alt | The alt text. Statac uses it wherever the content shows the image without alt text, as in . |
caption | Text to show with the image. @figure shows it. |
decorative | true for an image that is only decoration and needs no alt text. |
optimise | false publishes the original file instead of resized copies. |
Any other, such as credit | A custom field. Templates can read it along with the other lines. |
Statac never publishes the .yaml file.
Markdown can’t tell empty brackets apart from alt text you left out, so mark an image that is only decoration in one of these ways:
decorative: truein the image’s.yamlfile@figure("flourish-1.png", decorative=true)in the content, orpage.image("flourish-1.png", decorative=true)in a templatealt=""on an<img>you write yourself, the standard HTML way
Resized copies
Statac publishes each JPEG, and each PNG or WebP that isn’t animated, as resized copies at several widths. Screenshots get them too. The reader’s browser fetches the copy that suits its screen.
| The image’s width | Widths of its copies, with max_width set to 1600 |
|---|---|
| 3000 | 400, 800, 1200, 1600 |
| 1500 | 400, 800, 1200, 1500 |
| 850 | 400, 850 |
| 300 | 300 |
Statac makes a copy at each of these widths that is under nine tenths of
the image’s width: 400, 800, 1200, 1600 and 2400 pixels. It also makes
one at the image’s own width. No copy is wider than
max_width. If the image is wider than max_width and
max_width is one of those widths, Statac makes a copy at max_width
too, so an image 1700 pixels wide gets 400, 800, 1200 and 1600.
| Statac makes each width as | When |
|---|---|
| AVIF | Always. |
| JPEG | For browsers that don’t show AVIF. |
| PNG, instead of the JPEG | If any pixel of the image is transparent. A PNG or WebP that could be transparent but isn’t, as with most screenshots, gets the JPEG. |
If the camera was on its side when it took the image, Statac turns the copies upright. If the image uses a wider colour space than sRGB, Statac converts the copies so the colours look the same. The copies keep nothing else from the original file: not where or when the image was taken, nor the device that took it.
Statac publishes each copy where it would have published the original
file. Its name includes its width and a short hash that changes
whenever the copy changes: photo-1-800.b99b7f22.jpg.
The original file
| The image | What Statac publishes |
|---|---|
| A page shows it | Its resized copies. |
A page links to it, as in [the full-size image](photo-1.jpg), or names it in og_image | The original file, whether or not a page shows it. |
| No page shows it or links to it | The original file. |
Statac publishes the original file byte for byte, so it keeps all its metadata, such as where and when the image was taken and the device that took it. Its resized copies keep none of that.
If Statac publishes the original file of a JPEG, PNG or WebP, and its
metadata records where it was taken, statac check
shows a note:
note Location published: `content/photo-1.jpg` holds where it was taken in its metadata
Publish a copy without it, or add `location-published` to `quiet:` in `statac.yaml`.
More: https://statac.dev/e/location-published/
statac build and statac serve don’t show it. statac check looks
inside every image from content/ whose original file Statac
publishes, but never inside a file in static/.
Which images get resized copies
| Kind of file | What Statac publishes | What it writes into the page |
|---|---|---|
| JPEG, or a PNG or WebP that isn’t animated | Resized copies | A <picture> listing the copies |
| An animated PNG or WebP | The original file | An <img> with its width and height |
| GIF, SVG or AVIF | The original file | An <img> with its width and height |
| HEIC or HEIF | The original file | An <img> with no width or height |
Statac tells an image’s kind from the file’s contents, not from its
name. It knows an SVG’s size only if the SVG’s first tag sets a width
and a height in pixels.
Statac doesn’t read HEIC or HEIF, and few browsers can show them. Export the image as a JPEG and use that instead.
The HTML Statac writes
For a GIF, which Statac publishes as the original file:
<img src="drawing-1.gif" alt="How the parts fit" width="640" height="400" loading="lazy" decoding="async">
For a JPEG, which Statac publishes as resized copies:
<picture><source type="image/avif" srcset="photo-1-400.6ebf7d7e.avif 400w, photo-1-800.0f4dfc73.avif 800w" sizes="(max-width: 46rem) 100vw, 46rem"><img src="photo-1-800.b99b7f22.jpg" srcset="photo-1-400.8d7f3a18.jpg 400w, photo-1-800.b99b7f22.jpg 800w" sizes="(max-width: 46rem) 100vw, 46rem" width="800" height="533" alt="A gradient from blue to orange" loading="lazy" decoding="async"></picture>
The browser chooses a copy by the sizes attribute, which Statac fills
from the site’s image_sizes setting.
Warning
If your stylesheet sets a max-width or a width on img to make
images narrower, set height: auto as well. Otherwise the browser
shows a narrowed image too tall.
The first build
Made 60 resized copies of 11 images.
Statac keeps every copy in .statac/, in the site’s folder, so later
builds only make copies of images that are new or have changed.
After each build, Statac removes from .statac/ any copies that no page
shows any more. A build with
--url adds copies but never
removes any.
statac check makes no copies and writes nothing.
Change what Statac makes
In statac.yaml:
max_width: 2400
max_width- Default 1600
- The widest a resized copy can be, in pixels. If it is under 400, each image gets one copy. It applies to the whole site: Statac ignores it in an image’s
.yamlfile. image_sizes- Default
(max-width: 46rem) 100vw, 46rem - How wide the page shows images, written as the
sizesof an<img>. For example,(max-width: 40rem) 100vw, 40remsuits a column 40rem wide that fills the screen on narrow screens. optimise_images- Default
true falsestops Statac making resized copies: it publishes the original file of each image.
Publish one image’s original file
In photo-1.jpg.yaml:
optimise: false
Statac publishes the original file and makes no
resized copies. In the page it writes an <img> with the image’s width
and height, as it does for a GIF.
Images in templates and snippets
{% set image = page.image("photo-1.jpg") %}
<img src="{{ image.src }}" width="{{ image.width }}" height="{{ image.height }}" alt="{{ image.alt }}">
page.image finds an image by name the same way a Markdown
image does. It works on any page, so a list can show each post’s image
with post.image(post.cover).
An image in the Reference gives each of its names:
src, the avif and fallback copies, sizes, full, width and
height, alt and caption, and name. Every other line in the
image’s .yaml file is a name too, such as image.credit. With
full=true, Statac makes one more copy at the image’s own width, as a
JPEG or PNG only, whatever max_width says.
decorative=true marks the image as decorative in the place you show
it.
page.images(["photo-1.jpg", "photo-2.jpg"]) returns several images,
in the order you name them. On a page that has a folder of its own,
page.images() returns every JPEG beside the page, and every PNG or
WebP there that isn’t animated, in file name order. Both take sizes,
full and decorative.
You get files, videos and audio in the same way: see files and videos in a template.
Where next?
- Videos and files: videos, audio and files beside a post, and videos kept on YouTube or Vimeo
- Writing: Markdown, links and snippet calls
- Social cards: the image a link preview shows
- Settings: everything in
statac.yaml
Something unclear or wrong? Open an issue.