> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://documentation.celestory.io/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Displaying a background: the three-block chain

# 🖼️ Displaying a background: the three-block chain

A full-screen background is never placed with a single block. It takes three, chained together: one that fetches the image, one that prepares how it should fit the screen, and only one that actually threads into the story's flow. The first two are **value blocks**: they plug into an input, they never sit between two other blocks in the flow. The third is a **flow block**: it, and only it, takes a place in the sequence, right before the line it's meant to dress.

---

## 🧩 The diagram

```
Load image             ──image──▶     Background image        ──background image──▶     Background
(imageFromUrl)                        (createBackgroundImage)                             (switchBackground)
  url: Text                             image: Image                                       in: Stream ◀── threads in here
  image: Image (output)                 size: cover (default)                               background: Background image
                                         color, repeat,                                      duration, in effect,
                                         x position, y position                              out effect,
                                         background image: output                            text, text position
  value block                           value block                                          out: Stream
  no in/out stream points               no in/out stream points                              flow block
```

Only **Background** has "in" and "out" points of type Stream: it's the only one of the three that occupies a slot in the graph's sequence. **Load image** and **Background image** have neither — there's no way to thread them into the flow even if you wanted to; they only have value points to wire up.

---

## 🔗 Block by block

### Load image (`imageFromUrl`)

- Input: **url** (Text) — the direct link to the file (`https://…`).
- Output: **image** (Image).
- No stream point: this block only converts a URL into an "Image" value, usable by any block that accepts an image (Background image, but also Edit character for a portrait).

### Background image (`createBackgroundImage`)

- Input **image** (Image) — receives the previous block's output.
- Input **size** — a choice among *contain*, *auto*, **cover** (the block's default value).
- Inputs **color**, **repeat**, **x position**, **y position** — for cases where the image doesn't fill the whole frame.
- Output: **background image** — a "Background image" object, not a raw image. It's this specific type that the **Background** block expects.
- No stream point either: this block only assembles a setting, it doesn't display anything by itself.

### Background (`switchBackground`)

- Input **in** (Stream) — this is where the block threads in, before the line it should dress.
- Input **background** — receives the **background image** output from the previous block. It's the only point that accepts the full "Background image" type (color, repeat and position included); wiring a plain Image directly into it, skipping Background image, runs into the same problem as the legacy **Stage** block covered in *Legacy blocks*: the expected fields (size, color, repeat) are missing, and the render stays blank or inconsistent.
- Inputs **duration**, **in effect**, **out effect**, **text**, **text position** — the transition animation and an optional text overlay.
- Output **out** (Stream) — the rest of the flow.

---

## 📐 "Cover" doesn't stretch what you'd expect

The **cover** setting on the Background image block doesn't produce a standard `background-size: cover` — the kind that fills the whole frame, cropping whatever overflows. What it produces, checked directly in the player's code, is **`background-size: 100% auto`**:

- the image's **width** is always locked to the frame's width;
- the **height** then follows, proportionally to that width, based on the image's own aspect ratio — with no distortion of the image itself.

So the result depends on your image's proportions relative to the frame:

- an image **wider** than it is tall, in a frame **taller** than it is wide (a phone screen), leaves the background color showing above and below;
- an image **taller** than it is wide, in a wide frame, overflows the frame vertically — the excess is simply clipped, not resized.

So there's no stretching of the image in the strict sense (no distortion), but the frame isn't necessarily covered either. If you need an actual edge-to-edge crop, a **CSS** block setting `background-size: cover !important` on the background remains, as of now, the only way — see *Formatting without writing CSS* to check whether a native module setting already does the job before reaching for that.

---

## 🌐 An image from an external URL: what actually happens

Nothing gets uploaded into the project: the **Load image** block simply wraps the URL you typed into an "Image" value. None of the three blocks in the chain waits, before moving on, for the image to actually finish loading — unlike the **Play music** block, which does block the flow until the sound has started. In practice:

- the flow continues immediately; the image loads in the background like any web page image;
- if the URL is unreachable, malformed, or refused by the remote site (anti-hotlinking protection, CORS), the background simply doesn't appear — the background falls back to the **color** set in Background image, with no error and no blocking;
- **nothing warns you** of this failure during testing: the only way to see it is to open *Test play* and actually look at the background, not just the validator.

So pick stable URLs (Wikimedia Commons, for instance, serves direct URLs designed for external use) rather than a link copied from a site that might one day start blocking requests coming from anywhere but itself.

---

→ Next step: if a background already wired through this chain still stays invisible, re-read *Legacy blocks* — you may have placed **Stage** instead of **Background**.
