Marginalia

Typographic callout library. 15 components, CSS custom properties, zero dependencies.

GitHub

Showcase

Vision begins at the retina, where 130 million photoreceptors compress into 1.2 million ganglion cell axons — a 100:1 reduction before information reaches the brain. This isn't a bottleneck. It's an editorial decision, made in parallel across the visual field, about what matters enough to transmit.

Note: Ganglion cell density peaks at ~35,000 cells/mm² in the fovea and drops to ~5,000 cells/mm² at 10° eccentricity. The mg-dropcap above mirrors this hierarchy — the initial letter demands foveal attention.

Center-surround receptive fields perform edge detection and contrast normalization before any cortical processing occurs. Midget cells in the fovea carry high-acuity color-opponent signals. Parasol cells across the periphery prioritize motion and luminance transients. Two parallel channels, tuned to different statistics, feeding V1 LGN SC simultaneously.

// Retinal ganglion cell density falloff (Watson 2014)
float ganglionDensity(float eccentricity) {
    float fovealPeak = 35000.0; // cells/mm²
    float e2 = 1.72;           // half-density eccentricity
    return fovealPeak / pow(1.0 + eccentricity / e2, 2.0);
}
Why this matters for rendering

Foveated rendering exploits this density falloff. If you match your shader's spatial frequency budget to the retina's sampling capacity at each eccentricity, you can reduce fragment processing by 60-70% with no perceptible quality loss. The ganglionDensity() function above is the biological ground truth that rendering LOD curves approximate.

1. Callouts

Note: The cortical magnification function falls off roughly as 1 / (1 + e/e2) where e2 varies by visual field meridian.

Tip: Use shape-outside with pull quotes to create text that wraps along the perspective tilt, not just a rectangular float.

Warning: MIP level selection at extreme eccentricities can produce visible banding. Clamp to maxLod - 1 for smoother falloff.

Important: The 3D perspective transform uses transform: perspective(600px) rotateY(14deg). This is removed on viewports below 720px for readability.

Without vertical bar

Note: Add data-bar="none" to any callout, pull quote, or code block to remove the left border accent. The tinted background still provides visual separation.

Warning: Without the border, the background tint carries the semantic color. Works best with typed variants that have distinct tints.

2. Pull Quotes

Hardware texture MIP chains and biological retinal processing share a structural parallel that runs deeper than analogy. Both systems face the same computational problem: reducing high-resolution spatial information into progressively coarser representations while preserving the features that matter for downstream processing.

The GPU MIP chain builds power-of-two reductions through box filtering. The retina builds a spatial frequency cascade through center-surround receptive fields whose sizes increase with eccentricity from the fovea. Different mechanisms, same computational strategy, same mathematical structure — a Laplacian pyramid.

This convergence isn't mysterious. Progressive spatial pooling is simply an efficient solution to the problem of representing visual information at multiple scales. Evolution and engineering arrived at the same answer independently, which is exactly what you'd expect for a well-constrained optimization problem.

Flat (no 3D transform)

The mg-flat modifier removes the perspective tilt while keeping the sidebar float behavior. This works for content where the 3D effect would feel excessive — technical asides, definition boxes, or supplementary notes that sit alongside body text without demanding attention through visual skew.

Flat pull quotes still float right by default and can be combined with mg-flip to float left. The left border accent remains as the visual anchor.

Flipped (left float)

The oculomotor system makes roughly three saccadic eye movements per second during active viewing. Each saccade commits the visual system to a new fixation point for 200-300 milliseconds. The choice of where to look next is informed by peripheral vision — specifically, the low-spatial-frequency information available in the parafoveal and peripheral visual field during the current fixation.

Saliency models attempt to predict these fixation sequences from image statistics. The best-performing models combine bottom-up feature contrast (color, orientation, spatial frequency) with top-down task demands and scene grammar — the learned statistical regularities of where objects tend to appear in natural scenes.

3. Code Blocks

// Lorenz attractor step — the heart of Psychodeli+'s fractal engine
vec3 lorenzStep(vec3 p, float sigma, float rho, float beta, float dt) {
    return p + vec3(
        sigma * (p.y - p.x),
        p.x * (rho - p.z) - p.y,
        p.x * p.y - beta * p.z
    ) * dt;
}
// Cortical magnification — FOVI model (Blauch, Alvarez & Konkle 2026)
function corticalMagnification(eccentricity, e2 = 0.75) {
  return 1 / (1 + eccentricity / e2);
}

