Article
The reading experience. This is the most important pattern on the site. Every design decision serves one goal: let the reader forget they’re looking at a screen and simply read.
Composition
A standard article page assembles these elements in sequence:
- Breadcrumb —
Alex Priest -> Writingin the site header. Signifier for the nameplate, linking back to the homepage. The breadcrumb provides context without demanding attention. See Navigation. - Article header —
<article><header>containing theh1title (Signifier, 2rem,--text) and a.metadate line (Montreuil, 0.85rem,--text-2,tabular-nums). A--uibottom border separates the header from the body.margin-bottom: var(--space-xl),padding-bottom: var(--space-lg). - Prose container —
<div class="prose">holds all body content. Signifier at 1rem,--text-2,text-wrap: pretty,hanging-punctuation: first last. Child elements are spaced withmargin-top: var(--space-md). See Content components. - Footnotes — On narrow screens, a
.footnotessection renders at the bottom of the prose container. On wide screens (>=1080px), footnotes are lifted into the right margin as.margin-note-footnoteelements and the.footnotessection hides via.footnotes.margin-active. - Footer — The site footer acting as a colophon: navigation groups, copyright, theme toggle, accent picker, font size control. See Navigation.
Variants
Standard article
The default for writing posts. Full editorial treatment.
- Drop cap —
article.post.has-dropcap(added by client-side script when the first paragraph wraps to multiple lines). The first letter floats left at 3.5rem Signifier with weight 450 and a subtle ink-pooling text-shadow.--textcolor, not accent. Disabled on mobile and when the post opens with a blockquote. - Lede paragraph —
article .prose > p:first-of-typerenders at 1.1rem in--text(primary color, not the--text-2used for body prose). This newspaper convention draws the reader in. Resets to inherited styles if the post opens with a blockquote. - Letterpress headings —
h3elements receive a dualtext-shadowcreating the impression of type pressed into paper. Light mode: highlight above, shadow below. Dark mode: deeper shadow, subtler highlight. - Scroll progress bar — A 2px
--accentbar fixed to the top of the viewport, width driven byanimation-timeline: scroll(). Invisible at scroll top, full width at scroll bottom. - Side rail TOC — On wide screens (>=1080px), a table of contents appears in the left margin, positioned absolutely from the prose container and made sticky at
top: 2.5rem. Montreuil, 0.75rem,--text-3links. The active section is tracked via Intersection Observer and highlighted in--textat weight 500. Hidden on narrow screens and in print. - Margin notes — On wide screens, notes appear in the right margin at
0.75remMontreuil in--text-2. Positioned absolutely, translated right of the content column. On mobile, block-level margin notes render as inline callout asides with decorative brackets. Inline and footnote-derived notes are hidden on mobile.
Now page
Class: article.now-page
- No drop cap. First paragraph resets to inherited
font-size,color, andline-height. - No lede styling. The first paragraph is body text, not an editorial opening.
- Updated frequently, more casual in tone. The header includes location and last-updated date rather than a publication date.
- Sections for currently reading, watching, and recent writing are appended below the prose content, each introduced by a
.section-label-link.
Shortlist post
Class: article.shortlist-post
- No drop cap. First letter resets all drop-cap properties (
float: none,font-size: inherit,text-shadow: none). - No lede styling. First paragraph inherits standard prose styles.
- Category pills —
<span class="shortlist-cat">elements positioned in a hanging-indent layout. The paragraph containing a pill receivespadding-left: 5.4em; the pill itself is absolutely positioned to the left atright: calc(100% - 7em). Montreuil, 0.65rem, uppercase, colored from the--pill-1/--pill-2/--pill-3companion triple via client-side script. - Multiple short items rather than a single narrative. Each item is a paragraph with its category pill.
Link post
No special class on the <article> element. Distinguished by frontmatter: an external linkUrl field.
- Title links out — The
h1wraps the title text in an anchor to the external URL. A small arrow glyph (↗) follows the title as a separate link element (.link-arrow, 0.65em,--text-3). The title link uses the same weight-shift hover as post lists:font-variation-settings: 'wght' 400to'wght' 500. - “Must read” marginalia — On wide screens (>=1080px), link posts with
mustRead: truedisplay a.must-read-noteannotation in the right margin. This includes a rough.js hand-drawn arrow SVG (.must-read-arrow, 80x20px) and a handwritten-style label in Caveat cursive (1rem, weight 600,--text-2). Hidden on narrow screens and in print.
Atmospheric context
These ambient layers apply to all article variants. They establish the materiality of the reading surface.
- Scroll progress bar —
--accentcolor, 2px height, fixed to top of viewport. Width animated viaanimation-timeline: scroll()with a@keyframes scroll-fillfrom0%to100%width.z-index: 1000. - Side rail TOC — Left-positioned on screens >=1080px. Sticky at
top: 2.5rem. Montreuil labels,--text-3links that highlight to--textwhen active. Nestedh3links indent atpadding-left: 0.75remand render at 0.7rem. - Margin notes — Right margin on desktop (width 8rem, expanding to 10rem at >=1280px). Inline callouts on mobile with decorative SVG brackets.
- Paper grain, vignette, crop marks — Documented in Atmosphere.
Code example
Full HTML structure of a standard article page (simplified from the Astro template):
<body>
<div class="scroll-progress" aria-hidden="true"></div>
<div class="site-wrapper">
<header class="site-header">
<nav class="breadcrumb" aria-label="Breadcrumb">
<a href="/" class="name" style="view-transition-name: nameplate;">Alex Priest</a>
<span class="separator" aria-hidden="true">-></span>
<a href="/writing" class="current">Writing</a>
</nav>
</header>
<main id="main">
<article class="post has-dropcap">
<header>
<h1>Article title</h1>
<p class="meta">January 15, 2026</p>
</header>
<nav class="toc" aria-label="Table of contents">
<div class="toc-inner">
<span class="toc-label">Contents</span>
<ul class="toc-list">
<li class="toc-item toc-h2">
<a href="#section-one" class="toc-link is-active">Section one</a>
</li>
<li class="toc-item toc-h2">
<a href="#section-two" class="toc-link">Section two</a>
<ul class="toc-sublist">
<li class="toc-item toc-h3">
<a href="#subsection" class="toc-link">Subsection</a>
</li>
</ul>
</li>
</ul>
</div>
</nav>
<div class="prose">
<p>The lede paragraph renders at 1.1rem in primary text color.
The drop cap on the first letter floats left at 3.5rem.</p>
<h2 id="section-one">Section one</h2>
<p>Body prose at 1rem in --text-2.</p>
<aside class="margin-note">
<p>A margin note in the right gutter on desktop,
an inline callout on mobile.</p>
</aside>
<h2 id="section-two">Section two</h2>
<p>More body prose.</p>
<h3 id="subsection">Subsection</h3>
<p>Subsection content with letterpress text-shadow on the h3.</p>
<section class="footnotes">
<ol>
<li id="fn-1"><p>Footnote text. <a href="#fnref-1">Back</a></p></li>
</ol>
</section>
</div>
</article>
</main>
<footer class="site-footer">
<!-- Colophon: nav groups, copyright, settings -->
</footer>
</div>
<aside class="side-rail" aria-label="Navigation">
<!-- Book-spine nav links -->
</aside>
</body>