Jedes Bild in einer Markdown-Seite.

::callout{type="tip" title="Gerendert ansehen"}
Jedes Beispiel unten ist ein Codeblock. [Die Bild-Fixtures](~/demo/images) sind
dasselbe Markup, tatsächlich gezeichnet — ein dunkler Zwilling, ein Original
schmaler als die Spalte, eine Vektorgrafik, eine Animation und ein Bild, das
sich nicht zoomen lässt.
::

## Was sie hinzufügt

**Zwei Varianten.** Ein Screenshot eines dunklen Editors auf einer weißen Seite —
oder umgekehrt — ist das häufigste hässliche Ding in einer Dokumentation, und CSS
kann es nicht beheben, weil die Pixel falsch sind, nicht der Rahmen. Eine Seite
darf eine zweite Datei benennen:

```md
![Die Seitenleiste](/shots/sidebar.png){dark="/shots/sidebar-dark.png"}
```

**Zwei Anfragen, nicht eine Datei.** Das Bild in der Seite und das Bild im
Zoom-Dialog fragen unterschiedliche Breiten an, sodass ein Telefon das
2400-px-Original nicht mehr herunterlädt, um es in eine 48rem-Spalte zu zeichnen.
Beides sind `srcset`s, die `@nuxt/image` erzeugt — keine Datei, die jemand
vorbereiten müsste.

**Klick zum Zoomen**, sofern das Bild nicht darum bittet, es zu lassen:

```md
![Ein Diagramm](/diagram.svg){zoom="false"}
```

Ein zoombares Bild trägt einen kleinen Zoom-Hinweis in seiner Ecke, dauerhaft
statt beim Hover — ein Cursor ist auf einem Touch-Gerät nichts und in einem
Screenshot der Seite unsichtbar. Das Bild ist eine Schaltfläche: `Tab` erreicht
sie mit sichtbarem Ring, `Enter` und `Leertaste` öffnen den Dialog, `Escape`
schließt ihn und gibt den Fokus zurück. Mit `zoom="false"` gibt es keinen
Hinweis, keinen Ring und nichts, wohin getabbt werden könnte.

**Ein Hintergrund für ein transparentes Bild.** Ein Diagramm, dessen Linien für
eine helle Fläche gezeichnet sind, verschwindet auf einer dunklen Seite. Nenne
eine Farbe pro Theme — jede CSS-Farbe, auch `var(--card)`:

```md
![Ein Diagramm](/diagram.svg){background="#fafafa" dark-background="#171717"}
```

Farben statt Klassen, mit Absicht: Das Stylesheet des Layers wird aus seinen
eigenen Komponenten gebaut, nie aus Markdown — eine `dark:bg-…`-Klasse in einer
Seite hätte also kein CSS dahinter.

Die Ansicht nimmt den ganzen Bildschirm über einer weichgezeichneten Seite ein.
Ihre Bedienelemente — verkleinern, die Zoomstufe (die ihn zurücksetzt),
vergrößern, Original in neuem Tab öffnen, schließen — schweben in einer Zeile
über dem Bild, der Alt-Text steht darunter, sodass keins von beiden das Bild
verdeckt. Das Mausrad zoomt um den Cursor, eine Pinch-Geste um die Finger; ein
Klick aufs Bild zoomt an dieser Stelle auf 200 %, ein zweiter zurück; `+`, `-`
und `0` tun dasselbe über die Tastatur. Ein gezoomtes Bild wird zum Verschieben
gezogen und lädt die Originaldatei, damit es scharf bleibt. Ein Klick daneben
schließt die Ansicht.

## API

### Props

| Prop     | Typ       | Standard | Anmerkungen                                              |
| :------- | :-------- | :------- | :------------------------------------------------------- |
| `src`    | `string`  | —        | Wie geschrieben                                           |
| `alt`    | `string`  | —        | Wie geschrieben                                           |
| `dark`   | `string`  | —        | Eine zweite Datei, unter dem dunklen Theme ausgeliefert   |
| `zoom`   | `boolean` | `true`   | `false` lässt das Bild inert                              |
| `width`  | `number`  | —        | Optional; siehe **Maße** unten                            |
| `height` | `number`  | —        | Optional; siehe **Maße** unten                            |
| `sizes`  | `string`  | —        | Überschreibt die Richtlinie in der Seite; siehe **Größen** |
| `background`      | `string` | — | Eine CSS-Farbe hinter einem transparenten Bild, in der Seite und in der Ansicht |
| `dark-background` | `string` | — | Dasselbe unter dem dunklen Theme; fällt auf `background` zurück               |

## Größen

Das Theme weiß eine Sache, die `@nuxt/image` nicht wissen kann: wie breit der
Kasten ist, in den es ein Bild zeichnet. Mehr konfiguriert es nicht.

- **In der Seite** — `sm:95vw md:768px`. Unterhalb von `md` ist der Artikel der
  Viewport abzüglich seiner Ränder; ab `md` ist er auf `max-w-3xl` gedeckelt,
  unabhängig vom Bildschirm — die angefragte Breite hört also auf zu wachsen,
  statt auf einem 4K-Display weiterzuklettern.
- **Im Dialog** — `sm:96vw md:96vw lg:96vw xl:1264px`, dem Viewport folgend bis
  zur eigenen Deckelung des Dialogs bei `min(96vw, 80rem)`.

