Write
Pictures
Keep a picture beside the post, name it in the writing, and Statac publishes it, a photograph as smaller copies made for each screen.
Add a picture to a post
content/
post-1/
index.md
photo-1.jpg
post-2.md
photo-2.jpg
In post-1/index.md:

The brackets hold what a reader who can’t see the picture is given.
post-2.md shows photo-2.jpg the same way.
| Write | What the page shows |
|---|---|
 |
The picture where it is written: in its sentence, or alone in its paragraph. |
@figure("photo-1.jpg", alt="A description", caption="Photo 1.") |
The picture in a <figure>, with its caption beneath. Without alt or caption, those in the picture’s own file. wide=true gives the figure the class wide, and decorative=true marks it as decoration. |
@gallery("photo-1.jpg", "photo-2.jpg") |
Several pictures, each a link to its largest copy. @gallery() shows every photograph beside a page that has a folder of its own. |
@figure and @gallery are snippets a new site has, yours to change:
see the starter.
How a name is found
| Written | Found |
|---|---|
photo-1.jpg |
Beside the file it is written in. |
/img/logo.png |
From the top: content/img/logo.png, or else static/img/logo.png. |
https://example.org/photo-1.jpg |
Not looked for: left as written. |
<img src="photo-1.jpg"> |
Not looked for: HTML you write is published as you wrote it. |
On a site published under a path, such as https://example.org/blog/,
a picture written from / needs no
@url(...), unlike a link.
Describe it, or mark it decorative
A description goes in the brackets. For a picture under content/, it
can also be written once, in a file beside the picture named after it
with .yaml 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 description, used wherever the picture is shown without one, as . |
caption |
Words to show with the picture. @figure shows them. |
decorative |
true for a picture that is only decoration and needs no description. |
optimise |
false publishes the file in place of copies. |
Any other, such as credit |
Yours: it reaches templates with the rest. |
The file is never published.
Markdown can’t tell empty brackets from a description left out, so mark a picture that is only decoration in one of these ways:
decorative: truein the picture’s own file@figure("flourish-1.png", decorative=true)in the writing, orpage.photo("flourish-1.png", decorative=true)in a templatealt=""on an<img>of your own, as HTML says it
What Statac makes from a photograph
A photograph is a JPEG, or a PNG or WebP that doesn’t move: screenshots too. Statac publishes copies at several widths, and the reader’s browser fetches the one that suits its screen.
| The photograph’s width | Its copies, with max_width at 1600 |
|---|---|
| 3000 | 400, 800, 1200, 1600 |
| 1500 | 400, 800, 1200, 1500 |
| 850 | 400, 850 |
| 300 | 300 |
Copies are made at 400, 800, 1200, 1600 and 2400 pixels wide, each where
it is under nine tenths of the photograph’s width, and at the
photograph’s own width. None is wider than max_width.
| Each width is made as | When |
|---|---|
| AVIF | Always. |
| JPEG | For the browsers that don’t show AVIF. |
| PNG, in place of the JPEG | Where some pixel of the picture is see-through. A PNG or WebP that could be transparent and isn’t, as most screenshots are, gets the JPEG. |
A photograph taken with the camera turned is turned upright. One in a wider colour space than the web’s is converted so its colours look the same. The copies carry nothing else of the file: not where or when it was taken, nor what took it.
Each copy is published beside where the photograph would be, named with
its width and a mark that changes whenever the copy does:
photo-1-800.5e6f7a8b.jpg.
The photograph itself
| The photograph | What is published |
|---|---|
| A page shows it | Its copies. |
A page links to it, as [the whole photograph](photo-1.jpg), or names it with og_image |
The file itself, whether or not a page shows it. |
| No page shows it or links to it | The file itself. |
The file itself is published byte for byte, so it carries whatever it held: where and when it was taken, what took it. Its copies carry none of that.
Where a JPEG, PNG or WebP published as it is holds where it was taken,
statac check notes it:
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 say nothing of it. The same goes for
every picture published from content/ as it is. statac check never
looks inside a file in static/.
Which pictures get copies
| Kind of file | Published as | Written into the page |
|---|---|---|
| JPEG, or a PNG or WebP that doesn’t move | Copies | A <picture> naming the copies |
| A PNG or WebP that moves | The file as it is | An <img> with its width and height |
| GIF, SVG or AVIF | The file as it is | An <img> with its width and height |
| HEIC or HEIF | The file as it is | An <img> with no size |
Statac tells a picture’s kind by what the file holds, not by its name.
An SVG has a size only where its first tag gives a width and a
height in pixels.
Statac doesn’t read HEIC or HEIF, and few browsers show one. Export the photograph as a JPEG and show that.
What goes in the page
For a picture published as it is:
<img src="/post-1/drawing-1.gif" alt="How the parts fit" width="640" height="400" loading="lazy" decoding="async">
For a photograph:
<picture><source type="image/avif" srcset="/post-1/photo-1-400.1a2b3c4d.avif 400w, /post-1/photo-1-800.2e3f4a5b.avif 800w" sizes="(max-width: 46rem) 100vw, 46rem"><img src="/post-1/photo-1-800.5e6f7a8b.jpg" srcset="/post-1/photo-1-400.9c0d1e2f.jpg 400w, /post-1/photo-1-800.5e6f7a8b.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, which the site’s
image_sizes gives.
Warning:
A stylesheet that narrows pictures with a max-width or a width on
img needs height: auto beside it, or a picture made narrower is
shown too tall.
The first build
Made 60 copies of 11 photographs.
Statac keeps every copy in .statac/, in the site’s folder, so a later
build makes copies only of photographs new or changed.
After a build that publishes the site, Statac removes the copies no page
shows any more. A build with
--url adds copies and removes
none.
statac check makes no copies and writes nothing.
Change what Statac makes
In statac.yaml:
max_width: 2400
| Setting | What it does | Unless you say |
|---|---|---|
max_width |
No copy is wider, in pixels. Under 400, each photograph gets one copy. It is for the whole site: in a picture’s own file it changes nothing. | 1600 |
image_sizes |
How wide photographs are shown on the page, as the sizes of an <img>: (max-width: 40rem) 100vw, 40rem for a column 40rem wide that fills a narrow screen. |
(max-width: 46rem) 100vw, 46rem |
optimise_images |
false makes no copies: each photograph is published as it is. |
true |
Leave a photograph as it is
In photo-1.jpg.yaml:
optimise: false
The photograph is published as it is, and written into the page as any other picture is, with its width and height.
Pictures in templates and snippets
{% set picture = page.photo("photo-1.jpg") %}
<img src="{{ picture.src }}" width="{{ picture.width }}" height="{{ picture.height }}" alt="{{ picture.alt }}">
page.photo finds a name as the writing does. Any page can be asked, so
a list shows each post’s picture with post.photo(post.cover).
| Field | What it is |
|---|---|
src |
The address to show: a photograph’s copy 1,200 pixels wide, or its widest where none is that wide. |
avif, fallback |
A photograph’s copies, as AVIF and as JPEG or PNG, each a srcset. Empty for a picture published as it is. |
sizes |
The site’s image_sizes, or the call’s: page.photo("photo-1.jpg", sizes="(max-width: 30rem) 100vw, 15rem"). |
full |
The widest copy’s address, to link to. With full=true, one more copy at the photograph’s own width, whatever max_width says. For a picture published as it is, the picture. |
width, height |
The size in pixels, a photograph’s once turned upright. Empty where it isn’t known. |
alt, caption |
What the picture’s own file says, or empty. |
name |
The file’s name read as words: photo-1.jpg as “Photo 1”. |
| A line of your own | Each other line of the picture’s file, as picture.credit. |
decorative=true marks the picture as decoration where it is shown.
page.photos(["photo-1.jpg", "photo-2.jpg"]) gives pictures in the order
named, and page.photos() every photograph beside a page that has a
folder of its own. Both take sizes, full and decorative.
Files, videos and recordings are asked for the same way: videos and files.
Where next?
- Videos and files: videos, recordings and files beside a post, and videos kept on YouTube or Vimeo
- Writing: Markdown, links and snippet calls
- Sharing cards: the picture a link preview shows
- Settings: everything in
statac.yaml
Something unclear or wrong? Open an issue on GitHub.