Inline code: The shape-outside property creates a polygon that text wraps around, matching the visual tilt of the perspective() transform.

4. Badges

Default Tip Warning Important

Badges work inline: this feature is New and requires WebGL 2 GPU support.

5. Collapsible Sections

Mathematical derivation: Cortical magnification function

The cortical magnification factor M describes how many millimeters of cortical surface represent one degree of visual angle at eccentricity e:

M(e) = M0 / (1 + e/e2)

Where M0 is the foveal magnification (~15-20 mm/deg for V1) and e2 is the eccentricity at which M drops to half its foveal value (~0.75 deg for V1, varying by meridian). This hyperbolic falloff means roughly half of V1 is devoted to the central 2-3 degrees of the visual field.

Implementation note: shape-outside polygon coordinates

The shape-outside: polygon(0% 0%, 100% 0%, 100% 100%, 14% 100%) creates a trapezoid that approximates the visual footprint of the perspective-tilted pull quote. The 14% bottom-left inset roughly matches the apparent narrowing from rotateY(14deg) at the default perspective distance.

For the flipped variant, the polygon mirrors: polygon(14% 0%, 100% 0%, 100% 100%, 0% 100%).

6. Inline Highlights

The foveal region covers roughly 2 degrees of visual angle — about the width of your thumbnail at arm's length. Everything beyond that peripheral field is processed at progressively lower spatial resolution, following the cortical magnification function described above.

7. Drop Caps

Peripheral vision is not blurry vision. The retina's ganglion cell density drops with eccentricity, but peripheral processing excels at detecting motion, flicker, and large-scale spatial structure. The visual system trades resolution for temporal sensitivity as you move away from the fovea — a design tradeoff, not a deficiency.

Ornate variant

Every typeface carries its own history. The drop cap, or lettrine, dates to hand-illuminated manuscripts where monks painted the opening letter in gold leaf and lapis lazuli. Modern typography inherited the convention stripped of its gilding but not its function: signal the start, reward the eye, set the pace for what follows.

7b. Lead-in (Rubrication)

The ganglion cell layer is where the retina's editorial decisions become irreversible. Signals that survive center-surround filtering are bundled into 1.2 million axons — the optic nerve — and there is no going back to the raw photoreceptor mosaic after this point.

Small-caps variant

Cortical magnification describes how many millimeters of cortical surface represent one degree of visual angle. The function falls off hyperbolically from the fovea, with roughly half of V1 devoted to the central 2–3 degrees.

Paired with drop cap

Rubrication dates to medieval manuscripts where scribes wrote opening words in red ink — Latin ruber. The convention survived into modern editorial design as the colored lead-in, signaling the start of a new section without the weight of a full subheading.

8. Footnotes

The fovea covers roughly 2 degrees of visual angleAbout the width of your thumbnail at arm's length, or roughly 1.5mm on the retina. Ganglion cell density peaks here at ~35,000 cells/mm². but accounts for over half of the neural real estate in primary visual cortexThis disproportionate allocation is described by the cortical magnification function: M(e) = M₀ / (1 + e/e₂), where M₀ ≈ 15–20 mm/deg for V1.. This overrepresentation is not waste — it's the biological cost of high-acuity central visionPeripheral vision compensates with superior temporal resolution and motion sensitivity, making it the dominant early-warning system for saccade targeting..

Footnote markers auto-number via CSS counters. Content lives inline with its reference — no bottom-of-page lists to maintain. Hover or tab to a marker to reveal the note. Works without JavaScript; JS enhances popover positioning near viewport edges.

Manual numbering

You can also provide explicit marker text: some claim*This uses a manual marker instead of auto-numbering. Just put text inside the mg-fn-ref element. rather than a number.

9. Gallery / Lightbox

Click any image to expand in a lightbox overlay. Arrow keys navigate between images, ESC or click outside to close. Side-by-side comparison grids stack on mobile.

Single image

Side-by-side comparison

