<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>ollicle.com</title>
	<subtitle>by Oliver Boermans</subtitle>
	
	<link rel="alternate" type="text/html" href="https://ollicle.com/" />
	<link rel="self" href="https://ollicle.com/feed.xml" />
	<updated>2026-05-29T10:42:28Z</updated>
	<id>https://ollicle.com/</id>
	
	<entry>
		<title>Scratch – Re-title</title>
		<link href="https://ollicle.com/2026/may/29/scratch-re-title/"/>
		<updated>2026-05-29T10:42:28Z</updated>
		<id>https://ollicle.com/2026/may/29/scratch-re-title/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Continuing my incremental NetNewsWire theme build. Version 12 (&lt;a href=&quot;https://ollicle.com/2026/feb/21/scratch-text-measure/&quot;&gt;Scratch – text measure&lt;/a&gt;) improved reading by limiting line lengths and some other tweaks.&lt;/p&gt;
&lt;p&gt;This version too includes a collection of miscellaneous refinements. I’ll list them below. First though, I want to share the feature I’m most enthused about, responding to the shape of posts.&lt;/p&gt;
&lt;h2&gt;The shape of a feed item&lt;/h2&gt;
&lt;p&gt;The endurance of RSS as a standard can be attributed to it’s simplicity not it’s perfection. This is especially true when it comes to &lt;em&gt;how&lt;/em&gt; people push their differently shaped content into the RSS fields.&lt;/p&gt;
&lt;p&gt;Not all content that is pushed into an XML feed obviously fits into a title and a body. We’ve collectively agreed this is okay! You have some text? The important bit is the sharing. As a result we get posts that are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The regular title and body&lt;/li&gt;
&lt;li&gt;Body with no title&lt;/li&gt;
&lt;li&gt;Title with no body&lt;/li&gt;
&lt;li&gt;Body same as the title&lt;/li&gt;
&lt;li&gt;Truncated body as title&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These all make regular appearances in my feed reading. All deserve consideration.&lt;/p&gt;
&lt;h2&gt;Re-thinking untitled posts&lt;/h2&gt;
&lt;p&gt;My previous effort towards a consistency of sorts across this range was to populate the title with the date stamp when it would otherwise be empty. By ensuring there was always a h1 this might in some way benefit folks who are somehow using heading structure. &lt;em&gt;Note to self – check exactly what VoiceOver reads&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Visually though, I’ve had a change of heart. I’m keeping the consistent heading structure, but decided posts without titles &lt;em&gt;should&lt;/em&gt; look different. In version 13, instead of hoisting up a part of the date stamp to be a title stand-in, I’ve linked and made the date stamp &lt;em&gt;the&lt;/em&gt; h1. A welcome simplification.&lt;/p&gt;
&lt;p&gt;As a consequence the title in the large bold display font is simply &lt;em&gt;missing&lt;/em&gt;. Typographically I see this as a useful contrast rather than an inconsistency to be fixed. It does however, provide an opportunity.&lt;/p&gt;
&lt;h2&gt;Big short posts&lt;/h2&gt;
&lt;p&gt;There are no rules. However, posts without titles are often short and seldom use sub headings. Hierarchically they are flat.&lt;/p&gt;
&lt;p&gt;To add some nice constrast back I set out to make the body of such larger than the date stamp. Lots bigger because, what designer passes up an opportunity for a bit of big font?&lt;/p&gt;
&lt;p&gt;With the power of &lt;code&gt;:has()&lt;/code&gt; (&lt;em&gt;spoken like He-Man to his sword&lt;/em&gt;), testing for an absence of headings is just CSS. The length of text though, requires JavaScript. That’s okay, this is an enhancement only applied if such a post is identified.&lt;/p&gt;
&lt;p&gt;Scaling up a thus enlarged &lt;code&gt;&amp;lt;blockquote&amp;gt;&lt;/code&gt; required reworking the styles to use &lt;code&gt;em&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since I have JavaScript enabled now and spare opinions, might as well keep going.&lt;/p&gt;
&lt;h2&gt;Untitled beats Unbodied&lt;/h2&gt;
&lt;p&gt;Body with no title and title with no body are the same picture. A post with one length of text rather than two. It follows that they share a display mode.&lt;/p&gt;
&lt;p&gt;The theme uses JavaScript to move a title-only title text into the body.&lt;/p&gt;
&lt;h2&gt;The reason I bothered&lt;/h2&gt;
&lt;p&gt;The last two post shapes in the list above, body same as the title and truncated body as title, are just another variety of untitled. The author has been uncomfortable with, or uses a system that has prevented, an empty title. Like one those people with only one name confronted with a required family name field. Easy fix. Repeat it.&lt;/p&gt;
&lt;p&gt;The repetitive tedious experience of reading a post title, only to read it again in the post body, motivated most of the effort above. These are the real villan is this story.&lt;/p&gt;
&lt;p&gt;Removing the titles from these posts feels great. Well worth enabling JavaScript to compare and weed out those redundant words.&lt;/p&gt;
&lt;h3&gt;Enabling JavaScript in NetNewsWire&lt;/h3&gt;
&lt;p&gt;The checkbox to &lt;strong&gt;Enable JavaScript&lt;/strong&gt; is near the top of NetNewsWire general settings.&lt;/p&gt;
&lt;h2&gt;The other stuff&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Added &lt;strong&gt;Hanging punctuation&lt;/strong&gt; why the heck are are [brackets] considered hang worthy!?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some extra indent for &lt;strong&gt;lists within blockquote&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Applied &lt;strong&gt;tab-size&lt;/strong&gt; to size tabs as appear in code blocks. Expanded on wider measures.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Respected the &lt;code&gt;style&lt;/code&gt; attribute used to size &lt;strong&gt;Wordpress text icons&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tightened up the selector logic used to size icon sized &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Squeezed a little vertical space in respect to a &lt;strong&gt;shallow viewport&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;One more thing&lt;/h2&gt;
&lt;p&gt;Version 26 of Safari suffered &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=314999&quot;&gt;a regression&lt;/a&gt; that occurs when elements to which SVG filters are applied are clipped. Look out for unexplained black squares!&lt;/p&gt;
&lt;p&gt;This impacts the external link styling in Scratch.&lt;/p&gt;
&lt;p&gt;The only fix that worked, other than removing the SVG filter, was to ensure the link remained visible within the viewport. So I made it sticky. This required reworking the filter to make the shape opaque. As far as a workaround goes I’m happy with this outcome. Might even be a feature to have it visible without scrolling.&lt;/p&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v13.nnwtheme.zip&quot;&gt;Install: Scratch v13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v13.zip&quot;&gt;Download: Scratch_v13.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Template variables v5</title>
		<link href="https://ollicle.com/2026/mar/01/template-variables-v5/"/>
		<updated>2026-03-01T11:19:12Z</updated>
		<id>https://ollicle.com/2026/mar/01/template-variables-v5/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Update to my NetNewsWire &lt;a href=&quot;https://ollicle.com/projects/netnewswire/template-variables/&quot;&gt;Template variables theme&lt;/a&gt; pushed.&lt;/p&gt;
&lt;p&gt;This theme remains useful as a template variable reference, I checked it recently for the date stamp options and discovered it was missing a variable I was already using in the theme I’m working on: &lt;code&gt;[[datetime_medium]]&lt;/code&gt;. Fixed!&lt;/p&gt;
&lt;p&gt;Also, in a face-palm moment, I remembered &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; will render HTML markup as text. Makes much more sense than messing about with deprecated tags. Finally wrapped the content in a &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;, not sure if doing so helps anyone, but I can’t see it hurting as a convention.&lt;/p&gt;
&lt;h2&gt;Enable Web Inspector in NetNewsWire&lt;/h2&gt;
&lt;p&gt;The reason I’m subtlety talking down the usefulness of this theme is when I made it I didn’t know about the NetNewsWire debug menu. Enabling it exposes the &lt;strong&gt;Enable Web Inspector&lt;/strong&gt; menu. With this option checked we can right click in the article pane in NetNewsWire, select &lt;strong&gt;Inspect Element&lt;/strong&gt;, and Safari dev tools opens to inspect the source of the current theme template, styled with the current theme styles. Absolutely essential for NetNewsWire theme development!&lt;/p&gt;
&lt;h2&gt;Enable the debug menu in NetNewsWire&lt;/h2&gt;
&lt;p&gt;In Terminal enter and execute:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;defaults write com.ranchero.NetNewsWire-Evergreen ShowDebugMenu 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s it!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Scratch – text measure</title>
		<link href="https://ollicle.com/2026/feb/21/scratch-text-measure/"/>
		<updated>2026-02-21T03:42:32Z</updated>
		<id>https://ollicle.com/2026/feb/21/scratch-text-measure/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Continuing my incremental NetNewsWire theme build. Version 11 (&lt;a href=&quot;https://ollicle.com/2025/nov/28/scratch-header/&quot;&gt;Scratch – post header&lt;/a&gt;) styled the post header and finessed links and rules.&lt;/p&gt;