Beide benennen nur die Breakpoints, die `@nuxt/image` ohnehin mitbringt — ein
Konsument, der `image.screens` neu definiert, behält seine Definition. Die Ebene
deklariert keine eigenen `screens`.

Ein Bild, das **nicht** so breit ist wie die Textspalte — ein Logo, ein Badge,
ein Diagramm am Rand — sagt das:

```md
![Das Badge](/badge.png){sizes="sm:50vw md:200px"}
```

`sizes` ist die eigene Syntax von `@nuxt/image` und erreicht nur das Bild in der
Seite. Der Dialog behält seine Richtlinie: eine, die die Textspalte beschreibt,
kann keinen Dialog beschreiben.

## Maße

`width` und `height` sind optional und bleiben es — die meisten Seiten lassen
sie weg, und sie zu verlangen würde jede bereits geschriebene Seite brechen.

**Gib sie trotzdem an, wo du kannst.** Sie sind es, die den Browser den Kasten
reservieren lassen, bevor die Datei eintrifft; ohne sie hat das Bild bis zum
Laden kein Seitenverhältnis, und der Text darunter springt, sobald es da ist.
Die Komponente bewahrt das Verhältnis des Paares, das sie bekommt, und erfindet
nichts, wenn sie keines bekommt: es gibt kein Standard-Seitenverhältnis und
keinen Zuschnitt, denn ein falsches Verhältnis ist schlimmer als ein Sprung.

Ein Bild, das schmaler ist als die Spalte, bleibt in seiner eigenen Größe,
statt gedehnt zu werden.

## Formate

**SVG und animiertes GIF werden unverändert durchgereicht**, in der Seite wie im
Dialog, ganz ohne `srcset`. Ein Vektor hat keine Pixel zum Neuberechnen — einen
608 px breiten anzufragen rastert eine Datei, die in jeder Größe scharf war —
und ein GIF durch eine Rasterpipeline kommt als sein erstes Einzelbild zurück.

Das ist, was die Komponente tut, keine Aussage über Provider: manche reichen
diese Formate durch, manche nicht, und eine Dokumentations-Ebene kann nicht
wissen, welchen ein Konsument konfiguriert hat. Responsive Quellen gelten den
Rasterformaten, für die der Zoom existiert — PNG, JPEG, WebP, AVIF.

## Provider

**Die Ebene setzt keinen `image`-Schlüssel.** Welcher Dienst ein Bild
transformiert, gehört dem Konsumenten, so wie `sources`: ein von der Ebene
gewählter Provider ist ein Provider, den jeder Konsument wieder rückgängig
machen muss, und er entscheidet über ein Konto und eine Rechnung ebenso wie über
eine URL. Konfiguriere
[`@nuxt/image`](https://image.nuxt.com/get-started/configuration) wie in jeder
Nuxt-App; die Komponente übergibt ihm nur zwei `sizes`-Zeichenketten.

Sich selbst überlassen, wählt `@nuxt/image` selbst, und die drei Fälle, denen
eine Dokumentationsseite begegnet, sind:

- **Ein Node-Server.** `ipx` transformiert auf Anfrage unter `/_ipx/…`. Es
  braucht `sharp`, eine native Bindung, die die Node-Ausgabe ohnehin mitführt.
- **Eine generierte Seite** (`nuxt generate`). `ipxStatic` schreibt jede Variante
  zur Bauzeit. Danach läuft nichts mehr, und die Ausgabe wächst um die Varianten
  — der Handel, den eine vollständig statische Seite ohnehin eingeht.
- **Eine Edge-Laufzeit** — Cloudflare Workers und alles andere, das weder Node
  noch statisch ist. Kein Transformer läuft, und Bilder werden so ausgeliefert,
  wie sie eingecheckt wurden. **Eine prerenderte Seite auf einer solchen Laufzeit
  darf nicht auf `ipx` konfiguriert werden**: es ist eine native Bindung und kann
  dort überhaupt nicht laufen. Greif zu einem CDN-Provider, wenn die
  Transformationen gewünscht sind.

Die Varianten des Dialogs entstehen auch bei einem statischen Build, obwohl der
Dialog beim Rendern der Seite geschlossen ist — die Komponente meldet sie selbst
beim Prerender-Crawler an. Heruntergeladen wird nichts, bis der Dialog aufgeht.

Ein Bild mit `zoom="false"` bekommt keine davon. Es gibt keinen Dialog, der
aufgehen könnte, also wäre jede dialoggroße Datei dafür Output, den niemand je
anfordern kann.

## Anmerkungen

Die dunkle Variante wird ausdrücklich benannt, statt per Konvention geraten.
`-dark` aus einem Dateinamen abzuleiten heißt, dass eine fehlende Datei zu einem
kaputten Bild wird — und der Autor erfährt es nie.

Ein Bild aus einer Quelle, die aus einem anderen Repository geklont wurde, hat
keine eigene Route: Content lädt den Baum nach `.data/content/`, und nichts
kopiert seine Assets nach `public/`. Die Pfade in diesen Beispielen sind absolut
in das eigene `public/` der konsumierenden Seite — dort muss ein
Dokumentationsbild heute liegen.