10. Inline Skew Callout

Note: The V1 cortex tiles the visual field with orientation columns spaced at roughly 0.5mm intervals. Each hypercolumn contains a complete set of orientation preferences — a local Fourier basis for spatial frequency analysis.

Tip: Pair skewed callouts with pull quotes for a consistent 3D language across the page. The subtle 4° tilt here complements the stronger 14° on pull quotes.

11. Sidebar

Sidebars float alongside body text, providing tangential context without interrupting the reading flow. They use body-copy sizing — small enough to be subordinate, large enough to be legible. The subtle background and border distinguish them from the main column without the visual weight of a full callout.

Use sidebars for implementation notes, historical context, or definitions that support the main argument but aren't essential to it. They work best when the reader can skip them on a first pass and return on a closer read.

Wide variant

The mg-wide modifier increases sidebar width to 220px for longer content that needs breathing room. Both variants collapse to full-width blocks on mobile viewports.

Sidebars are the marginalia equivalent of a penciled annotation — they belong to the document but live at a lower priority level than the prose they accompany.

12. Margin Note

On screens wider than 1200px, margin notes escape the content column and float in the gutter with large peripheral-readable text. On narrower screens they degrade to inline callouts. Resize your browser to see both modes.

The tiles are still square That's the hardware. The retina compensates in the wiring.

The content column needs a parent with mg-margin-scope to allow the note to escape via absolute positioning. On desktop, the note appears in the left gutter at 2.8rem / 800-weight with a 14° perspective tilt pointing inward toward the body text.

The 5px border sits on the inside edge — right border for left-gutter notes, left border for right-gutter notes — creating a visual bridge between the annotation and the text it refers to.

12b. Margin Note — Right Gutter

130M → 1.2M The retina's compression ratio. Not a bottleneck — an editorial decision.

Add mg-right to position the note in the right gutter instead. The border flips to the left (inside) edge and the perspective tilt mirrors to point inward. On narrow screens both variants collapse identically to inline callouts.

Left and right gutter notes can alternate down a long article, creating the kind of margin annotation rhythm you see in academic textbooks or magazine feature spreads.

2b. Pull Quote — Flat + Flipped

Combining mg-flat and mg-flip gives a left-floated sidebar without the 3D perspective tilt. This is the quietest pull quote variant — no skew drawing the eye, just a bordered float sitting in the left margin.

The four pull quote configurations form a 2×2 matrix: skewed/flat × right/left. Each serves a different editorial role, from the dramatic tilted hero quote to the understated left-margin gloss.

13. Content Mode

Repeat mode (data-content="repeat") signals that the callout duplicates text from the surrounding body — the traditional pull quote. It renders in italics at slightly reduced opacity, telling the reader "you've seen this already; this is emphasis, not new information."

Progressive spatial pooling solves the same problem whether evolution or engineering builds it. Hardware MIP chains and retinal eccentricity gradients converge on the same Laplacian pyramid structure because the optimization landscape has one global minimum.

Insert mode (data-content="insert") signals new standalone content — a tangential observation, an aside, a definition. Normal weight, full opacity. The reader knows this is additive information worth reading even if they've read every word of the body text.

The content mode attribute works on any callout variant: pull quotes, margin notes, sidebars, and inline callouts. It's a semantic flag, not a layout modifier.

On a callout

Aside: The magnocellular pathway carries achromatic, high-temporal-frequency signals from parasol ganglion cells. It's faster than the parvocellular pathway by ~20ms — enough to prime spatial attention before fine detail arrives.

On a sidebar

Content mode on a sidebar signals whether the tangential note paraphrases nearby body text or introduces a new definition. Insert mode keeps normal weight; repeat mode would italicize the sidebar body.

14. Spread — Two-Column Magazine Layout