&lt;p&gt;I’ve been sitting on this new version, using it while I ponder the next focus. Well past due time to share the current increment.&lt;/p&gt;
&lt;h2&gt;Back pedalling on the style overrides&lt;/h2&gt;
&lt;p&gt;Previously I applied an aggressive &lt;code&gt;!important&lt;/code&gt; to unset inline styles in feed content. This ultimately caused more trouble than it solved. To compromise I’ve kept the width override to ensure that otherwise fixed width content remains responsive.&lt;/p&gt;
&lt;h2&gt;More space&lt;/h2&gt;
&lt;p&gt;Although readable, the text &lt;em&gt;felt&lt;/em&gt; cramped – particularly on my little phone. To add some air the global line-height has been increased. For similar effect I’ve also increased the page gutters.&lt;/p&gt;
&lt;p&gt;The reduction of text density is most noticeable using small text on a larger screen. In this context you’ll see I’ve also added a limit to the length of the text measure.&lt;/p&gt;
&lt;p&gt;For the sake of readability, increasing the line-height helps. However, an over-large line-height results in lines that feel disconnected from one another. Large line spaces also make the use of larger margins to help distinguish headings less effective.&lt;/p&gt;
&lt;p&gt;Had to draw the line somewhere.&lt;/p&gt;
&lt;h2&gt;Nudge third level headings&lt;/h2&gt;
&lt;p&gt;Squished ’em a little for a more typographic affinity with the proceeding levels.&lt;/p&gt;
&lt;h2&gt;Ordered lists&lt;/h2&gt;
&lt;p&gt;For contrast, I found one opportunity to tighten some space. Specifically the left indent alongside short ordered lists. Ordered lists with ten or greater items get a slightly larger space to ensure space for two digits.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ol:not(:has(&amp;gt; li:nth-child(10))) {
	padding-inline-start: 2.1ch;
}
ol:has(&amp;gt; li:nth-child(10)) {
	padding-inline-start: 3.1ch;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ain’t CSS lovely.&lt;/p&gt;
&lt;h2&gt;NetNewsWire 7&lt;/h2&gt;
&lt;p&gt;I’m thrilled to see NetNewsWire grow up with Brent’s ongoing care. I share a fondness for his cause to help lift the RSS boats. Between this post and my previous – NetNewsWire has &lt;a href=&quot;https://netnewswire.blog/2026/02/11/netnewswire-turns.html&quot;&gt;turned 23 years old&lt;/a&gt; and released version 7:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://netnewswire.blog/2026/02/06/netnewswire-for-ios.html&quot;&gt;NetNewsWire 7 for iOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://netnewswire.blog/2026/01/27/netnewswire-for-mac.html&quot;&gt;NetNewsWire 7 for Mac&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both of these require version 26+ of their respective OS’s – into which I’m yet to venture. As a result I have not seen NetNewsWire in liquid glass beyond the odd screenshot, let alone how the Scratch theme looks in it. I am not anticipating issues or even a need to make changes. Feedback is welcome.&lt;/p&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v12.nnwtheme.zip&quot;&gt;Install: Scratch v12&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v12.zip&quot;&gt;Download: Scratch_v12.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Scratch – post header</title>
		<link href="https://ollicle.com/2025/nov/28/scratch-header/"/>
		<updated>2025-11-28T07:32:34Z</updated>
		<id>https://ollicle.com/2025/nov/28/scratch-header/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Continuing my incremental NetNewsWire theme build. Version 10 (&lt;a href=&quot;https://ollicle.com/2025/oct/19/scratch-line-height/&quot;&gt;Scratch – version 10&lt;/a&gt;) added a responsive line-height, styled &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt;, post external link, and made a start on unordered lists. This version styles the post header, post title link, tones down the styling of links, and makes horizontal rules dotty.&lt;/p&gt;
&lt;h2&gt;Post header&lt;/h2&gt;
&lt;p&gt;Starting from the top, is the post header styling.&lt;/p&gt;
&lt;p&gt;I’ve kept it boring and minimal. Applying a grid layout layout to cluster the icon, feed title and byline – reducing the space they were occupying.&lt;/p&gt;
&lt;p&gt;When the author line is present I’m reducing the size of the feed title and capitalising it. Shifting the emphasis towards the author’s name. As both the feed title and byline may have distinct links, some fat finger space between them is essential.&lt;/p&gt;
&lt;p&gt;The header is set in the sans-serif font in keeping with it’s role as furniture.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;p&gt;I found the underlined, contrasted, links a little too prominent. I knocked back their emphasis by dimming the text decoration colour a shade. Taking care to ensure the underlines remained sufficiently clear. With only a relatively subtle colour difference the underlines remain critical to them being recognised as such.&lt;/p&gt;
&lt;p&gt;Pushing the underline away from the text enhanced the legibility of the underlined text.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a {
	text-underline-offset: var(--underline-offset, 15%);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The custom property here provided an easy means to tighten this value on headings which are either a different font or larger size. Mostly for the condensed font.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;h2,h3,h4,h5,h6 {
	--underline-offset: 10.5%;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Maybe a different unit here would make it possible to set one value that would work for both – responding to the x height appropriately. I didn’t spend enough time testing to say for sure.&lt;/p&gt;
&lt;h2&gt;The post title link&lt;/h2&gt;
&lt;p&gt;H1 is obviously missing from the above heading selector. I have special cased the post title. Removing the underline to make it a more headline like.&lt;/p&gt;
&lt;p&gt;The post title for a feed item is &lt;em&gt;almost&lt;/em&gt; always linked, there is only one in a post, and it’s in the same place. Removing the underline allowed me to reduce the visual noise. The expectation that the title is linked is strong enough that the indicator for it could afford to be somewhat subtle.&lt;/p&gt;
&lt;p&gt;As unlinked posts are not unheard of, I wanted some kind of indicator that the title &lt;em&gt;went somewhere&lt;/em&gt;. Looking through the arrows available I chose the Medium Right-Pointing Angle Bracket ❭ – placing it like an icon on the end of the title link.&lt;/p&gt;
&lt;h3&gt;Preventing orphans&lt;/h3&gt;
&lt;p&gt;Adding an icon to the end makes it the first candidate to wrap onto the next line if the title length is just so. To avoid it doing so without the company of some text, I added a Zero Width No-break Space alongside the arrow character. Applying &lt;code&gt;white-space: nowrap;&lt;/code&gt; to their wrapper has the desired effect – providing there is no regular spaces between the title text and the “icon”.&lt;/p&gt;
&lt;p&gt;Now if the arrow must wrap to fit, it takes the last word with it.&lt;/p&gt;
&lt;p&gt;As an odd side note, I found when I applied &lt;code&gt;text-wrap: balance&lt;/code&gt; to the heading with this arrangement, it had the perverse effect of often &lt;em&gt;forcing&lt;/em&gt; the arrow onto the second line, but only when the heading was a single short word. Weird!&lt;/p&gt;
&lt;h2&gt;Horizontal rules&lt;/h2&gt;
&lt;p&gt;Even as I write this I’m continuing to make changes to the &lt;code&gt;&amp;lt;hr&amp;gt;&lt;/code&gt; styling. &lt;em&gt;Currently&lt;/em&gt; I’m treating it a little like a &lt;a href=&quot;https://en.wikipedia.org/wiki/Greeking&quot;&gt;greeked&lt;/a&gt; heading (apologies to anyone to whom Greek is perfectly comprehensible!). To make it a little closer to the texture of text I’ve given it some weight and dotted it. To help keep the emphasis on the breath of space above it, it is coloured a noticeable step below the text contrast.&lt;/p&gt;
&lt;p&gt;Speaking of rules; &lt;code&gt;border-style: dotted;&lt;/code&gt; in Safari (for anyone not looking at it) creates alternating squares, not “dots” which to my mind ought to be round. &lt;em&gt;Shrugs&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v11.nnwtheme.zip&quot;&gt;Install: Scratch v11&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v11.zip&quot;&gt;Download: Scratch_v11.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next up&lt;/h2&gt;
&lt;p&gt;I don’t have a roadmap. Consider the &lt;em&gt;Next up&lt;/em&gt; sub heading deprecated.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Scratch – version 10</title>
		<link href="https://ollicle.com/2025/oct/19/scratch-line-height/"/>
		<updated>2025-10-19T00:42:35Z</updated>
		<id>https://ollicle.com/2025/oct/19/scratch-line-height/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Continuing my incremental NetNewsWire theme build. Version 9 (&lt;a href=&quot;https://ollicle.com/2025/aug/31/scratch-figure-blockquote/&quot;&gt;Scratch – figure and blockquote&lt;/a&gt;) styled figures, blockquotes, and figures in blockquotes.&lt;/p&gt;
&lt;p&gt;Alongside some fixes, this version styles the external link, aside elements, unordered lists, and applies a dynamic line-height.&lt;/p&gt;
&lt;h2&gt;External link aside&lt;/h2&gt;
&lt;p&gt;The external link is not strictly &lt;em&gt;part&lt;/em&gt; of a post. It is data associated with the post, like the date. It is generally a link to the &lt;em&gt;subject&lt;/em&gt; of the post and therefore a natural place to go once we’ve read what our beloved blogger and had to say about it.&lt;/p&gt;
&lt;p&gt;Relatively few bloggers I read make use of the external link field in their feed. To do so it is necessary to explicitly assign the link in question to a dedicated field in such a way that it will make it’s way to the appropriate place in the feed xml. Few folks are looking for those kind of extra steps when they blog.&lt;/p&gt;
&lt;p&gt;It’s a shame it’s not more commonly used. “Blog” is short for “web log” in which external links are the whole point!&lt;/p&gt;
&lt;p&gt;No shade from me, additional blog fields add blogging friction. Whack it in the content if you must. Please keep blogging!&lt;/p&gt;
&lt;h3&gt;Template aside&lt;/h3&gt;
&lt;p&gt;My initial take on the theme template placed the external link (on posts that provide one) at the end of the content after a horizontal rule (&lt;code&gt;&amp;lt;hr&amp;gt;&lt;/code&gt;). For version 10 I started looking at ways to style this rule and link combination – to distinguish it from the post content.&lt;/p&gt;
&lt;p&gt;Dissatisfaction with my efforts led me to reconsider this mark-up entirely. Placing the link in an &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt; (please excuse my punny foreshadowing) feels better to me. More semantic? Locating the aside element after the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; in hope that it may make it a little more prominent to a savvy VoiceOver user somewhere.&lt;/p&gt;
&lt;p&gt;I relegated the external link label “Link” to an &lt;code&gt;aria-label&lt;/code&gt; for the &lt;code&gt;aside&lt;/code&gt;. It is obviously a link. If my design succeeds it will obviously be &lt;em&gt;the&lt;/em&gt; link.&lt;/p&gt;
&lt;h3&gt;Aside outline&lt;/h3&gt;
&lt;p&gt;Experimenting with outlining the aside I tried a bunch of different line styles. The url never looked comfortable in a box. I settled on applying an &lt;a href=&quot;https://tympanus.net/codrops/2019/01/15/svg-filters-101/&quot;&gt;SVG filter&lt;/a&gt; that would outline the link snugly with rounded corners. This feels particularly magical when the links wraps across multiple lines.&lt;/p&gt;
&lt;h2&gt;Content aside&lt;/h2&gt;
&lt;p&gt;While working on the external link I was surprised to notice the odd styled &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt; appearing in the content of blog posts. I had overlooked it as a content element to style. So happy accident!&lt;/p&gt;
&lt;p&gt;A strong separation from the surrounding content is the point of an aside. The dot pattern I used certainly has this effect. There was some trickiness involved to ensure the dot boundary was composed only of complete dots. Basing the dot size and spacing on a division of the text line height dealt with the vertical. While making use of the CSS &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/round&quot;&gt;round()&lt;/a&gt; function provided a means to lock the width to a whole division of the dot spacing horizontally.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;inline-size: round(down, 100%, var(--my-lh) * 0.5);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That custom property, &lt;code&gt;--my-lh&lt;/code&gt; is short for “my line-height”.&lt;/p&gt;
&lt;h2&gt;Line-height&lt;/h2&gt;
&lt;p&gt;It was while building a theme for an earlier version of NetNewsWire I had the &lt;a href=&quot;https://ollicle.com/2005/oct/12/javascript_flex_css/&quot;&gt;idea of making line-height dynamically adjust&lt;/a&gt;. Far out! It’s been twenty years! Back then doing so required JavaScript. Now it’s a tiny bit of CSS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;html {
	--my-lh: round(nearest, calc(1em + 1.5vw), 2px);
	line-height: var(--my-lh);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pff, who needs flying cars! We got CSS of the future.&lt;/p&gt;
&lt;p&gt;Technically, it could be simpler. I found the rounding was necessary to avoid some rounding errors that made a mess of the aside dots. The &lt;code&gt;vw&lt;/code&gt; contributes a scaling factor relative to the viewport width, while the &lt;code&gt;em&lt;/code&gt; responds to the font size.&lt;/p&gt;
&lt;p&gt;Why choose a CSS unit when you can mix them!&lt;/p&gt;
&lt;h2&gt;Unordered lists&lt;/h2&gt;
&lt;p&gt;I also applied some styling to unordered lists. Using outdented dots for the first level. I’m happy with how they look. I have doubts it is a good idea. Ordered lists can’t be aligned in the same manner. As a result the relative nesting depth becomes ambiguous when they are mixed.&lt;/p&gt;
&lt;p&gt;Let’s mark this as work in progress. I’m looking forward to Safari supporting the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/::marker&quot;&gt;&lt;code&gt;:marker&lt;/code&gt;&lt;/a&gt; pseudo to provide a little more control.&lt;/p&gt;
&lt;h2&gt;Polish&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Some little spacing adjustments to blockquote and figure.&lt;/li&gt;
&lt;li&gt;Applied a grid layout to the page to anchor external links to the bottom of the viewport.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Version 10 and how it’s going&lt;/h2&gt;
&lt;p&gt;My initial concept for the process of building Scratch was to tackle one thing at a time. As it has taken shape and started to look a little &lt;em&gt;nice&lt;/em&gt; I’ve found myself increasingly distracted by side polishing missions. I’m okay with that, design isn’t a straight line. And it’s my scratch I’m itching here!&lt;/p&gt;
&lt;p&gt;Maybe I’ll come back and make another pass through these posts, and fix the things I subsequently changed. Maybe I’ll add some screenshots. For now I’m documenting as I progress. The benefit of hindsight can come later.&lt;/p&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v10.nnwtheme.zip&quot;&gt;Install: Scratch v10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v10.zip&quot;&gt;Download: Scratch_v10.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next up&lt;/h2&gt;
&lt;p&gt;Likely some more miscellaneous polish. Maybe apply some layout to the header.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Vale Lyndon Whaite</title>
		<link href="https://ollicle.com/2025/oct/18/lyndon-whaite/"/>
		<updated>2025-10-18T00:29:00Z</updated>
		<id>https://ollicle.com/2025/oct/18/lyndon-whaite/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;I’m sad to learn that Lyndon Whaite has died this month. A web search will reveal some of the beautiful graphic design he created. The web however will not show you the many designers he taught and inspired in his many years of teaching here in Adelaide.&lt;/p&gt;
&lt;p&gt;I count myself very privledged to have had his attention as a student in a small class for my Underdale years.&lt;/p&gt;
&lt;p&gt;Your excitement for the magic and craft of design lives on in us Lyndon, thank-you.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Scratch – figure and blockquote</title>
		<link href="https://ollicle.com/2025/aug/31/scratch-figure-blockquote/"/>
		<updated>2025-08-31T07:20:53Z</updated>
		<id>https://ollicle.com/2025/aug/31/scratch-figure-blockquote/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Continuing my incremental NetNewsWire theme build. Version 8 (&lt;a href=&quot;https://ollicle.com/2025/jul/27/scratch-headings/&quot;&gt;Scratch – headings&lt;/a&gt;) styled headings and vertical typographic spacing. This version styles figure and blockquote.&lt;/p&gt;
&lt;h2&gt;Figures&lt;/h2&gt;
&lt;p&gt;The job of a &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; is to associate it’s subject with a caption, or more specifically a &lt;code&gt;&amp;lt;figcaption&amp;gt;&lt;/code&gt;. As the caption text is self contained, it also needs some indication that it is to be read isolated from the surrounding text.&lt;/p&gt;
&lt;p&gt;Sometimes you might see a figure used without a figcaption. I’m explicitly choosing not to apply figure styling to those. Without a caption to contain the figure is pointless.&lt;/p&gt;
&lt;p&gt;Default browser styles indent the figure element with inline margin. I’m indenting with a heavy rule extended to define the edge of a box to enclose the subject and caption text, holding and separating them from the surrounding content.&lt;/p&gt;
&lt;p&gt;Some figures contain transparent images. Without the image filling the corner that connects to the caption my design left the caption floating. To remedy this a soft shade in the background of the image makes the boundary visible.&lt;/p&gt;
&lt;h2&gt;Blockquote&lt;/h2&gt;
&lt;p&gt;Quoting folks is something bloggers do extensively. Most often they use a &lt;code&gt;&amp;lt;blockquote&amp;gt;&lt;/code&gt; to wrap the quoted text to help highlight it as something other than their own words. An indent and rule similar to what I’ve used for figure is a common styling choice.&lt;/p&gt;
&lt;p&gt;A blockquote though, has a distinctly different reason to exist to a figure. A clear visual contrast between the two is warranted. I’ve applied an enlarged curly quote mark as a clear sign post. With a similarly curvy wavy line to delineate the extent of the quoted text.&lt;/p&gt;
&lt;p&gt;To render the wavy line I fiddled with the variables provided by very handy &lt;a href=&quot;https://css-shape.com/wavy-line/&quot;&gt;CSS shape wavy line&lt;/a&gt;. Thank you &lt;a href=&quot;https://github.com/Afif13/&quot;&gt;Temani Afif&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;NetNewsWire lacks a language&lt;/h3&gt;
&lt;p&gt;I planned to allow &lt;a href=&quot;https://www.stefanjudis.com/today-i-learned/how-to-use-language-dependent-quotes-in-css/&quot;&gt;CSS to select the appropriate quote mark&lt;/a&gt; for the language of the post. This idea was stymied by the &lt;a href=&quot;https://github.com/Ranchero-Software/NetNewsWire/issues/4688&quot;&gt;lack of a template &lt;code&gt;lang&lt;/code&gt;&lt;/a&gt; at the time of writing.&lt;/p&gt;
&lt;h2&gt;Associating a citation to a quote&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://heydonworks.com/article/the-blockquote-element/&quot;&gt;As Heydon Pickering explains&lt;/a&gt;, a great way to mark up a blockquote is to use a figure to associate a citation to the quote with a figure and figcaption.&lt;/p&gt;
&lt;p&gt;To pave the path for this great idea I’ve styled this combo so the blockquote styling usurps the figure styling. Extending the wavy line to close to the figcaption beneath the quoted text.&lt;/p&gt;
&lt;h2&gt;Polish&lt;/h2&gt;
&lt;p&gt;Also in this version I have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Defined some missing heading line-heights.&lt;/li&gt;
&lt;li&gt;Adjusted the sizing of h3 and h4 elements.&lt;/li&gt;
&lt;li&gt;Applied a minimal page margin.&lt;/li&gt;
&lt;li&gt;Removed some CSS that was &lt;em&gt;not&lt;/em&gt; hiding unloaded svg sprites.&lt;/li&gt;
&lt;li&gt;Sized the monospace code font to better match the body text.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v9.nnwtheme.zip&quot;&gt;Install: Scratch v9&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v9.zip&quot;&gt;Download: Scratch_v9.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next up&lt;/h2&gt;
&lt;p&gt;A few things I’m considering tackling next, in no particular order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Further refine the display of &lt;code&gt;code&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Make line-height responsive to viewport size.&lt;/li&gt;
&lt;li&gt;Similarly apply some constraint on text measure.&lt;/li&gt;
&lt;li&gt;Have a play with pretty or balanced text-wrapping.&lt;/li&gt;
&lt;li&gt;Polish the display of links.&lt;/li&gt;
&lt;li&gt;Ordered and unordered lists.&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>Scratch – headings</title>
		<link href="https://ollicle.com/2025/jul/27/scratch-headings/"/>
		<updated>2025-07-27T10:46:27Z</updated>
		<id>https://ollicle.com/2025/jul/27/scratch-headings/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Continuing my incremental NetNewsWire theme build. Version 7 (&lt;a href=&quot;https://ollicle.com/2025/jun/21/netnewswire-visited-links/&quot;&gt;The riddle of the NetNewsWire visited link&lt;/a&gt;) made changes to handle feeds with no feed link. This version takes first steps to improve the type.&lt;/p&gt;
&lt;p&gt;Since the last version of Scratch I published, I explored some ideas around typography. Including &lt;a href=&quot;https://ollicle.com/2025/jul/13/has-heading-scales/&quot;&gt;using &lt;code&gt;:has()&lt;/code&gt;&lt;/a&gt; to apply a heading hierarchy dynamically. I’ve used this idea to style headings in the Scratch theme.&lt;/p&gt;
&lt;h2&gt;Font choice&lt;/h2&gt;
&lt;p&gt;The first step was to design the full spread of headings. To help bridge all six levels between &lt;code&gt;H1&lt;/code&gt; and &lt;code&gt;H6&lt;/code&gt; 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;To preserve a simple theme installation I’d rather not ask you to install a font &lt;em&gt;and&lt;/em&gt; a NetNewsWire theme. So system fonts it is.&lt;/p&gt;
&lt;h2&gt;Assigning Apple system fonts with CSS&lt;/h2&gt;
&lt;p&gt;As expected we use the CSS &lt;code&gt;font-family&lt;/code&gt; property. Surprisingly though, using the names of the fonts does not work. Instead we need to use one of a set of keywords.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;font-family: system-ui;&lt;/code&gt; to assign San Franciso&lt;/li&gt;
&lt;li&gt;&lt;code&gt;font-family: ui-serif;&lt;/code&gt; for New York&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h2&gt;Tweaking unicode font features&lt;/h2&gt;
&lt;p&gt;To discover the features available on these fonts I inspected the &lt;a href=&quot;https://v-fonts.com/publishers/apple&quot;&gt;Apple Variable Fonts&lt;/a&gt; page in browser dev tools.&lt;/p&gt;
&lt;p&gt;For example: &lt;code&gt;font-variation-settings: &amp;quot;wght&amp;quot; 400, &amp;quot;opsz&amp;quot; 22, &amp;quot;wdth&amp;quot; 75;&lt;/code&gt; adjusts the weight, optical size and width of San Franciso.&lt;/p&gt;
&lt;p&gt;New York only provides a weight adjustment.&lt;/p&gt;
&lt;h2&gt;Vertical spacing&lt;/h2&gt;
&lt;p&gt;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 &lt;code&gt;rlh&lt;/code&gt; for all line height values. For fine spacing control I’ve used a quarter division of &lt;code&gt;0.25rlh&lt;/code&gt;. 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.&lt;/p&gt;
&lt;h3&gt;Paragraph spacing&lt;/h3&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h3&gt;Margins for visual hierarchy&lt;/h3&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h3&gt;Flattening CSS specificity with &lt;code&gt;@layer&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;To make it easier to override some moderately complicated selectors without complicating them further, I introduced a “base” CSS &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@layer&quot;&gt;&lt;code&gt;@layer&lt;/code&gt;&lt;/a&gt;. Styles outside of a layer override those inside a layer without consideration of specificity.&lt;/p&gt;
&lt;h2&gt;Some polish&lt;/h2&gt;
&lt;h3&gt;What sup with footnote size?&lt;/h3&gt;
&lt;p&gt;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 &lt;code&gt;&amp;lt;sup&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Assigning &lt;code&gt;font-size: inherit;&lt;/code&gt; to &lt;code&gt;&amp;lt;sup&amp;gt;&lt;/code&gt; elements inside &lt;code&gt;a.footnote&lt;/code&gt; elements did the trick.&lt;/p&gt;
&lt;p&gt;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 &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/popover&quot;&gt;popover&lt;/a&gt; to avoid the need for nesting. Especially when the &lt;a href=&quot;https://developer.apple.com/videos/play/wwdc2025/233/&quot;&gt;incoming&lt;/a&gt; anchor positioning support lands.&lt;/p&gt;
&lt;h3&gt;Hiding SVG sprites&lt;/h3&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;svg:has(&amp;gt; use[href^=&amp;quot;#&amp;quot;]:only-child) {
	display: none;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v8.nnwtheme.zip&quot;&gt;Install: Scratch v8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v8.zip&quot;&gt;Download: Scratch_v8.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next up&lt;/h2&gt;
&lt;p&gt;Version 8 demonstrates many clear opportunities for improvement including:&lt;/p&gt;
&lt;h3&gt;Code typography&lt;/h3&gt;
&lt;p&gt;Monospace text could use some love and attention.&lt;/p&gt;
&lt;h3&gt;Variable line-height&lt;/h3&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h3&gt;Horizontal spacing&lt;/h3&gt;
&lt;p&gt;I’m yet to address horizontal spacing of elements such as lists, figures, blockquotes, or the page itself.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Heading scales with :has()</title>
		<link href="https://ollicle.com/2025/jul/13/has-heading-scales/"/>
		<updated>2025-07-13T10:02:54Z</updated>
		<id>https://ollicle.com/2025/jul/13/has-heading-scales/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;The &lt;code&gt;:has()&lt;/code&gt; CSS selector provides us with the means to apply a typographic hierarchy to heading elements dependent on which heading levels are present.&lt;/p&gt;
&lt;p&gt;Justifying the necessary added complexity demands some context.&lt;/p&gt;
&lt;h2&gt;Reading and typography&lt;/h2&gt;
&lt;p&gt;Presuming the website you are designing contains text you want readers to read – your primary job as a typographer is to keep out of the way. Reading requires a flow that is easily interrupted.&lt;/p&gt;
&lt;p&gt;The right breaks in the text however, are vital for reading: New paragraphs provide us an opportunity to take a mental breath; Headings serve as way-markers, slicing the information into meaningful chunks that help us navigate longer text.&lt;/p&gt;
&lt;p&gt;Overly prominent sub-headings in a body of text don’t serve your readers. Unless you are writing about the design of the font, those lovely large characters don’t serve your readers.&lt;/p&gt;
&lt;h2&gt;Relative typographic contrast&lt;/h2&gt;
&lt;p&gt;A visual reader encountering a heading is not concerned with which number in the scale the heading lies any more than they are individually identifying the letters of the words. &lt;em&gt;Relative&lt;/em&gt; contrast is where it is at. A heading is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Distinct from text;&lt;/li&gt;
&lt;li&gt;And &lt;em&gt;lower&lt;/em&gt;, &lt;em&gt;higher&lt;/em&gt;, or of the &lt;em&gt;same&lt;/em&gt; importance as the previous heading.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Well balanced typographic contrast allows readers to discern the hierarchy effortlessly with a minimum of fuss. Constrast between headings ideally balances clarity with cohesion of the whole.&lt;/p&gt;
&lt;h2&gt;The HTML challenge&lt;/h2&gt;
&lt;p&gt;Assigning a specific size and style to each of the HTML heading levels is the customary approach. A simple approach and comes with a tradeoff. A fixed heading level to size association forces us to apply strong visual prominence to higher level headings, on the off chance our heading might need to coexist with a set of deeper level headings.&lt;/p&gt;
&lt;p&gt;A crude example demonstrating &lt;code&gt;font-size&lt;/code&gt; alone to distinguish the ludicrous six levels HTML offers:&lt;/p&gt;
&lt;div&gt;&lt;template shadowrootmode=&quot;open&quot;&gt;
&lt;h1&gt;Heading level one&lt;/h1&gt;
&lt;h2&gt;Heading level two&lt;/h2&gt;
&lt;h3&gt;Heading level three&lt;/h3&gt;
&lt;h4&gt;Heading level four&lt;/h4&gt;
&lt;h5&gt;Heading level five&lt;/h5&gt;
&lt;h6&gt;Heading level six&lt;/h6&gt;
&lt;p&gt;Body text&lt;/p&gt;
&lt;style&gt;
:host{
	background-color: Canvas;
	padding: 2rem;
	&gt; * {
		margin-block: 0;
	}
	&gt; * + * {
		margin-block-start: 1rem;
	}
}
h1,h2,h3,h4,h5,h6 {line-height: 1.2;font-weight: 500}
h1 {font-size: 3.65em}
h2 {font-size: 3em}
h3 {font-size: 2.3em}
h4 {font-size: 1.85em}
h5 {font-size: 1.5em}
h6 {font-size: 1.2em}
&lt;/style&gt;
&lt;/template&gt;&lt;/div&gt;
&lt;p&gt;Defining an appropriate contrast between the text and each of the consecutive heading levels nudges the contrast range into the stratosphere. No wonder the default browser styling sizes &lt;code&gt;h6&lt;/code&gt; significantly smaller than body text.&lt;/p&gt;
&lt;p&gt;Pragmatically, in the vast majority of projects, dropping &lt;code&gt;h6&lt;/code&gt; from typographic considerations will be inconsequential. How about &lt;code&gt;h5&lt;/code&gt;? Fewer levels is always going to be easiest to design. Beware though, adding a level later however, a cause a cascade of rework.&lt;/p&gt;
&lt;h2&gt;Depth shifting the hierarchy&lt;/h2&gt;
&lt;p&gt;For flexibility, instead of (or in addition to) assigning the prescribed styles to the HTML heading elements, we create a set of CSS classes that correspond to the designed hierarchy:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.h1 { … }
.h2 { … }
.h3 { … }
.etc { … }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Should a particular web page not use deeper level headings, we can shift the designed scale. For example, should the page we are concerned with only include &lt;code&gt;h1&lt;/code&gt; through to &lt;code&gt;h3&lt;/code&gt; – we can re-assign the sizes by applying the corresponding classes to each heading.&lt;/p&gt;
&lt;p&gt;By applying classes belonging to an otherwise deeper level heading, we can be assured we’re sticking with the designed heading scale. A subset of the designed scale preserves the contrasts between each heading level step:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Page title&amp;lt;/h1&amp;gt;
&amp;lt;h2 class=&amp;quot;h5&amp;quot;&amp;gt;A small level two heading&amp;lt;/h2&amp;gt;
&amp;lt;h3 class=&amp;quot;h6&amp;quot;&amp;gt;A small level two heading&amp;lt;/h3&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;template shadowrootmode=&quot;open&quot;&gt;
&lt;h1&gt;Page title&lt;/h1&gt;
&lt;h2 class=&quot;h5&quot;&gt;Heading level two&lt;/h2&gt;
&lt;h3 class=&quot;h6&quot;&gt;Heading level three&lt;/h3&gt;
&lt;p&gt;Body text&lt;/p&gt;
&lt;style&gt;
:host{
	background-color: Canvas;
	padding: 2rem;
	&gt; * {
		margin-block: 0;
	}
	&gt; * + * {
		margin-block-start: 1rem;
	}
}
h1,h2,h3,h4,h5,h6 {line-height: 1.2;font-weight: 500}
h1 {font-size: 3.65em}
h2,.h2 {font-size: 3em}
h3,.h3 {font-size: 2.3em}
h4,.h4 {font-size: 1.85em}
h5,.h5 {font-size: 1.5em}
h6,.h6 {font-size: 1.2em}
&lt;/style&gt;
&lt;/template&gt;&lt;/div&gt;
&lt;p&gt;Note I’m not shifting the &lt;code&gt;h1&lt;/code&gt; in this example, instead choosing to keep it consistent between pages as I would expect to be desirable in a multi-page site.&lt;/p&gt;
&lt;h2&gt;Perils of making the wrong things easy&lt;/h2&gt;
&lt;p&gt;The flexibility of assigning classes to individual elements brings new ways to break the heading outline in a page. In particular we can create what appear to be headings, but are nothing of the sort:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&amp;quot;h2&amp;quot;&amp;gt;Looks exactly like a heading&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Element misuse such as this can contribute to a terrible experience for anyone using tools reliant on a page’s accessibility tree. Screen reader users are the usual example.&lt;/p&gt;
&lt;p&gt;Maintaining a well structured outline that doesn’t skip levels in challenging enough in a complex website without adding non-heading headings as an option.&lt;/p&gt;
&lt;p&gt;Of course it may be perfectly appropriate to make some big text that is not a heading (I’m thinking big text in a promotional banner). Naming classes after HTML elements invites misinterpretation by unwary developers.&lt;/p&gt;
&lt;p&gt;Regardless of the class naming convention used, this kind of case-by-case override will likely become the default. You’ll know something it off when you find yourself with a heading size class on every heading element in a page.&lt;/p&gt;
&lt;h2&gt;Using CSS for presentation&lt;/h2&gt;
&lt;p&gt;Shifting the hierarchy is the idea I want to pursue. However, if doing so requires micro managing heading sizes with classes in HTML. I say it is not worth the headaches.&lt;/p&gt;
&lt;p&gt;We can use CSS to apply the heading sizes based on what headings are present.&lt;/p&gt;
&lt;h3&gt;Demo&lt;/h3&gt;
&lt;p&gt;I’ve wired up a little JavaScript to quickly alter which headings are present so we can readily see the applied hierarchy shift accordingly. Try shifting the range input:&lt;/p&gt;
&lt;p&gt;&lt;heading-scale-demo&gt;&lt;template shadowrootmode=&quot;open&quot;&gt;&lt;/template&gt;&lt;/heading-scale-demo&gt;&lt;/p&gt;
&lt;form&gt;
&lt;label for=&quot;depth&quot;&gt;Heading depth&lt;/label&gt;&lt;br /&gt;
&lt;input type=&quot;range&quot; id=&quot;depth&quot; name=&quot;h&quot; min=&quot;1&quot; max=&quot;6&quot; value=&quot;3&quot; /&gt;
&lt;/form&gt;
&lt;div class=&quot;flow hroot&quot;&gt;&lt;/div&gt;
&lt;template id=&quot;headings&quot;&gt;
&lt;h1&gt;Heading level one&lt;/h1&gt;
&lt;h2&gt;Heading level two&lt;/h2&gt;
&lt;h3&gt;Heading level three&lt;/h3&gt;
&lt;h4&gt;Heading level four&lt;/h4&gt;
&lt;h5&gt;Heading level five&lt;/h5&gt;
&lt;h6&gt;Heading level six&lt;/h6&gt;
&lt;p&gt;Body text&lt;/p&gt;
&lt;/template&gt;
&lt;style&gt;
:host {
	--f2-size: 3em;
	--f3-size: 2.3em;
	--f4-size: 1.85em;
	--f5-size: 1.5em;
	--f6-size: 1.2em;
}
h1 {font-size: 3.65em}
h2,h3,h4,h5,h6 {
	font-size: var(--f6-size);
}
.hroot {
	&amp;:has(h3) h2,
	&amp;:has(h4) h3,
	&amp;:has(h5) h4,
	&amp;:has(h6) h5 {
		font-size: var(--f5-size);
	}
	&amp;:has(h4) h2,
	&amp;:has(h5) h3,
	&amp;:has(h6) h4 {
		font-size: var(--f4-size);
	}
	&amp;:has(h5) h2,
	&amp;:has(h6) h3 {
		font-size: var(--f3-size);
	}
	&amp;:has(h6) h2 {
		font-size: var(--f2-size);
	}
}
h1,h2,h3,h4,h5,h6 {line-height: 1.2;font-weight: 500}
input {inline-size: 100%}
:host{
	display: block;
	background-color: Canvas;
	padding: 2rem;
}
.flow {
	&gt; * {
		margin-block: 0;
	}
	&gt; * + * {
		margin-block-start: 1rem;
	}
}
&lt;/style&gt;
&lt;script&gt;
class HeadingScaleDemo extends HTMLElement {
	connectedCallback() {
		this.form.addEventListener(&quot;input&quot;, this.updateHTML.bind(this));
		this.updateHTML();
	}
	get hroot() {
		return this.shadowRoot.querySelector(&quot;.hroot&quot;);
	}
	get form() {
		return this.shadowRoot.querySelector(&quot;form&quot;);
	}
	get depth() {
		const formData = new FormData(this.form);
		return +formData.get(&quot;h&quot;);
	}
	get template() {
		return this.shadowRoot.getElementById(&quot;headings&quot;);
	}
	depthSelector() {
		const hn = [&quot;h1&quot;,&quot;h2&quot;,&quot;h3&quot;,&quot;h4&quot;,&quot;h5&quot;,&quot;h6&quot;];
		return hn.slice(0, this.depth).join(&quot;,&quot;);
	}
	updateHTML() {
		const all = this.template.content.cloneNode(true);
		const selected = Array.from(all.children).filter((el)=&gt;{
			return el.matches(`p,${this.depthSelector()}`);
		});
		this.hroot.replaceChildren(...selected);
	}
}
customElements.define(&quot;heading-scale-demo&quot;, HeadingScaleDemo);
&lt;/script&gt;

&lt;h3&gt;The pertinent CSS&lt;/h3&gt;
&lt;p&gt;The first layer of the abstraction is a set of variables in place of the classes we created for the previous example. The variable names could be based on the heading element names if doing so didn’t make me itch:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:root {
	--f1-size: 3.65em;
	--f2-size: 3em;
	--f3-size: 2.3em;
	--f4-size: 1.85em;
	--f5-size: 1.5em;
	--f6-size: 1.2em;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As mentioned earlier I’m keeping &lt;code&gt;h1&lt;/code&gt; consistent. The other headings all have the least prominent size assigned as a base:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;h1 {
	font-size: var(--f1-size);
}
h2,h3,h4,h5,h6 {
	font-size: var(--f6-size);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The promised, the overrides use the &lt;code&gt;:has()&lt;/code&gt; selector applied to a parent element:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.hroot {
	&amp;amp;:has(h3) h2,
	&amp;amp;:has(h4) h3,
	&amp;amp;:has(h5) h4,
	&amp;amp;:has(h6) h5 {
		font-size: var(--f5-size);
	}
	&amp;amp;:has(h4) h2,
	&amp;amp;:has(h5) h3,
	&amp;amp;:has(h6) h4 {
		font-size: var(--f4-size);
	}
	&amp;amp;:has(h5) h2,
	&amp;amp;:has(h6) h3 {
		font-size: var(--f3-size);
	}
	&amp;amp;:has(h6) h2 {
		font-size: var(--f2-size);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not much code! Mostly because this example only twiddles font size. A designed implementation would likely want to adjust a fuller set of properties. For example, the space around a heading goes a long way to denote it’s relative importance. Especially if the designed scale is six levels deep!&lt;/p&gt;
&lt;h2&gt;Future scope and nesting&lt;/h2&gt;
&lt;p&gt;By thoughtfully placing the &lt;code&gt;hroot&lt;/code&gt; class, creating multiple heading scale contexts becomes trivial. These tend to be crop up in the various boxes in a complex website. As the exceptions that are usually responsible for upsetting a plan to simply assign heading sizes directly, these contexts are the chief cause for my interest in this approach.&lt;/p&gt;
&lt;p&gt;The missing facet in what I have outlined above is nesting. Dealing with nesting of these contexts is more complicated and no less common in a complex website design. Without the experience of applying this approach in a complete and serious website build I feel less inclined to attempt to advocated for it as a strategy.&lt;/p&gt;
&lt;p&gt;I’ve had some experimental success using &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@scope&quot;&gt;&lt;code&gt;@scope&lt;/code&gt;&lt;/a&gt;. Fortunately we can look forward to broad support of &lt;code&gt;@scope&lt;/code&gt; relatively soon. As a component of &lt;a href=&quot;https://wpt.fyi/interop-2025&quot;&gt;Interop 2025&lt;/a&gt;, Firefox ought to catch up in the coming year.&lt;/p&gt;
&lt;h2&gt;Back to reality&lt;/h2&gt;
&lt;p&gt;Is this idea useful? I don’t know yet, but I’ll be looking for opportunities to try it in the next new site design I encounter. This site would be an obvious place to start, but hardly a substantial test.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>The riddle of the NetNewsWire visited link</title>
		<link href="https://ollicle.com/2025/jun/21/netnewswire-visited-links/"/>
		<updated>2025-06-21T07:54:31Z</updated>
		<id>https://ollicle.com/2025/jun/21/netnewswire-visited-links/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Past me is a fool. He spent a portion of my limited lifetime supply of keypresses on the colour choice of visited links in &lt;a href=&quot;https://ollicle.com/2025/may/04/scratch-text-colour/&quot;&gt;a NetNewsWire theme&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In case you haven’t caught on (I forgive us), NetNewsWire is &lt;em&gt;not a browser&lt;/em&gt;. It displays some HTML in a web view. This content, extracted from an XML file, usually includes links. Links are &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; elements with a &lt;code&gt;:visited&lt;/code&gt; state. Logical right? Not quite. It didn’t cross the  code-addled mind of past me that &lt;strong&gt;NetNewsWire never visits web pages&lt;/strong&gt;. How do you get a visited link without the visit!&lt;/p&gt;
&lt;p&gt;The thing is… I &lt;em&gt;was&lt;/em&gt; seeing visited links in NetNewsWire. I was &lt;em&gt;styling&lt;/em&gt; visited links. Definitely visited. In the colour I assigned to &lt;code&gt;a:visited&lt;/code&gt;. In the theme I had installed. But how? What is going on?&lt;/p&gt;
&lt;p&gt;To avoid unnecessary embarrassment I won’t mention some of the (fortunately shallow) irrational rabbit holes I looked in first. The important clue was &lt;em&gt;where&lt;/em&gt; the visited links were appearing. Only in some feeds, and only adorning the &lt;strong&gt;feed link title&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This is the bit where I plug the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/template-variables/&quot;&gt;Template variable NetNewsWire theme&lt;/a&gt;. Necessary because NetNewsWire does not have dev tools enabled in it’s web view (I remember the web before Firebug – it was not pretty). Anyway…&lt;/p&gt;
&lt;p&gt;Turns out, the feeds displaying the :visited feed link title. &lt;em&gt;Did not have a feed link&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Of course there was a link! I can see it. If I click it, my browser opens the blog post on the web. That is confusing. I know. I was confused too, for a moment at least. I’ll try to explain because when I understood I laughed.&lt;/p&gt;
&lt;p&gt;This is the pertinent portion of template before NetNewsWire renders the page:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;a href=&amp;quot;[[feed_link]]&amp;quot;&amp;gt;[[feed_link_title]]&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NetNewsWire, to render a feed item, replaces tokens in the template. A feed item with no feed link might result in this perfectly valid link.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;a href=&amp;quot;&amp;quot;&amp;gt;A curiously visited link&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here it is rendered in this page: &lt;a href=&quot;https://ollicle.com/2025/jun/21/netnewswire-visited-links/&quot;&gt;A curiously visited link&lt;/a&gt;. Give it a click. You’ll find it reloads the page, because it is a link to the &lt;em&gt;current page&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Which of course you’ve visited. &lt;a href=&quot;https://www.youtube.com/watch?v=qZowK0NAvig&quot;&gt;As a matter of fact, you’re there right now&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But, but, that’s not what happens when I click the “visited” links in NetNewsWire. It loads the feed item’s page on the web, past me might have said.&lt;/p&gt;
&lt;p&gt;This is explained by the presence of a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/base&quot;&gt;base&lt;/a&gt; tag in the template in which the link is rendered.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The base URL to be used throughout the document for relative URLs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;NetNewsWire assigns the feed item’s “preferred link” to this URL. As a result, empty links, relative to the base link, effectively &lt;em&gt;become&lt;/em&gt; the base link. That is, a link to the blog post NetNewsWire has rendered.&lt;/p&gt;
&lt;h2&gt;Scratch theme update&lt;/h2&gt;
&lt;p&gt;Now I know what’s going on, I’ll change &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch&lt;/a&gt; to display feed items in feeds lacking feed links a little differently.&lt;/p&gt;
&lt;p&gt;Despite the empty link kinda working, it is at very least surprising. If a feed doesn’t have a feed link, I reckon it makes more sense to display the feed title unlinked. If anything it is redundant alongside the title with the same link.&lt;/p&gt;
&lt;p&gt;To apply this logic without relying on JavaScript, I’ve applied a similar trick already used in the &lt;a href=&quot;https://ollicle.com/2025/apr/25/scratch-template/&quot;&gt;theme template&lt;/a&gt; to handle missing titles. Repeating the feed title in a span displayed in place of the link when the &lt;code&gt;href&lt;/code&gt; is empty.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;a href=&amp;quot;[[feed_link]]&amp;quot;&amp;gt;[[feed_link_title]]&amp;lt;/a&amp;gt;&amp;lt;span&amp;gt;[[feed_link_title]]&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The CSS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;header a + span,
header a[href=&amp;quot;&amp;quot;] {
	display: none;
}

header a[href=&amp;quot;&amp;quot;] + span {
	display: inline;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While I was at it I ensured &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt; tags scaled like video; And, of course, deleted the visited colour.&lt;/p&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v7.nnwtheme.zip&quot;&gt;Install: Scratch v7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v7.zip&quot;&gt;Download: Scratch_v7.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next up&lt;/h2&gt;
&lt;p&gt;I’ve been side tracked by a baseline grid, taking advantage of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/text-box&quot;&gt;text-box&lt;/a&gt;. Not sure where it is going yet.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Scratch – tables</title>
		<link href="https://ollicle.com/2025/jun/09/scratch-tables/"/>
		<updated>2025-06-09T06:48:25Z</updated>
		<id>https://ollicle.com/2025/jun/09/scratch-tables/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Continuing my incremental NetNewsWire theme build. Version 5 &lt;a href=&quot;https://ollicle.com/2025/jun/06/scratch-footnotes/&quot;&gt;Scratch – footnotes&lt;/a&gt; styled NetNewsWire footnotes. Time for tables! And as a side mission an overflow indicator experiment.&lt;/p&gt;
&lt;h2&gt;Minimal tables&lt;/h2&gt;
&lt;p&gt;One size fits all table styling is always going to leave much to be desired. CSS alone provides no way to introspect the text in a cell, so responding to the type of data is not an option. We might otherwise want to alter the alignment or apply a suitable minimum cell width.&lt;/p&gt;
&lt;p&gt;It’s on the to-do list, but I’m yet to cater for &lt;code&gt;&amp;lt;caption&amp;gt;&lt;/code&gt;. Most tables ought to have one! Perhaps, when I’m feeling it, I’ll build a simple 11ty site to generate RSS feeds for the purpose of testing content including some table variants.&lt;/p&gt;
&lt;p&gt;As it stands, my testing is constrained to a few tables in feeds I chanced upon that are sans-caption.&lt;/p&gt;
&lt;h2&gt;Table styling&lt;/h2&gt;
&lt;p&gt;The approach I’ve taken is not radically different to the default NetNewsWire theme. Borders are limited to between rows, using consistent text alignment and white space to hold the columns together.&lt;/p&gt;
&lt;p&gt;As the values in the first column are often row labels they are aligned right to hug the row they are labelling. If these styles were for my tables, I would make this alignment exclusive to &lt;code&gt;&amp;lt;th&amp;gt;&lt;/code&gt; within &lt;code&gt;&amp;lt;tbody&amp;gt;&lt;/code&gt;. People seldom go to the trouble of designating their row headers, so I’m going with the flow.&lt;/p&gt;
&lt;h2&gt;Space units&lt;/h2&gt;
&lt;p&gt;Horizontal space tends to be constrained in tables, so padding is reserved for between cells to minimise width. For horizontal space I’ve used &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/length#ch&quot;&gt;&lt;code&gt;ch&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/length#ex&quot;&gt;&lt;code&gt;ex&lt;/code&gt;&lt;/a&gt; for vertical space. So that the spacing might to respond to the proportions of the assigned typeface.&lt;/p&gt;
&lt;p&gt;A more nuanced solution, for vertical space in particular, could involve a calc incorporating  &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/length#cap&quot;&gt;&lt;code&gt;cap&lt;/code&gt;&lt;/a&gt; and perhaps
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/length#lh&quot;&gt;&lt;code&gt;lh&lt;/code&gt;&lt;/a&gt; to take into account the variety of white space different typefaces incorporate in their metrics.&lt;/p&gt;
&lt;p&gt;For now I’m still looking at Times and perfection can wait.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;table {
	border-collapse: collapse;
	font-size: inherit;
}

th,td {
	overflow-wrap: normal;
	border-style: none;
	border-block-end: var(--rule-width) solid var(--rule-color);
	text-align: left;
	
	&amp;amp;:first-child {
		text-align: right;
	}
	
	&amp;amp;:not(:last-child) {
		padding-inline-end: 2ch;
	}
	
	thead &amp;amp; {
		padding-block-end: 1ex;
		vertical-align: bottom;
	}
	
	tfoot &amp;amp;,
	tbody &amp;amp; {
		padding-block: 1ex;
		vertical-align: top;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Overflow&lt;/h2&gt;
&lt;p&gt;Table layouts had a few years (too long) in the sun before mobile phones brought their particularly little screens to the web. There are a few approaches to making tables respond to a narrow viewport and most of them are overcomplicated and often harmful to accessibility. The simplest solution which NetNewsWire adopts remains the best. If a table is too wide, let it scroll horizontally.&lt;/p&gt;
&lt;p&gt;NetNewsWire bakes in JavaScript to wrap tables in a div (with a class of &lt;code&gt;nnw-overflow&lt;/code&gt;) to facilitate a horizontal scroll.&lt;/p&gt;
&lt;p&gt;The cell content will wrap (to a possibly uncomfortable degree) before the table will create a scroll-bar. We could mitigate this by applying a minimum cell width. However, I choose the side of keeping data tables with short text values compact.&lt;/p&gt;
&lt;p&gt;It is definitely worth overriding the earlier added &lt;code&gt;overflow-wrap: anywhere;&lt;/code&gt;. Applied to squashed tables would cause the words to be smeared across lines.&lt;/p&gt;
&lt;p&gt;The default table sizing algorithm assigns more width to columns with more text. In the circumstance where we have no control over the HTML it is best to avoid getting in the way by trying to guess widths.&lt;/p&gt;
&lt;p&gt;Take this as your reminder that HTML tables are a poor choice for lots of text.&lt;/p&gt;
&lt;h2&gt;Reinventing overflow indicators&lt;/h2&gt;
&lt;p&gt;In addition to being too wide, tables are often too tall. One of the knock on effects of this is the indication that there is horizontal cropping occurring may not be visible until you’ve scrolled far enough to see the scroll-bar at the bottom of the table. Visibly cropped text is a good indicator, but it doesn’t help when the edge of a table column happens to fall aligned with the edge of the viewport.&lt;/p&gt;
&lt;p&gt;The most popular, and wonderfully clever, solution to this problem is to apply a shadow to the edge of the overflowing content. With some crafty use of &lt;code&gt;background-image&lt;/code&gt; and &lt;code&gt;background-attachment&lt;/code&gt; (that I won’t explain here) no JavaScript is required to have the shadow only present when content is hidden.&lt;/p&gt;
&lt;p&gt;However, this physical metaphor loses some intuitive immediacy in dark mode. I took this as excuse enough to experiment with an alternative.&lt;/p&gt;
&lt;p&gt;Using the same overlapping backgrounds approach, instead of a shadow, I’m rendering an ellipsis like symbol (…) at the top of the overflowing container – above the corner of cropping side.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.nnw-overflow {
	padding-block-start: 0.5em;
	max-width: 100%;
	overflow-x: auto;
	overscroll-behavior-inline: none;
	--dot: radial-gradient(
		circle at center, 
		var(--text-color) 0, 
		var(--text-color) 70%,
		transparent 70%);
	--d-size: .3rem .3rem;
	background-image:
		/* Cover left */
		linear-gradient(
			to right, Canvas 50%, transparent
		),
		/* Cover right */
		linear-gradient(
			to left, Canvas 50%, transparent
		),
		/* Dots */
    	var(--dot),var(--dot),var(--dot),
    	var(--dot),var(--dot),var(--dot);
	background-size: 4rem 100%, 4rem 100%,
		var(--d-size), var(--d-size), var(--d-size),
		var(--d-size), var(--d-size), var(--d-size);
	background-position: left, right,
		top left, top left 0.5rem, top left 1rem,
		top right, top right 0.5rem, top right 1rem;
	background-repeat: no-repeat;
	background-attachment: local, local,
		scroll, scroll, scroll,
		scroll, scroll, scroll;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Worth mentioning the use of &lt;code&gt;overscroll-behavior-inline&lt;/code&gt;. The over-scrolling bounce effect spoilt the magic somewhat by revealing the dots when scrolling beyond the extent of the content. This property specifically prevents the horizontal scroll bounce while allowing vertical scrolling to function normally.&lt;/p&gt;
&lt;p&gt;These dots are not as familiar as a nice shadow. They are visually robust though – working equally well in and light and dark mode.&lt;/p&gt;
&lt;p&gt;Whether or not people will intuitively read the dots as a scroll indicator remains to be seen. Keeping the dots tight to the content will hopefully help distinguish them from a menu button. Maybe within the context of a NetNewsWire theme I’ll get away with it. Let me know what you think.&lt;/p&gt;
&lt;p&gt;I’m happy enough with the effect to apply it to &lt;code&gt;pre&lt;/code&gt; tags too in Scratch.&lt;/p&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v6.nnwtheme.zip&quot;&gt;Install: Scratch v6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v6.zip&quot;&gt;Download: Scratch_v6.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next up&lt;/h2&gt;
&lt;p&gt;I’ve been pondering a somewhat novel idea for handling heading hierarchy I’m keen to try.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Scratch – footnotes</title>
		<link href="https://ollicle.com/2025/jun/06/scratch-footnotes/"/>
		<updated>2025-06-06T08:40:01Z</updated>
		<id>https://ollicle.com/2025/jun/06/scratch-footnotes/</id>
		<author>
			<name>Oliver Boermans</name>
			<uri>https://ollicle.com/about-oliver-boermans/</uri>
		</author>
		<content type="html">&lt;p&gt;Continuing my incremental NetNewsWire theme build. Version 4 &lt;a href=&quot;https://ollicle.com/2025/may/24/scratch-overflow/&quot;&gt;Scratch – overflow&lt;/a&gt; handles styling to prevent the common causes of content horizontal overflow. Version 5 digs into styling NetNewsWire’s popover footnote implementation.&lt;/p&gt;
&lt;h2&gt;NetNewsWire footnotes&lt;/h2&gt;
&lt;p&gt;Along with some core CSS, NetNewsWire injects a little JavaScript. One of the functions of this code is to enhance footnotes that follow the requisite pattern. Displaying the referenced content in an in-place popover when the anchor is clicked. Saving us the effort of scrolling up and down to read the referenced text.&lt;/p&gt;
&lt;p&gt;The inline footnote anchors are wrapped in a div to provide a positioning context for the referenced footnote:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&amp;quot;newsfoot-footnote-container&amp;quot;&amp;gt;
	&amp;lt;a href=&amp;quot;#fn:000&amp;quot; class=&amp;quot;footnote&amp;quot;&amp;gt;1&amp;lt;/a&amp;gt;
	&amp;lt;div class=&amp;quot;newsfoot-footnote-popover&amp;quot;&amp;gt;
		&amp;lt;div class=&amp;quot;newsfoot-footnote-popover-arrow&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
		&amp;lt;div class=&amp;quot;newsfoot-footnote-popover-inner&amp;quot;&amp;gt;
			&amp;lt;!-- Footnote content --&amp;gt;
		&amp;lt;/div&amp;gt;
	&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The anchors&lt;/h2&gt;
&lt;p&gt;Typically a digit wrapped in a link to the footer note. NetNewsWire bakes in some core CSS to style these as little capsule buttons. These styles are readily overridden. For now I’m sticking with the providing the colour as appropriate for a theme.&lt;/p&gt;
&lt;p&gt;To ensure a little space between the anchor and the preceding text, I applied a little left margin to the container div. This got a little complicated when I realised &lt;em&gt;the container div is not inserted until you click the link&lt;/em&gt;. Making the anchor visibly jump on click.&lt;/p&gt;
&lt;p&gt;Remedy: add the margin to both the anchor and the container – removing the anchor margin when it was wrapped.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:root {
	--footnote-margin: 0.3rem;
}

.newsfoot-footnote-container {
	margin-inline-start: var(--footnote-margin);
	--contained: 0;
}

a.footnote {
	color: Canvas;
	background-color: var(--link-color);
	margin-inline-start: var(--contained, var(--footnote-margin));
	font-weight: bold;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Text and link colour variable refactor&lt;/h2&gt;
&lt;p&gt;Applying the link colour to the footnote anchor background provided cause for a light refactor to make it a variable.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:root {
	color-scheme: light dark;
	--text-color-contrast: 65%;
	--link-color-contrast: 75%;
	
	--text-color: color-mix(in oklab, CanvasText var(--text-color-contrast), Canvas);
	--link-color: color-mix(in oklab, CanvasText var(--link-color-contrast), Canvas);
	--visited-link-color: oklch(50.3% 0.282 295);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Mistakes made&lt;/h2&gt;
&lt;p&gt;Attempting to style the footnotes I realised I had messed up.&lt;/p&gt;
&lt;p&gt;Drunk on the power of a clean CSS selector; I had applied the nuclear option in &lt;a href=&quot;https://ollicle.com/2025/may/24/scratch-overflow/&quot;&gt;version 4&lt;/a&gt; – negating inline styles on divs and spans. Doing so removed the author’s inline styles, while also making footnotes difficult to style without a reciprocal !important escalation.&lt;/p&gt;
&lt;p&gt;To enable the footnotes to be positioned it was necessary to tighten the beam and direct it away from our footnote divs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.articleBody {
	span[style],
	div[style]:not([class^=&amp;quot;newsfoot&amp;quot;]) {
		all: revert !important;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The popovers&lt;/h2&gt;
&lt;p&gt;Like the anchors, the core NNW CSS for popovers leaves colours for the theme. The three divs overlap to simplify the CSS necessary to make the speech bubble style.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.newsfoot-footnote-popover {
	padding-inline: 0;
	border: solid 0.125em currentColor;
	background-color: Canvas;
}

.newsfoot-footnote-popover-arrow {
	display: block;
	background-color: Canvas;
	outline: solid 0.125em currentColor;
	outline-offset: -0.0625em;
}

.newsfoot-footnote-popover-inner {
	background-color: Canvas;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The arrow is a rotated positioned square tucked between the other two divs.&lt;/p&gt;
&lt;p&gt;A too-wide arrow can look broken when the anchor is against the right hand edge. Using outline with outline offset provides a little additional control over how the arrow point is drawn.&lt;/p&gt;
&lt;p&gt;I had to &lt;code&gt;display:block&lt;/code&gt; it for &lt;em&gt;reasons&lt;/em&gt;…&lt;/p&gt;
&lt;h2&gt;More regret&lt;/h2&gt;
&lt;p&gt;It took me a moment to realise the popover arrow was not displaying because it was one of those empty decorative divs I had explicitly hidden. Reducing the specificity of the &lt;code&gt;:empty&lt;/code&gt; selector to ease the override, hence &lt;code&gt;display:block&lt;/code&gt; above.&lt;/p&gt;
&lt;p&gt;Hid empty paragraphs too while I was at it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:is(p,div):where(:empty) {
	display: none;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If these styles continue to prove troublesome I’ll consider removing them altogether. I’m overstating the mistakes and regrets for forced drama. This is an iterative push pull process.&lt;/p&gt;
&lt;h2&gt;The shrinking nested paragraph mystery&lt;/h2&gt;
&lt;p&gt;All the themes I’ve checked present footnote popover text smaller than the surrounding body text. I can imagine this being deliberate, but I’ve found no explicit cause for the size shift.&lt;/p&gt;
&lt;p&gt;For now I’m fudging it with this cursed code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;p p {
	font-size: 120%;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Another case of small svg intent&lt;/h2&gt;
&lt;p&gt;I’m punting on the subject of a figure being more likely to be the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; than the &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; if both a present.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;figure:has(img) svg,
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Install&lt;/h2&gt;
&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;netnewswire://theme/add?url=https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch_v5.nnwtheme.zip&quot;&gt;Install: Scratch v5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ollicle/nnw-ollicle-scratch/raw/main/dist/Scratch.nnwtheme_v5.zip&quot;&gt;Download: Scratch_v5.nnwtheme.zip&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Get the latest version on the &lt;a href=&quot;https://ollicle.com/projects/netnewswire/scratch/&quot;&gt;Scratch project page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next up&lt;/h2&gt;
&lt;p&gt;Maybe version 6 will tackle tables. No promises.&lt;/p&gt;
</content>
	</entry>
</feed>
