Statac

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:

![A gradient from blue to orange](photo-1.jpg)

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
![Alt text](photo-1.jpg) 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://example.org/photo-1.jpg 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://example.org/blog/, 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 ![](photo-1.jpg).
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: true in the image’s .yaml file
  • @figure("flourish-1.png", decorative=true) in the content, or page.image("flourish-1.png", decorative=true) in a template
  • alt="" 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 .yaml file.
image_sizes
Default (max-width: 46rem) 100vw, 46rem
How wide the page shows images, written as the sizes of an <img>. For example, (max-width: 40rem) 100vw, 40rem suits a column 40rem wide that fills the screen on narrow screens.
optimise_images
Default true
false stops 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.