Two-column body text with callouts that bridge both columns. The classic editorial spread — inspired by CSS Regions (Adobe's abandoned spec) but built on column-count + column-span: all, which actually ships in every browser.

The retina performs more computation than any other structure in the central nervous system relative to its size. Six layers of neurons — photoreceptors, horizontal cells, bipolar cells, amacrine cells, ganglion cells, and their associated interneurons — implement a signal processing pipeline that would require roughly 10 billion operations per second to simulate digitally.

Center-surround receptive fields emerge at the ganglion cell layer through lateral inhibition mediated by horizontal and amacrine cells. This architecture performs simultaneous contrast normalization across the entire visual field, adapting the neural code to local luminance statistics on a millisecond timescale. The result is a representation that encodes edges, gradients, and transients rather than absolute intensity — exactly the features that matter for object recognition downstream.

Midget ganglion cells in the central retina maintain a one-to-one connection with individual cone photoreceptors, preserving the full spatial resolution of the cone mosaic. This private-line architecture is unique to primates and explains why human visual acuity exceeds that of all other mammals despite having a similar optical system. The tradeoff: midget cells consume roughly 80% of ganglion cell bandwidth for the central 5 degrees alone.

Note: The midget pathway's 80% bandwidth allocation for 5° of visual field is the biological precedent for foveated rendering's aggressive LOD falloff. If the retina can justify that resource distribution, so can your shader.

Parasol cells cover the remaining visual field with larger receptive fields optimized for temporal contrast and motion detection. Their faster conduction velocity and transient response profiles feed the magnocellular pathway, which drives saccade targeting and the perception of optic flow. This is the system that makes you flinch before you consciously see the baseball.

The division of labor between midget and parasol pathways is not a compromise — it's a Pareto-optimal allocation of neural bandwidth given the statistics of natural scenes. High spatial frequency information is concentrated at fixation. Motion energy dominates the periphery. The retina matches its channel capacity to the signal structure at each eccentricity.

Usage

<!-- Include in your page -->
<link rel="stylesheet" href="marginalia.css">
<script src="marginalia.js" defer></script>

<!-- Callout -->
<div class="mg-callout" data-type="note">
  <p><strong>Note:</strong> Your content here.</p>
</div>

<!-- Pull quote -->
<aside class="mg-pull">Your quote text.</aside>
<aside class="mg-pull mg-flat">Flat sidebar (no 3D tilt).</aside>

<!-- Code block -->
<pre class="mg-code" data-lang="js">const x = 42;</pre>

<!-- Badge -->
<span class="mg-badge">Label</span>

<!-- Collapse -->
<details class="mg-collapse">
  <summary>Title</summary>
  <div class="mg-collapse-body">Content</div>
</details>

<!-- Highlight -->
<mark class="mg-mark">highlighted text</mark>

<!-- Drop cap -->
<p class="mg-dropcap">Your opening paragraph.</p>
<p class="mg-dropcap" data-type="ornate">Ornate variant with border accent.</p>

<!-- Lead-in (rubrication) -->
<p><span class="mg-lede">Opening words</span> rest of text.</p>
<p><span class="mg-lede" data-type="caps">Small caps</span> variant.</p>

<!-- Footnote (auto-numbered) -->
Text<span class="mg-fn">
  <a class="mg-fn-ref" tabindex="0"></a>
  <span class="mg-fn-body">Footnote content shown on hover/focus.</span>
</span> continues.

<!-- Inline skew callout -->
<div class="mg-callout mg-skew" data-type="note">Tilted block callout.</div>

<!-- Sidebar — float-right body-copy tangential note -->
<aside class="mg-sidebar">
  <strong>Title</strong>
  <p>Tangential context at body-copy size.</p>
</aside>
<aside class="mg-sidebar mg-wide">Wider variant.</aside>

<!-- Margin note — escapes into the gutter on wide screens -->
<div class="mg-margin-scope">
  <div class="mg-margin">
    Big gutter text
    <small>Explanatory subtext.</small>
  </div>
  <p>Body text continues normally.</p>
</div>

<!-- Content mode: repeat (duplicated body text) vs insert (new content) -->
<aside class="mg-pull" data-content="repeat">Emphasized body text.</aside>
<aside class="mg-pull" data-content="insert">New standalone aside.</aside>

<!-- Two-column magazine spread -->
<div class="mg-spread">
  <p>Body text flows into two columns.</p>
  <aside class="mg-pull">Bridges both columns.</aside>
  <p>Text resumes in two columns.</p>
</div>

<!-- Remove vertical bar from any component -->
<div class="mg-callout" data-type="note" data-bar="none">No left border.</div>