# Escaping to Override Components

> Replace the built-in layout, styles, scripts and components, or add your own, from .htmlpress/.

Htmlpress ships a layout, a theme, three scripts and a library of components, all compiled into the binary. Every built-in file can be replaced: drop a file at the same path under `.htmlpress/` and the build uses it instead.

| To override                 | Drop a file at                                     |
| --------------------------- | -------------------------------------------------- |
| the page around the content | `.htmlpress/layout.html`                           |
| the global theme            | `.htmlpress/styles/<name>.css`                     |
| a global script             | `.htmlpress/scripts/<name>.js`                     |
| one component               | `.htmlpress/components/<name>/<name>.css` or `.js` |

- .htmlpress

  - layout.html

  - layouts
    - landing.html

  - styles

    - tokens.css
    - layout.css
    - content.css

  - scripts
    - code.js

  - components

    - callout
      - callout.css

    - tabs

      - tabs.css
      - tabs.js

    - credits
      - credits.html

* `layout.html`

  The page around the content, plain HTML with the layout elements htmlpress fills, such as `<htmlpress-content>` and `<htmlpress-nav>`.

* `styles/*.css`

  The global theme, joined into one `theme.css` on every page: `tokens.css` (the `--htmlpress-*` values), `layout.css` (the page's globals) and `content.css` (headings, prose, tables, code).

* `scripts/code.js`

  The copy button on code blocks and the link on each heading.

* `scripts/hints.js`

  The hover hint on abbreviations and footnote references.

* `scripts/keys.js`

  The `J`, `K` and `D` keys, which scroll the page down, up and to its bottom, and `H` and `L`, which follow the `<link rel="prev">` and `rel="next"` htmlpress writes into the head: one reading order from the home page through every section, so they go on where the pager stops.

* `components/<name>/<name>.css` and `.js`

  One component each, the elements of the layout's frame included, in a folder named for its tag without the `htmlpress-` prefix. Its styles sit in `@scope (<tag>)`, so they never reach outside it, and its script defines only that element. A page links only the components it uses.

No other change is needed: the rest of htmlpress picks up the escaped file automatically.

## The `htmlpress escape` command

`htmlpress escape` copies a default into `.htmlpress/` to start from. Name a file by its path, or a component by its tag for all of its files:

```sh
$ htmlpress escape                       # list every file, marking the escaped ones
$ htmlpress escape htmlpress-tabs        # its .css and .js
$ htmlpress escape layout.html styles/tokens.css
$ htmlpress escape htmlpress-tabs -r docs  # in another project folder
```

`htmlpress escape` never overwrites a file you already have: delete it first to start over. An escaped copy keeps the code it was copied from, so after an upgrade it misses the new defaults.

Deleting an escape restores the default: at once while `htmlpress start` runs, otherwise on the next `start` or `build`.

## Example: credits

A folder under `components/` with a new name adds a component of your own, `<htmlpress-<name>>`, each file named like the folder. Its `.html` fills every such tag in the layout and the pages at build time; its `.css` and `.js` load wherever the tag appears.

```html
<!-- .htmlpress/components/credits/credits.html -->
<footer><p>Built by my team · 2026</p></footer>

/* .htmlpress/components/credits/credits.css */
@scope (htmlpress-credits) {
  :scope { display: block; }
  p { color: var(--htmlpress-muted); }
}
```

Then put `<htmlpress-credits></htmlpress-credits>` in an escaped `layout.html` or any page. Save: the dev server picks it up immediately. A name is lowercase letters, digits and hyphens.

## Example: retheme buttons

```sh
$ htmlpress escape components/button/button.css
```

Edit `.htmlpress/components/button/button.css` to change button styling everywhere: every page that uses `<htmlpress-button>` links your copy instead of the built-in one.

## Example: tweak a token

```sh
$ htmlpress escape styles/tokens.css
```

Edit the `:root` block in `.htmlpress/styles/tokens.css` to rebrand:

```
:root {
  --htmlpress-accent: oklch(0.55 0.24 27); /* red */
}
```

For a single page, override the token from that page's own `<style>` instead; no escape needed.

## Using other components from an override

An escaped `layout.html`, a layout of your own and a component's `.html` may hold any `htmlpress-*` component, which renders and links its styles as it would in a page. A component's `.html` may not hold another project component's tag: it is pasted in once, never rewritten again.

### Scoping a component's styles

A component's tag stays around the markup its `.html` fills it with, keeping its attributes, so its `.css` scopes to the tag, `@scope (htmlpress-credits)`, with or without an `.html`. A custom element is inline until its CSS says otherwise. To restyle a component from another one, beat its `:scope`: `:scope htmlpress-header`, not a bare `htmlpress-header`.

## Page transitions

Moving between pages crossfades the content only: `<htmlpress-header>` and `<htmlpress-sidebar>` carry the view transition names `htmlpress-header` and `htmlpress-sidebar` and switch to the new page at once. Hovering a link prerenders its page, so it is ready by the click. The header's buttons are built into each page; a head script sets `data-scripted` on `<html>`, and without it they stay hidden, so style anything that only works with scripts under `:root[data-scripted]`.

## What you can't override this way

- **Layout element markup**: the markup inside `<htmlpress-nav>`, `<htmlpress-page-toc>`, `<htmlpress-pager>` and the other layout elements is built from the site, so only their `.css` and `.js` can be escaped. A `components/brand/brand.html` fills one with your own static HTML; its built-in `.css` still applies to the tag, so escape that too to restyle it.
- **Pages with a different layout**: use [`.htmlpress/layouts/`](/customization/custom-routes/) instead.
- **The binary**: reading pages, the navigation and the commands are not overridable; fork the repo if you need to change these.
- **Config schema**: the shape of `htmlpress.yaml` is fixed.

> **Warning**
>
> A folder under `components/` with a name htmlpress does not ship, such as `calout/`, adds a new component rather than replacing one. A file directly in `components/` fails the build, and so does any file under `styles/` or `scripts/` that replaces nothing.

## See also

- [Syntax Themes](/customization/syntax-themes/): the look of code blocks.
- [Custom Routes](/customization/custom-routes/): pages with a layout of their own, rather than replacing the default one.
