<!-- Attributes · Docs · clayjs · https://clayjs.com/docs/attributes · generated from the page; every page has one at its path plus .md -->

[Docs](https://clayjs.com/docs) · Attributes

# The HTML surface

The HTML surface: rich text, saved form values, autosave, regions and owner-only behavior.

| Attribute | Where | What it does |
| --- | --- | --- |
| `editable` | any element | Rich text editing with a floating toolbar (richclay, default on). Tokens: `editable="single-line no-toolbar toolbar-on-select"`. Native `contenteditable` also works for plain text. |
| `persist` | form controls | Writes the control's current value into the HTML so it survives the save. `password`, `hidden` and `file` inputs are always skipped, so a secret cannot be written into the file by adding one attribute. |
| `trigger-save` | buttons | Clicking it calls `clay.save()`. Same as wiring onclick yourself. Put it on a `<button type="button">`: on a link the browser follows the href as well, and the navigation can outrun the save. If you want a link, give it an onclick instead: `<a href="#" onclick="event.preventDefault(); clay.save()">`. |
| `autosave` | `<html>` | Save automatically after edits settle. Debounced and throttled. |
| `clay="…"` | any element | Region control: `no-save`, `no-snapshot`, `no-trigger-autosave`, `no-dirty`, `no-watch`, `no-undo`, `no-data`, `editor-ui`, `freeze`. [Full reference](https://clayjs.com/advanced#regions). |
| `merge="name"` | JSON script tags | Multi-writer safety for JSON stored in a script tag (sync plugin). Incoming saves three-way merge the JSON per key against the last synced version instead of replacing the blob, so unsaved local keys survive. Arrays merge by identity (`id`\-style fields; name your own with `merge-key="taskId"`). Bodies may use relaxed JSON: unquoted keys, single quotes, trailing commas, comments. Requires a JSON `type`. |
| `editmode:contenteditable` | any element | Editable for the owner, inert for visitors. |
| `editmode:onclick` | any element | The `onclick` runs only for the owner; it's saved inert so it never runs for visitors. |
| The three `editmode:` rows and the `viewmode:` row are enforced by a _save_ transform, which view mode never loads. So they hold for any file an owner has saved, which is every file in normal use, but not for freshly authored markup a visitor reaches before the first owner save. Save once after adding them. |
| `editmode:resource` | style, link, script | Active for the owner, saved with an inert `type` so visitors never load it. |
| `viewmode:disabled` / `viewmode:readonly` | form controls | Disabled or read-only for visitors, live for the owner. |
| `onbeforesave` / `onbeforesnapshot` / `onaftersave` | any element | Inline hooks into the save. `onbeforesave` and `onbeforesnapshot` run on the clone for _every_ change check, not only for saves that ship, so keep them pure and repeatable: no counters, no logging, no network. [Details](https://clayjs.com/advanced#save-attrs). |
| `savestatus` | `<html>`, set by clayjs | Read-only state for your CSS: `saving`, `saved`, `error`, `offline`. |
