# Images

Standard markdown images work out of the box. sitemd adds modifiers for resizing, cropping, filtering, and layout — plus a built-in lightbox for fullscreen viewing. For vector graphics, see [Icons](/docs/icons).

## Basic images

Use standard markdown syntax:

```markdown
![A mountain landscape](https://picsum.photos/id/29/800/400)
```

![A mountain landscape](https://picsum.photos/id/29/800/400)

Images are block-level, responsive (`max-width: 100%`), and lazy-loaded automatically.

## Image modifiers

Add `+modifier` flags to the image URL — same pattern as `+newtab` on links.

### Width

Set a max width in pixels:

```markdown
![Narrow photo](https://picsum.photos/id/10/800/400 +width:400)
```

![Narrow photo](https://picsum.photos/id/10/800/400 +width:400)

### Height

Set a fixed height (image crops to fit):

```markdown
![Fixed height](https://picsum.photos/id/15/800/400 +height:150)
```

![Fixed height](https://picsum.photos/id/15/800/400 +height:150)

### Crop

Crop to exact pixel dimensions:

```markdown
![Cropped](https://picsum.photos/id/20/800/600 +crop:300x200)
```

![Cropped](https://picsum.photos/id/20/800/600 +crop:300x200)

### Circle

Circular crop — great for avatars and profile photos:

```markdown
![Circle](https://picsum.photos/id/64/400/400 +circle +width:200)
```

![Circle](https://picsum.photos/id/64/400/400 +circle +width:200)

### Square

Square crop with 1:1 aspect ratio:

```markdown
![Square](https://picsum.photos/id/42/800/500 +square +width:250)
```

![Square](https://picsum.photos/id/42/800/500 +square +width:250)

### Rectangle

Landscape rectangle with 3:2 aspect ratio:

```markdown
![Rectangle](https://picsum.photos/id/37/800/800 +rect +width:400)
```

![Rectangle](https://picsum.photos/id/37/800/800 +rect +width:400)

### Black & white

```markdown
![Black and white](https://picsum.photos/id/28/800/400 +bw)
```

![Black and white](https://picsum.photos/id/28/800/400 +bw)

### Sepia

```markdown
![Sepia tone](https://picsum.photos/id/28/800/400 +sepia)
```

![Sepia tone](https://picsum.photos/id/28/800/400 +sepia)

### Rotate

Rotate the image 90 degrees clockwise. Use `+rotate:1` for 90°, `+rotate:2` for 180°, or `+rotate:3` for 270°.

```markdown
![Rotated 90°](https://picsum.photos/id/56/400/300 +rotate:1 +width:300)
```

![Rotated 90°](https://picsum.photos/id/56/400/300 +rotate:1 +width:300)

```markdown
![Rotated 180°](https://picsum.photos/id/56/400/300 +rotate:2 +width:300)
```

![Rotated 180°](https://picsum.photos/id/56/400/300 +rotate:2 +width:300)

### Expand (lightbox)

Click the image below to open it fullscreen. Press `Escape` to close.

```markdown
![Expanded example](https://picsum.photos/id/29/1200/800 +expand)
```

![Expanded example](https://picsum.photos/id/29/1200/800 +expand)

### Corner rounding

Control corner rounding per image with `+corner:`. Three named options:

| Value | Effect |
|---|---|
| `+corner:none` | Square corners (0px) |
| `+corner:subtle` | Default rounding (6px) |
| `+corner:curve` | Heavy rounding (16px) |

```markdown
![No corners](https://picsum.photos/id/10/800/400 +corner:none +width:300)
```

![No corners](https://picsum.photos/id/10/800/400 +corner:none +width:300)

```markdown
![Curved corners](https://picsum.photos/id/10/800/400 +corner:curve +width:300)
```

![Curved corners](https://picsum.photos/id/10/800/400 +corner:curve +width:300)

To set the default for all images globally, add `imageCorners` to `settings/theme.md`:

```yaml
# Image corner rounding: none, subtle (default), or curve
imageCorners: subtle
```

Per-image `+corner:` overrides the global setting.

### Combining modifiers

Stack any number of modifiers together. Order doesn't matter.

```markdown
![Circle, B&W, expandable](https://picsum.photos/id/64/600/600 +circle +bw +width:200 +expand)
```

![Circle, B&W, expandable](https://picsum.photos/id/64/600/600 +circle +bw +width:200 +expand)

```markdown
![Sepia crop](https://picsum.photos/id/43/800/600 +crop:500x250 +sepia)
```

![Sepia crop](https://picsum.photos/id/43/800/600 +crop:500x250 +sepia)

```markdown
![Square, rotated, B&W](https://picsum.photos/id/76/600/600 +square +width:200 +rotate:2 +bw)
```

![Square, rotated, B&W](https://picsum.photos/id/76/600/600 +square +width:200 +rotate:2 +bw)

## Image row

Display multiple images in a row at equal height. Images stretch to fill the row regardless of their original aspect ratios.

```markdown
image-row:
  ![Mountains](https://picsum.photos/id/29/800/600)
  ![Lake](https://picsum.photos/id/16/800/400)
  ![Forest](https://picsum.photos/id/15/800/500)
```

image-row:
  ![Mountains](https://picsum.photos/id/29/800/600)
  ![Lake](https://picsum.photos/id/16/800/400)
  ![Forest](https://picsum.photos/id/15/800/500)

On mobile, images wrap to two per row.

### Image row with modifiers

Modifiers work on individual images within a row. Add `+expand` to enable lightbox — left/right arrows navigate between the expanded images in the same row.

```markdown
image-row:
  ![Color](https://picsum.photos/id/28/800/500 +expand)
  ![B&W](https://picsum.photos/id/28/800/500 +bw +expand)
  ![Sepia](https://picsum.photos/id/28/800/500 +sepia +expand)
```

image-row:
  ![Color](https://picsum.photos/id/28/800/500 +expand)
  ![B&W](https://picsum.photos/id/28/800/500 +bw +expand)
  ![Sepia](https://picsum.photos/id/28/800/500 +sepia +expand)

## Gallery

Display images in a responsive grid. All gallery images automatically open in a lightbox when clicked — navigate with left/right arrow keys or the on-screen arrows.

```markdown
gallery:
  ![Mountains](https://picsum.photos/id/29/800/600)
  ![Ocean](https://picsum.photos/id/14/800/600)
  ![Forest](https://picsum.photos/id/15/800/600)
  ![Lake](https://picsum.photos/id/16/800/600)
  ![Desert](https://picsum.photos/id/17/800/600)
  ![Waterfall](https://picsum.photos/id/18/800/600)
```

gallery:
  ![Mountains](https://picsum.photos/id/29/800/600)
  ![Ocean](https://picsum.photos/id/14/800/600)
  ![Forest](https://picsum.photos/id/15/800/600)
  ![Lake](https://picsum.photos/id/16/800/600)
  ![Desert](https://picsum.photos/id/17/800/600)
  ![Waterfall](https://picsum.photos/id/18/800/600)

### Gallery with modifiers

Image modifiers work inside galleries:

```markdown
gallery:
  ![Original](https://picsum.photos/id/37/800/600)
  ![Black & white](https://picsum.photos/id/37/800/600 +bw)
  ![Sepia](https://picsum.photos/id/37/800/600 +sepia)
```

gallery:
  ![Original](https://picsum.photos/id/37/800/600)
  ![Black & white](https://picsum.photos/id/37/800/600 +bw)
  ![Sepia](https://picsum.photos/id/37/800/600 +sepia)

### Gallery with custom corners

Override corner rounding for an entire gallery:

```markdown
gallery +corner:curve:
  ![One](https://picsum.photos/id/10/800/600)
  ![Two](https://picsum.photos/id/11/800/600)
  ![Three](https://picsum.photos/id/12/800/600)
```

gallery +corner:curve:
  ![One](https://picsum.photos/id/10/800/600)
  ![Two](https://picsum.photos/id/11/800/600)
  ![Three](https://picsum.photos/id/12/800/600)

```markdown
gallery +corner:none:
  ![One](https://picsum.photos/id/42/800/600)
  ![Two](https://picsum.photos/id/43/800/600)
  ![Three](https://picsum.photos/id/44/800/600)
```

gallery +corner:none:
  ![One](https://picsum.photos/id/42/800/600)
  ![Two](https://picsum.photos/id/43/800/600)
  ![Three](https://picsum.photos/id/44/800/600)

### Static gallery (no lightbox)

Use `+noexpand` to disable the lightbox. Images display as a static grid. Flags can be combined.

```markdown
gallery +noexpand:
  ![One](https://picsum.photos/id/10/800/600)
  ![Two](https://picsum.photos/id/11/800/600)
  ![Three](https://picsum.photos/id/12/800/600)
```

gallery +noexpand:
  ![One](https://picsum.photos/id/10/800/600)
  ![Two](https://picsum.photos/id/11/800/600)
  ![Three](https://picsum.photos/id/12/800/600)

## Local vs URL images

All modifiers work on both local images and external URLs:

```markdown
![Local](media/content/photo.jpg +circle +bw)
![External](https://picsum.photos/id/64/400/400 +circle +bw)
```

Place local images in the `media/content/` directory. They're copied to the output during build and served at `/media/content/filename.ext`.

## Modifier reference

| Modifier | Effect |
|---|---|
| `+width:N` | Max width in pixels |
| `+height:N` | Fixed height (crops with cover) |
| `+crop:WxH` | Crop to exact dimensions |
| `+circle` | Circular crop |
| `+square` | Square crop (1:1) |
| `+rect` | Landscape rectangle (3:2) |
| `+bw` | Black and white filter |
| `+sepia` | Sepia tone filter |
| `+rotate:N` | Rotate 90° clockwise N times (1–3) |
| `+corner:name` | Corner rounding: `none`, `subtle`, `curve` |
| `+expand` | Click to open fullscreen lightbox |

## Notes

- Image syntax inside fenced code blocks is displayed as text, not rendered.
- Modifiers are order-independent — `+bw +circle` and `+circle +bw` produce the same result.
- Modifiers work on [card images](/docs/cards#image-modifiers-on-cards) too — append them to the `card-image:` URL.
- The lightbox supports keyboard navigation: `Escape` to close, `Left`/`Right` arrows to navigate within a group.
- Gallery images are displayed at 4:3 aspect ratio with `cover` fit.
- Image rows equalize height across all images in the row automatically.
- Set `imageCorners` in `settings/theme.md` to change the global default for all images, image rows, and galleries.
- Use [alignment fences](/docs/content-alignment) (`center:` / `/center`, `right:` / `/right`) to center or right-align images, image rows, and galleries.


## Image optimization

Enable build-time image optimization in `settings/build.md`:

```yaml
# settings/build.md
imageOptimization: optimize
imageMaxWidth: 1920
imageQuality: 80
```

| Setting | Default | What it does |
|---|---|---|
| **imageOptimization** | `false` | `false` disables optimization. `optimize` enables resizing, compression, and WebP generation. |
| **imageMaxWidth** | `1920` | Images wider than this are resized down. Height scales proportionally. |
| **imageQuality** | `80` | Compression quality for JPEG and PNG output. Lower values reduce file size. |

**What happens at build time:**

Optimization runs after the main build, in the same async post-build step as OG image generation. For every image in `site/media/`:

1. If wider than `imageMaxWidth`, the image is resized down
2. The original is recompressed at `imageQuality`
3. A `.webp` variant is generated alongside the original (`photo.jpg` → `photo.webp`)
4. All `<img src="/media/...">` tags in the HTML output are wrapped in `<picture>` elements:

```html
<picture>
  <source srcset="/media/content/photo.webp" type="image/webp">
  <img src="/media/content/photo.jpg" alt="...">
</picture>
```

Browsers that support WebP receive the smaller file automatically. Browsers that don't fall back to the original.

**Source images are never modified.** Optimization operates on the copies in `site/media/` (the build output), leaving your `media/` source files intact.

Results are cached by content hash in `site/media/.image-cache.json`. Unchanged images are skipped on subsequent builds — only new or modified images are reprocessed.

Requires Sharp. If Sharp is not installed, optimization is skipped silently. Use [Media Hosting](/docs/media-hosting) to serve optimized images from a CDN.