Scratch – headings
- Posted
27 July 2025
Continuing my incremental NetNewsWire theme build. Version 7 (The riddle of the NetNewsWire visited link) made changes to handle feeds with no feed link. This version takes first steps to improve the type.
Since the last version of Scratch I published, I explored some ideas around typography. Including using :has()
to apply a heading hierarchy dynamically. I’ve used this idea to style headings in the Scratch theme.
Font choice
The first step was to design the full spread of headings. To help bridge all six levels between H1
and H6
I chose two fonts. San Franciso for display, and New York for text. I went for these partly for their flexibility as variable fonts, but mostly because they are readily available as system fonts on MacOS and iOS.
Although a .nnwtheme package could include font files, NetNewsWire provides no means to reference them. Even if it did, licensing a font for to be distributed in a NetNewsWire theme seems like a stretch. I expect we would be limited to free or open source fonts anyway.
To preserve a simple theme installation I’d rather not ask you to install a font and a NetNewsWire theme. So system fonts it is.
Assigning Apple system fonts with CSS
As expected we use the CSS font-family
property. Surprisingly though, using the names of the fonts does not work. Instead we need to use one of a set of keywords.
font-family: system-ui;
to assign San Francisofont-family: ui-serif;
for New York
For a web site that might be displayed on any device, fleshing out a list of fallbacks is prudent. For a NetNewsWire theme, defining a font stack is pointless. Occurred to me I could define a preferred font that requires installation, and use a system font as a fallback. Someday maybe.
Tweaking unicode font features
To discover the features available on these fonts I inspected the Apple Variable Fonts page in browser dev tools.
For example: font-variation-settings: "wght" 400, "opsz" 22, "wdth" 75;
adjusts the weight, optical size and width of San Franciso.
New York only provides a weight adjustment.
Vertical spacing
Initially I set out to place all text on a consistent baseline grid. In practice I found the grid had to be overly fine to maintain it strictly. I’ve kept rlh
for all line height values. For fine spacing control I’ve used a quarter division of 0.25rlh
. The benefit of a baseline grid is as subjective as it gets. Especially in a single column layout. I like to think it provides a subtle reassuring consistency.
Paragraph spacing
After line height to separate lines of text, the next step in visual hierarchy is the break between paragraphs. For Scratch I’ve chosen a different handling of this break depending on the text measure. When the line length is narrow I’m using an indent and no additional space between paragraphs. This is good for maintaining a baseline grid, and more significantly, maximising the vertical density on smaller screens.
For wider viewports a minimal margin denotes the start of new paragraphs in place of the indent. Restricting the use of indenting for narrow screens reduces the instances of awkward single line paragraphs causing consecutive indented lines.
I could have stuck more strictly to the baseline grid by choosing to split paragraphs with the equivalent of an empty line break. This large space, however, would increase the space necessary to distinguish headings.
Margins for visual hierarchy
Along with font weight and sizing, I’ve used margins to help distinguish heading levels. Additional space around higher level headings lends them visual importance.
Flattening CSS specificity with @layer
To make it easier to override some moderately complicated selectors without complicating them further, I introduced a “base” CSS @layer
. Styles outside of a layer override those inside a layer without consideration of specificity.
Some polish
What sup with footnote size?
My previous difficulty determining why footnotes were rendering with text content smaller than the body text is resolved! Noticing only some footnotes were too small was the clue I needed to realise the little footnotes were nested in a <sup>
.
Assigning font-size: inherit;
to <sup>
elements inside a.footnote
elements did the trick.
I had to jump through similar hoops to solve issues with paragraph indent inherited by nested footnote paragraphs. Looks increasingly worthwhile to reimplement footnotes in NetNewsWire using popover to avoid the need for nesting. Especially when the incoming anchor positioning support lands.
Hiding SVG sprites
It’s a rare RSS feed that includes working inline SVG sprites. Rather than leaving a mystery vacant space, I’m hiding SVG that follow the common pattern:
svg:has(> use[href^="#"]:only-child) {
display: none;
}
Install
To enable a quick switch between different versions of this theme I’ve generated a zip of each version – incorporating the version number in the name:
Get the latest version on the Scratch project page.
Next up
Version 8 demonstrates many clear opportunities for improvement including:
Code typography
Monospace text could use some love and attention.
Variable line-height
The 1.5 line-height looks much too tight over the longer text measures you might see on a wider screen. I plan on expanding this relative to the displayed width to ease reading.
Horizontal spacing
I’m yet to address horizontal spacing of elements such as lists, figures, blockquotes, or the page itself.