Accessibility#
When ssg.a11y is enabled, themed pages get:
- a Skip to content link as the first focusable control in
<body> id="ox-main"on<main>so the skip link has a target- print CSS that hides header, sidebar, search, and reader-chrome extras
The feature is off unless you turn it on. Disabled pages emit no skip link and no extra print CSS.
import { oxContent } from "@ox-content/vite-plugin";
export default {
plugins: [
oxContent({
ssg: {
a11y: true,
},
}),
],
};
false or omitted keeps the extras off. true enables the defaults. An
object enables the feature and can override the skip-link label:
oxContent({
ssg: {
a11y: { skipLinkLabel: "Skip to main" },
},
});
| Field | Default | Effect |
|---|---|---|
skipLinkLabel |
"Skip to content" |
Text of the skip link. Escaped in the HTML. |
The skip link uses class="ox-skip-link" and href="#ox-main". CSS keeps it
visually hidden until it receives keyboard focus, so the first Tab stop is
the skip link.
Print output keeps the article and hides site chrome: the header, sidebar, search modal, and reader-chrome controls such as copy and back-to-top.
Bare mode never emits the skip link or the extra print CSS. Hostile labels cannot break out of the link text.
Embed states#
Almost nothing resolves in the reader's browser. Cards, players, and link previews are all built once and shipped as static HTML, so they have no loading state to show — they arrive resolved. When a build-time fetch fails, the card that ships is already the fallback or the error card; the reader never watches it happen.
The exception is islands. A component tag hydrates in the browser, so it is the one embed with states over time:
| State | Marker | Appearance |
|---|---|---|
| loading | .ox-island-loading |
spinner, after a short delay so a fast hydrate never flashes one |
| resolved | [data-ox-hydrated] |
the component itself |
| error | .ox-island-error |
the static content it was rendered from, marked as not interactive |
All three honour prefers-reduced-motion: reduce.
Reduced motion#
Built-in embed and island styles honour prefers-reduced-motion: reduce.
The loading spinners on Open Graph cards, GitHub cards, and unhydrated
islands stop rotating, the island skeleton stops shimmering, and hover
transitions on tabs and the YouTube placeholder are dropped.
Each indicator keeps its shape, so a card that is still loading still looks like it is loading — only the movement goes away. These styles ship with the embeds themselves and need no configuration.