Escaping to Override Components
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
-
callout
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.csson every page:tokens.css(the--htmlpress-*values),layout.css(the page's globals) andcontent.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">andrel="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>.cssand.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:
$ 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.
<!-- .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
$ 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
$ 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.cssand.jscan be escaped. Acomponents/brand/brand.htmlfills one with your own static HTML; its built-in.cssstill applies to the tag, so escape that too to restyle it. -
Pages with a different layout: use
.htmlpress/layouts/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.yamlis fixed.
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: the look of code blocks.
- Custom Routes: pages with a layout of their own, rather than replacing the default one.
Created with ❤ and Htmlpress