Ovellum v0.12.0
English

Edited

Styleguide#

This page is both the reference and the proof — every element below is real Markdown rendered by Ovellum's default template, so what you see is exactly what your own pages get. It documents the type scale, the vertical rhythm, the color system, and each content element you can write.

Try the appearance control in the top bar while you read: switch mode (auto / light / dark), pick a theme, set a color, bump the text size, or change the font (Default / Serif / Inter / Geist). Everything on this page re-tints and re-flows live, because it's all driven by the same design tokens.

Typography#

Text and headings use the system sans-serif stack by default — instant first paint, no webfont hop. Readers can switch to Serif, Inter, or Geist from the appearance control's Font picker (Inter and Geist ship with the template and load only when chosen), and step the Text size up or down. The typeface and size are the reader's choice; the scale, rhythm, and color below are Ovellum's shipped defaults and apply to any template.

Body text runs at a 1.55 line-height inside a 76ch measure — the reading column is capped at roughly 76 characters per line, the band where long prose stays comfortable. Headings tighten to a 1.2 line-height with a small negative letter-spacing so they read as one unit rather than spaced words.

Type scale#

Sizes come from a modular scale: one base size, multiplied by a fixed ratio at each step. Ovellum uses a major third (1.25) on a fluid base that grows from ~15px on small screens to 16px on wide ones (a single clamp() — no breakpoints). Each heading maps to a step, so the hierarchy is mathematical, not hand-picked:

StepRatio from baseUsed by
--font-size-41.25⁴ (≈ 2.44×)h1
--font-size-31.25³ (≈ 1.95×)h2
--font-size-21.25² (≈ 1.56×)h3
--font-size-11.25¹ (1.25×)h4, lead
--font-size-01× (base)body, p, li

Because every step is calc(previous × var(--ratio)), changing the one --ratio token reflows the entire hierarchy in proportion.

Headings#

The six levels, rendered at their real sizes:

Heading level 1#

Heading level 2#

Heading level 3#

Heading level 4#

Heading level 5#
Heading level 6#

Each heading gets a stable id and a hover anchor (#) so any section is directly linkable, and h2/h3 are collected into the "On this page" list to the right.

Vertical rhythm#

Spacing isn't ad hoc — it's a fluid space scale (--space-3xs through --space-3xl), each step a clamp() that grows gently with the viewport. Block elements share one rule: no top margin, a consistent gap below, so rhythm accumulates predictably down the page. Headings add a larger lead-in above (an h2 opens a new section with generous space before it, tight space after), which is what makes a heading feel attached to the text it introduces.

Paragraphs and inline text#

A paragraph sets the baseline. This sentence shows bold for emphasis, italic for stress, and inline code for identifiers — code gets a faint tint and a monospace face so a symbol like OvellumUserConfig never gets mistaken for prose. Links such as the configuration reference carry an accent color and a thin underline offset from the baseline; they change tint on hover. You can also strike text with strikethrough for retractions.

A blockquote sits slightly inset with a single rule on the leading edge and muted text — quiet, not boxed. Use it for an aside or a pulled quote, not for emphasis (that's what bold is for).

Callouts#

GitHub-style alert blockquotes become tinted callout panels:

Note

Useful context that complements the surrounding prose.

Tip

A shortcut or a better way to do the thing.

Important

Something the reader genuinely shouldn't miss.

Warning

A sharp edge — proceed deliberately.

Caution

A risk of data loss or a hard-to-reverse action.

Lists#

Unordered lists use a quiet marker in a subdued color, and nest with reduced spacing so depth reads as hierarchy:

  • A first item, kept to a line or two.
  • A second item, with nested detail:
    • A nested point.
    • Another, to show the indent step.
      • One level deeper still.
  • A final item.

Ordered lists carry the same rhythm:

  1. Author the page in Markdown.
  2. Run ovellum build.
  3. Deploy the dist/ output anywhere static.

Task lists render their checkboxes:

  • Typography scale
  • Color system
  • Your next page

Footnotes#

A footnote reference sits as a small superscript1 that links down to the note, and the note links back. References number by order of appearance, and the notes gather into a tinted panel — one type-step smaller than body text — at the foot of the page.2

Code#

Inline code reads as const x = 1. Fenced blocks are highlighted by Shiki using a dual light/dark theme emitted through CSS variables — so the colors flip with the appearance mode at zero runtime cost — with a language eyebrow and a copy button:

import { defineConfig } from 'ovellum';

export default defineConfig({
  mode: 'manual',
  input: 'content',
  output: 'dist',
  site: {
    title: 'My Docs',
    palette: 'default',
  },
});
ovellum build

Tables#

Tables are editorial-calm — horizontal rules only, no grid lines, no header fill. The header reads through weight and a thicker bottom rule; a table wider than the column scrolls horizontally rather than blowing out the layout:

ElementTokenNote
Body text--font-size-0Fluid 15→16px base
Measure--content-max76ch reading column
Body rhythm--leading-normal1.55 line-height
Headings--leading-tight1.2 line-height, negative tracking

Images#

Images scale to the column width, keep their aspect ratio, and pick up the same corner radius as other media:

A sample photograph

This one sits next to the page's Markdown file (styleguide-sample.jpg) and is referenced with a root-absolute path — the pattern the Assets & downloads guide recommends for page-specific images.

Video#

Paste the embed code straight from YouTube or Vimeo — "Share → Embed", copied verbatim — and it just works. Ovellum allows <iframe> only from those known video hosts, hardens it, and wraps it in a responsive 16:9 frame:

For the YouTube video embed above, here is the code — the exact snippet YouTube hands you under Share → Embed, dropped straight into the Markdown:

<iframe
  width="560"
  height="315"
  src="https://www.youtube.com/embed/1Jpjw2w_0l8"
  title="YouTube video player"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
  referrerpolicy="strict-origin-when-cross-origin"
  allowfullscreen
></iframe>

Nothing else to do — the fixed width/height and frameborder come along harmlessly. Ovellum's responsive wrapper overrides the pixel dimensions, and loading="lazy" plus a strict referrer policy are applied automatically. (Swap in https://www.youtube-nocookie.com/embed/… for YouTube's privacy-preserving host.) For self-hosted clips, the native <video> / <audio> players work too. Both are covered in Assets & downloads.

Horizontal rule#

A thematic break sets a quiet divider between passages:


That rule, like everything above, is the default template doing its job — no custom CSS on this page.

Color system#

Five palettes ship, each authored in OKLCH (perceptually uniform, so a ramp steps in even visual increments rather than the uneven jumps sRGB hex gives):

  • Ovellum — neutral grays, the default.
  • Nord — cool, frosty blue-grays.
  • Flexoki — warm, inky paper.
  • Solarized — Ethan Schoonover's measured base tones.
  • E-ink — high-contrast warm paper and ink, monochrome.

Each palette is one gray ramp plus an accent; dark mode reuses the same ramp with reversed indices, so there's no second set of values to maintain. The appearance control's Color picker overrides just the accent, live. All of it flows through semantic tokens (surface, border, foreground, link), which is why a single switch re-tints the entire page — this one included.

Footnotes

  1. The note itself takes inline Markdown — code, emphasis, even a link.

  2. A second note, to show the list numbering and the panel rhythm.

Edit this page