Index


60 Characters

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

If the screen is wide enough, this text wraps exactly every 60 characters. Using a monospace font and careful choice of words, I can perfectly justify text and avoid uneven spaces and kerning like often produced by CSS text-align: justify.

Wide text looks like this; wrapping every 80 instead of 60. It's hard to ensure everything flows nicely at both widths, so I follow a template while writing to ensure I put spaces at a few critical positions. Here's the basic pattern. Zoom in or out, or resize the window, to see everything reflow.

My static site generator reads markdown and generates plain HTML with (almost) no JavaScript. I support styled text and even LATEX, all perfectly aligned to the character grid.

Code

Everything is monospace, and I write about coding and math, so it's critical to distinguish code snippets from the main text. Code uses a different font and background, and blocks of code have syntax highlighting.

const std = @import("std");

pub fn main() void {
    std.log.debug("Hello, World!");
}

Fonts

I can also change the font for an element using attributes like {: .radon } (handwriting) or {: .lm } (Latin Modern).

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
— Tim Peters, The Zen of Python

The monospace font is Monaspace; its variants have the same dimensions, so mixing variants preserves the main grid. The proportional and math font is Latin Modern, consistent with all the other LATEX on the page.

Math

My Python-Markdown extension compiles LATEX to MathML while the static site is generated; there's no client-side render step, so (as long as fonts are cached) math is instant. But since I insist on aligning everything to the character grid there is a small step to add padding to inline math tags so their width is some integer number of characters.

With that, this markup:

[[ \iint_\Sigma \nabla \cross \mathbf F \cdot d \Sigma 
= \oint_{\partial \Sigma} \mathbf F \cdot d \Gamma ]]

Or [( 
\int_M d\tilde\varphi = \int_{\partial M} \tilde\varphi 
)], as the differential geometers say. Note 
that text before and after inline math is aligned the same.

Compiles to this static html:

Σ×𝐅dΣ=Σ𝐅dΓ

Or Mdφ~=Mφ~, as the differential geometers say. Note that text before and after inline math is aligned the same.

I use TEMML to render MathML; from experience it yields the best-looking results. However, TEMML is a NodeJS module! To invoke it from Python I use JSPyBridge. I've been impressed at how seamless it is (as long as node is on your PATH). To be clear, this is Python:

from javascript import require

temml = require('./temml.cjs')
mathml = temml.renderToString(r'\LaTeX')

Figures

I finally implemented a Python-Markdown extension to render tikz figures and embed them in the page as svg. However, it was very slow; every figure on every page launched its own xetex process. So, instead, I modified the extension to run Python code blocks and embed any matplotlib.pyplot figures. Just set the language to py figure or py wide figure!

Styling

Use class attributes to override styles for block elements.

Wide text looks like this; wrapping every 80 instead of 60. It's hard to ensure everything flows nicely at both widths, so I follow a template while writing to ensure I put spaces at a few critical positions. Here's the basic pattern. Zoom in or out, or resize the window, to see everything reflow.

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbb ccccccccccccccccccccccccccccccccccccccc ddddddddddddddddddddddddddddddddddddddd eeeeeeeeeeeeeeeeeee fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

![](https://cdn.esahubble.org/archives/images/screen/heic1502a.jpg)
Hubble image of the Andromeda galaxy.
{: .wide .radon .center}

Hubble image of the Andromeda galaxy.

abf(x)dx