Oli Warner's BlogLatest posts from Oli Warner2022-07-20T00:00:00Zhttps://thepcspy.com/Oli WarnerSave £23,265 with *one weird trick!*2022-07-20T00:00:00Zhttps://thepcspy.com/read/ten-years-23k-saved/<p>Tobacconists hate him.</p>
<p>Tobacconists hate him.</p>
<p>It’s that time of the year. I never really know who this sort of post is <em>for</em>. Maybe it’s for you, maybe for it’s for me one dark day in the future, but…</p>
<h2 id="%F0%9F%8E%89-i-stopped-smoking-ten-years-ago!" tabindex="-1">🎉 <a href="https://thepcspy.com/read/breaking-the-habit/">I stopped smoking</a> <em><strong>ten years</strong></em> ago!</h2>
<p>If somebody as flimsy-willed as me can stop smoking, <em><strong>you can stop smoking too</strong></em>. I’m not going to labour the “it kills you” thing, but it is so here’s the financial breakdown for any fellow cheapskates.</p>
<div class="rim">
<pre class="language-text"><code class="language-text"> 10 years = 3,652 days<br /> @13/day = 47,476 cigs<br /> = 2,374 packs<br /><br />2012 price = £7.10 /pack<br />2022 price = £12.50 /pack<br />Mean price = £9.80 /pack</code></pre>
</div>
<p>I’ve not smoked <strong>£23,265.20</strong>.</p>
<p>If I’d regularly deposited that into an investment account, a 2% return that would be £25k and 5% would be almost £30k.</p>
<p>I’d say I feel fantastic but I <em>am</em> also ten years older. I gained two children a dog, and everything hurts. <strong>But I don’t smoke</strong>. I don’t feel the urge to smoke, and haven’t for years. I never have to stand outdoors on cold, wet nights to smoke. I don’t panic when I’m running out of cigarettes. And that means a lot.</p>
<h2 id="it%E2%80%99s-easier-to-just-not-smoke" tabindex="-1">It’s easier to <em>just not smoke</em></h2>
<p>You might not be convinced and that’s because we’re all told <em>it’s really hard to stop smoking</em>. All the time. Even by people who want smokers to quit, as if it’s something that takes a run-up, an intake of bravery and team-cajoling. It’s not hard; just stop smoking the bloody things.</p>
<p>The rest is understanding your body and addiction, that smoking never made you feel better, it only made <em>not smoking</em> feel worse. As soon as you cut that cycle, your body recalibrates. As soon as you realise that, the infinitesimal cost of quitting seems worth it.</p>
<p>If you’re trying to quit and you’re not finding it easy, stick with it. If you need help understanding addiction, <a href="https://www.amazon.co.uk/dp/0615482155">Allen Carr’s Easy Way to Stop Smoking</a> has an eerily convincing narrative that plods through the feelings every smoker goes through. I never finished it —I convinced myself I didn’t want to quit— but it was absolutely the basis for the voice in my head that let me quit later on.</p>
Goodbye Internet Explorer2022-06-15T00:00:00Zhttps://thepcspy.com/read/goodbye-internet-explorer/<p>But what will people download Chrome with now?</p>
<p>But what will people download Chrome with now?</p>
<p>Raise a glass, kiss your wife, hug your children. It’s finally gone.</p>
<figure style="float:left; margin:0 1rem 1rem -100px; shape-outside:url(ie11.svg); shape-margin: 1rem" data-type="image"><img src="https://thepcspy.com/read/goodbye-internet-explorer/ie11.svg" alt="IE11 Logo" width="300" height="299" loading="lazy" decoding="async" /></figure>
<h2 id="it%E2%80%99s-dead." tabindex="-1">It’s dead.</h2>
<p>Internet Explorer has been dying for an age. 15 years ago <a href="https://thepcspy.com/read/ie6-usage-is-dropping-like-a-stone/">IE6 finally bit it</a>, 8 years ago I was calling for webdevs to <a href="https://thepcspy.com/read/time-to-bury-ie8/">hasten the death of IE8</a> and today is the day that Microsoft has <em>finally</em> <s>pulled regular support for</s> <a href="https://techcommunity.microsoft.com/t5/windows-it-pro-blog/internet-explorer-11-desktop-app-retirement-faq/"><em>“retired”</em> Internet Explorer 11</a>, last of its name.</p>
<p>Its successor, Edge, uses Chrome’s renderer. While I’m sure we’ll have a long chat about the problems of monocultures one day, this means —<em>for now</em>— we can really focus on modern standards without having to worry about what this 9 year old renderer thinks. And I mean that at a commercial, enterprise level. Use <code>display: grid</code> without fallback code. Use ES6 features without Babel transpiling everything. <strong>Go, <em>create something</em> and expect it to just work.</strong></p>
<p>Here’s to never having to download the multi-gigabyte, 90 day Internet Explorer test machine images. Here’s to kicking out swathes of compat code. Here’s to being able to [fairly] rigourously test a website locally without a third party running a dozen versions of Windows.</p>
<p>The web is more free for this. <em><strong>Rejoice!</strong></em> while it lasts.</p>
Turning my sites up to Eleven-ty2022-06-12T00:00:00Zhttps://thepcspy.com/read/turning-it-up-to-11ty/<p>This site is now powered by a static site generator called <a href="https://www.11ty.dev/">11ty</a>. <strong>It’s awesome!</strong> I’ll try to explain some of my favourite things about it and reasons you might prefer it to stalwarts in the <abbr title="Static Site Generator">SSG</abbr> arena.</p>
<p>This site is now powered by a static site generator called <a href="https://www.11ty.dev/">11ty</a>. <strong>It’s awesome!</strong> I’ll try to explain some of my favourite things about it and reasons you might prefer it to stalwarts in the <abbr title="Static Site Generator">SSG</abbr> arena.</p>
<figure class="nobg" style="float:left; margin:3rem 1rem 1rem -100px; shape-outside:url(up-to-11.svg); shape-margin: 1.5rem" data-type="image"><img src="https://thepcspy.com/read/turning-it-up-to-11ty/up-to-11.svg" alt="Volume knob that goes to 11" style="min-width:350px" loading="lazy" decoding="async" /></figure>
<p>15 years ago, training up on Django, I built a blog. It’s what webdevs did back then. It was much faster than Wordpress but the editing always fell short and the database design got in the way more than it helped. <a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food">Dogfooding</a> your software means <strong>every problem is yours</strong>. I had a glossy coat but the jelly and chunks arrested my writing process.</p>
<h2 id="ssgs-are-perfect-for-blogs-and-brochure-websites" tabindex="-1"><abbr title="Static Site Generators">SSGs</abbr> are perfect for blogs and brochure websites</h2>
<p>Static site generators churn content through templates into a static website that you can just upload to a simple webserver. This is unlike Django or any other dynamic language, where you host <em>a running process</em> and database on an expensive server 24/7 to generate HTML on demand. You’re just serving files, <a href="https://pages.cloudflare.com/">for free</a>.</p>
<p>Most sites don’t need fresh fresh HTML for every request. They don’t change often enough. A blog or a business’ brochure website might get updates anywhere from a couple of times a day to only once or twice a year. With a static site generator, you can make your edits and regenerate the site.</p>
<p>It’s also secure. There’s nothing to hack running on my domain like there might be in a Wordpress install. There’s no database to run injection attacks against. There’s no indication where the source is hosted. Cloudflare assumes much of liability <em>for me</em> (as well as the buildchain) and if I’m worried about them, it only costs me 20 minutes messing around with DNS to move to another host.</p>
<p>I’ve used a few <abbr title="Static Site Generators">SSGs</abbr> professionally: <a href="https://jekyllrb.com/">Jekyll</a>, <a href="https://gohugo.io/">Hugo</a> and <a href="https://nuxtjs.org/">Nuxt</a>.</p>
<h2 id="why-pick-11ty-over-those%3F" tabindex="-1">Why pick <a href="https://www.11ty.dev/">11ty</a> over those?</h2>
<figure class="rim" data-type="image"><img src="https://thepcspy.com/read/turning-it-up-to-11ty/11ty.svg" alt="11ty logo" loading="lazy" decoding="async" /></figure>
<p>Jekyll is glacial on Cloudflare’s <a href="https://en.wikipedia.org/wiki/CI/CD" title="Continuous Integration and Continuous Deployment">CI/CD environment</a>; about 3 minutes a build. Hugo is <em>Fast</em> but can be a nightmare to work with when things go wrong. Absolutely user-error, but I’ve wasted days at a time banging my head on Hugo. Both Jekyll and Hugo being non-JS options have their own take on asset management. I’m also a Vue developer so Nuxt is great <em>for me</em>, but force-feeding users a bundle of Vue, Nuxt and routers and whatnot, just for a blog? It’s silly. It does have top-shelf asset management though.</p>
<p>11ty was a perfect balance between Hugo and Nuxt. I get all my favourite frontend tools (PostCSS, PurgeCSS on here) with a generator that isn’t trying to force-feed my users a massive script bundle.</p>
<p>More, <em>I get to pick</em> the markup language I write in. I can use Markdown, Liquid, Handlebars, Nunjucks, Moustache, and many, many more. Even plain old HTML, or a mix. I can bundle images with the blog posts (like Hugo leaf bundles). I can paint extra styles on the page if I want to.</p>
<p><strong>I have freedom.</strong> I can do anything, on any page.</p>
<p>It’s been 3 weeks, 2 days since my initial commit on <a href="https://thepcspy.com/">this site</a>’s repo and since finishing the conversion I’ve written more posts than I did in the previous decade, and I’ve also converted two Jekyll sites over too. Each took about an afternoon. Perfect URL parity, nothing ostensibly different, just a [much] better toolchain.</p>
<p>What took longest was editing and upgrading 285 blog posts, spanning back to the early Naughties.</p>
<h2 id="fast-enough%E2%84%A2-for-developers" tabindex="-1">Fast Enough™ for developers</h2>
<p>Build performance only matters <em>to a point</em>. On this <em>seven year old</em> laptop, 11ty generates this whole blog, 400 pages, in well under two seconds:</p>
<pre><code>Copied 403 files / Wrote 539 files in 1.46 seconds (2.7ms each, v1.0.1)
</code></pre>
<p>It’s a second faster on my desktop, and on a real 23 page brochure website, it’s only 0.3s.</p>
<p><strong>11ty <em>is</em> fast</strong> but whatever I use only has to be faster than me switching to my browser. Hugo is insanely fast but so what? <em>Anything</em> less than 2 seconds is Fast Enough™. That’s what I mean.</p>
<h2 id="no-added-bloat-for-visitors" tabindex="-1">No added bloat for visitors</h2>
<p>Many Javascript-based <abbr title="Static Site Generators">SSGs</abbr> bundle in client code too. Sometimes this makes sense: You might use Next and Nuxt to build component rich SPAs, but for blogging and brochure stuff, an extraneous 100KB of swarf delivers a poor user experience.</p>
<p>This may explain why I’ve actively sought out non-JS <abbr title="Static Site Generators">SSGs</abbr> like Jekyll and Hugo before.</p>
<p>11ty is one of the few JS <abbr title="Static Site Generators">SSGs</abbr> that doesn’t force script on your users. If you want “pure” HTML, that’s what you’ll get. If you’re economic with your CSS, images and fonts, it’s easy to juice the performance stats.</p>
<figure data-type="image"><img src="https://thepcspy.com/read/turning-it-up-to-11ty/pagespeed.svg" alt="100% on Pagespeed" loading="lazy" decoding="async" /></figure>
<h2 id="comes-with-batteries%E2%80%A6" tabindex="-1">Comes with batteries…</h2>
<p>You don’t have to pick between Markdown and Pug, Liquid or Nunjucks. You get them all, and more. <a href="https://jekyllrb.com/docs/front-matter/">Frontmatter</a> can be in YAML, TOML, HAML, JSON even build-time javascript. So what? <em>So what?!</em> You wouldn’t say that if you’d ever wasted a day trying to work out what the hell a Hugo site was doing because of a typo in a template whose syntax was so thick and unwelcoming, kings built castle walls with it.</p>
<p>11ty is simple and flexible.</p>
<p>There’s also a <em>huge</em> pile of <a href="https://www.npmjs.com/search?q=11ty">community 11ty plugins</a> too.</p>
<h2 id="%E2%80%A6-but-you-can-use-your-own" tabindex="-1">… But you can use your own</h2>
<p>If you don’t get on with something in 11ty, you use something else, or rip it; do your own thing.</p>
<p>The Eureka moment for me was when I got into a fight with the markdown engine. I wanted to extend it to handle some of the custom things I did in my old blog posts, that I’d implemented in Django. Code to generate Youtube embeds, special floats, <code><aside></code> sidebars, etc. It would have been a nightmare to upgrade every post.</p>
<p>Using <code>markdown-it</code> and <code>markdown-it-container</code> I completely replaced the Markdown engine with something I could hack on. Here’s a real “explainer” snippet I have and use:</p>
<aside><details><summary>Open this <code><aside></code> to see the 11ty code that generated it…</summary>
<p>If I want one of these blocks, I can put this in my post:</p>
<pre class="language-markdown"><code class="language-markdown">:::explainer Click this to see how I configured this in 11ty<br />...</code></pre>
<p>And this is configured in the main <code>.eleventy.js</code> config</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> md <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">require</span><span class="token punctuation">(</span><span class="token string">"markdown-it"</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token literal-property property">html</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">)</span><br /><br />md<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'markdown-it-container'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'explainer'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token function-variable function">validate</span><span class="token operator">:</span> <span class="token parameter">params</span> <span class="token operator">=></span> params<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex"><span class="token anchor function">^</span>explainer<span class="token char-set class-name">\s</span><span class="token quantifier number">+</span><span class="token group punctuation">(</span><span class="token char-set class-name">.</span><span class="token quantifier number">*</span><span class="token group punctuation">)</span><span class="token anchor function">$</span></span><span class="token regex-delimiter">/</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span><br /> <span class="token function-variable function">render</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">tokens<span class="token punctuation">,</span> idx</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">let</span> m <span class="token operator">=</span> tokens<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">.</span>info<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex"><span class="token anchor function">^</span>explainer<span class="token char-set class-name">\s</span><span class="token quantifier number">+</span><span class="token group punctuation">(</span><span class="token char-set class-name">.</span><span class="token quantifier number">*</span><span class="token group punctuation">)</span><span class="token anchor function">$</span></span><span class="token regex-delimiter">/</span></span><span class="token punctuation">)</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>tokens<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">.</span>nesting <span class="token operator">===</span> <span class="token number">1</span><span class="token punctuation">)</span><br /> <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"><aside><details><summary></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>md<span class="token punctuation">.</span><span class="token function">renderInline</span><span class="token punctuation">(</span>m<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"></summary>\n</span><span class="token template-punctuation string">`</span></span><br /> <span class="token keyword">return</span> <span class="token string">'</details></aside>\n'</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /><br />module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> eleventyConfig<span class="token punctuation">.</span><span class="token function">setLibrary</span><span class="token punctuation">(</span><span class="token string">"md"</span><span class="token punctuation">,</span> md<span class="token punctuation">)</span><br /> <span class="token comment">// ...</span><br /><span class="token punctuation">}</span><br /></code></pre>
</details></aside>
<p>It’s important to stress that neither of those projects are <em>for</em> 11ty. They’re just two of a million projects sitting on npm for anyone to use. 11ty just makes it easy to use any of this stuff on your pages.</p>
<p>Adding template-filters for all the bundled template languages is also made really simple:</p>
<pre class="language-js"><code class="language-js">eleventyConfig<span class="token punctuation">.</span><span class="token function">addFilter</span><span class="token punctuation">(</span><span class="token string">"striptags"</span><span class="token punctuation">,</span> <span class="token parameter">v</span> <span class="token operator">=></span> v<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex"><span class="token group punctuation">(</span><<span class="token group punctuation">(</span><span class="token char-class"><span class="token char-class-punctuation punctuation">[</span><span class="token char-class-negation operator">^</span>><span class="token char-class-punctuation punctuation">]</span></span><span class="token quantifier number">+</span><span class="token group punctuation">)</span>><span class="token group punctuation">)</span></span><span class="token regex-delimiter">/</span><span class="token regex-flags">gi</span></span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<p>If you’ve ever used <em>opinionated software</em> before —perhaps even your own— you’ll appreciate that 11ty isn’t just getting out of your way, <strong>it’s going out of its way to make your life <em>easy</em></strong>.</p>
<h2 id="what%E2%80%99s-not-so-good%3F" tabindex="-1">What’s not so good?</h2>
<p>I’m three sites into 11ty now, I’ve seen how I work with it and I’ve bumped into a few things I’m not gushing about:</p>
<ul>
<li>
<p>Pagination is good and frustrating in equal measure. Collections seem like a good idea, filtering them into new collections is easy enough, but actually paginating them can be a bit of a mess. To show <a href="https://thepcspy.com/tag/webdev/">a tag page</a>, for example, <a href="https://www.11ty.dev/docs/quicktips/tag-pages/">you actually use pagination to filter the collection to that tag</a>. But then you can’t [easily] re-paginate <em>that</em> data, so I just show all posts from that tag rather than 15.</p>
<p>If I had hundreds of posts in any one tag, this’d be a problem.</p>
</li>
<li>
<p>For all my complaints with Jekyll and Hugo’s wonky asset pipelines, 11ty’s is completely decoupled.</p>
<p>I use <a href="https://www.npmjs.com/package/eleventy-plugin-postcss"><code>eleventy-plugin-postcss</code></a> to call PostCSS at roughly the right time (and update on changes) but I could just as easily handle that externally. There’s nothing in 11ty (obvious to me anyway) to ingest that back into the templates.</p>
<ul>
<li>You can’t easily inline classes that only get used on one page.</li>
<li>You can’t easily hash the filenames and update the links that call them <em><strong>after</strong></em> generating the post HTML (that’s important with PurgeCSS).</li>
<li>Media handling could be tighter. The <a href="https://www.11ty.dev/docs/plugins/image/">Image plugin</a> is official, but this should be part of the project IMO, and not rely on <a href="https://www.11ty.dev/docs/plugins/image/#use-this-in-your-templates">this hairy shortcode</a>.</li>
</ul>
<p>It’s important to stress that I’m using 11ty in order that I don’t <em>need</em> bundles, but some of these complaints would be assuaged if the system could parse bundle manifests, so I could use external tools rather than just a dumb static assets and have the right filenames pulled in (at the right time).</p>
</li>
<li>
<p>A scoped include like Django’s would solve a couple of problems I’ve hacked around:</p>
<pre class="language-django"><code class="language-django"><span class="token django language-django"><span class="token delimiter punctuation">{%</span> <span class="token tag keyword">include</span> <span class="token string">'template'</span> <span class="token keyword">with</span> <span class="token variable">variable</span><span class="token operator">=</span><span class="token variable">value</span> <span class="token delimiter punctuation">%}</span></span></code></pre>
<p>Saneef points out that <strong>this <em>is</em> possible</strong> by <a href="https://www.trysmudford.com/blog/encapsulated-11ty-components/">leveraging the macro functions in Nunjucks</a>. It’s a bit of a mouthful. I’d prefer a first-party solution (which I guess would actually have to come as part of the Nunjucks), but again it’s interesting to see just how flexible this thing is.</p>
</li>
<li>
<p>Named/keyword arguments in shortcodes would also be nice, so I don’t have to provide every option to just use the last, but I guess this would require some thinking to overcome the lack of support for destructured parameters in ES6.</p>
</li>
</ul>
<p>These are small complaints, maybe already with solutions I’ve just not seen yet.</p>
<p>I’ve still managed to transfer three sites to 11ty in a couple of weeks and I wouldn’t have done that if I didn’t think it worked well enough. <strong>I’m really happy with 11ty.</strong> I’d heartily recommend it to anyone.</p>
Wait! What happened to RSS?!2022-06-10T00:00:00Zhttps://thepcspy.com/read/what-happened-to-rss/<p>While I was busy aging like soft cheese, someone killed-off* RSS.</p>
<p>It used to be everywhere, now it’s <em>gone</em>; hidden or dead. How do you kids stay up to date with the websites you like? Do you know what RSS does? How are websites <em>supposed to</em> advertise update-subscriptions?</p>
<p>While I was busy aging like soft cheese, someone killed-off* RSS.</p>
<p>It used to be everywhere, now it’s <em>gone</em>; hidden or dead. How do you kids stay up to date with the websites you like? Do you know what RSS does? How are websites <em>supposed to</em> advertise update-subscriptions?</p>
<figure class="rim" data-type="image"><img src="https://thepcspy.com/read/what-happened-to-rss/rss.svg" alt="" loading="lazy" decoding="async" /></figure>
<p><a href="https://en.wikipedia.org/wiki/RSS">Really Simple Syndication</a> was invented in the Cretaceous period, roughly 100 million years ago. It enabled websites’ fans to get updates, quickly and easily. It got used for everything else too and remains a fundamental part of podcasting, but in the explosion of Web 2.0, it was a very serious part of websites keeping in touch with their user-bases.</p>
<p>I recently restored the Subscribe Icon back to the main navigation here when it started to dawn on me…</p>
<h2 id="do-you-kids-know-what-to-do-with-rss%3F" tabindex="-1">Do <em>you kids</em> know what to <em><strong>do</strong></em> with RSS?</h2>
<figure class="rim" data-type="image"><img src="https://thepcspy.com/read/what-happened-to-rss/xml.png" alt="" loading="lazy" decoding="async" /></figure>
<p>Once upon a time, you clicked a link to a RSS feed, you’d see an option <em>to do something with it</em>: save a <a href="https://support.mozilla.org/en-US/kb/feed-reader-replacements-firefox">live bookmark in Firefox</a>, or add it to <a href="https://en.wikipedia.org/wiki/Google_Reader">Google Reader</a>. Both long dead. There still are a clutch other readers today, but the automated handling of this, and seemingly the <em>desire</em> of browsers to <em>handle this</em> seems to have evaporated, leaving novices in the lurch.</p>
<p>If you click a link to <a href="https://thepcspy.com/feeds/full.xml">my main feed</a>, <s>your browser might pretty-format the XML code but that’s all the help you get</s>. <strong>Update</strong>: The raw RSS is now styled via XSLT so it does at least look better than a page of XML. More at the end.</p>
<p><em>You</em> still need to plumb that URL into something. And that relies on you knowing what it is. So straw poll, please. If you don’t know anything about RSS, let this old doughnut know and I’ll stop pushing it. Ideally you’ll also have an answer to my next question…</p>
<h2 id="how-do-you-subscribe-to-websites-in-2022%3F" tabindex="-1">How do you subscribe to websites in 2022?</h2>
<figure class="rim" data-type="image"><img src="https://thepcspy.com/read/what-happened-to-rss/fellowkids.jpg" alt="" loading="lazy" decoding="async" /></figure>
<p>I’m people so I’ll go first: <strong>I still use RSS</strong>. I use <a href="https://feedly.com/">Feedly</a> to get updates from about a hundred websites, and Hacker News, and <a href="https://www.youtube.com/watch?v=DwumK549k6g">I’m happy with my wash</a>. This is how it’s been for a decade.</p>
<p>That’s where my consternation originated. Do people just consume what they’re now fed through Platforms: Facebook, Twitter and Tiktok? Would I have to hawk myself on each platform? I’m concerned that’s just feeding the problem. It’s not even apparent how websites are doing this either now. I know I’ve hacked together a few <em>feed generators</em> for websites without RSS, just so I can get updates.</p>
<p><strong>I want to know how you handle updates. Please tell me in the comments or <a href="https://thepcspy.com/contact/">by email</a>.</strong></p>
<h2 id="why-are-google%2C-microsoft-and-apple-so-inactive-here%3F" tabindex="-1">Why are Google, Microsoft and Apple so inactive here?</h2>
<p>It’s super easy to blame “The Rise of Platforms”, but hard to ignore that the big desktop and mobile operating systems have done nothing to help. Browser vendors washed their hands of RSS. What’s especially galling is <strong>these companies run personalised news aggregation services</strong>, but none lets you add your own feeds. I’d think that each of them has a vested interest in reining back control of web consumption. Maybe the <a href="https://www.theverge.com/2022/6/7/23156361/european-union-usb-c-wired-charging-iphone-lightning-ewaste">EU can mandate</a> RSS support.</p>
<p>I don’t have a high note to end on here. I stopped paying attention and the world changed on me, and I can’t figure out why. I just feel old.</p>
<h2 id="update%3A-tell-people-what-rss-is-with-xslt" tabindex="-1"><strong>Update:</strong> Tell people what RSS <em><strong>is</strong></em> with XSLT</h2>
<figure class="rim" data-type="image"><img src="https://thepcspy.com/read/what-happened-to-rss/xslt.jpg" alt="" loading="lazy" decoding="async" /></figure>
<p>My biggest single complaint was that linking to a wall of XML would just confuse people. I don’t think we’ll convince any browser vendors to give us back RSS support in the short term, but <a href="https://en.wikipedia.org/wiki/XSLT">XSLT</a> came up a few times in your comments here, emails, and <a href="https://news.ycombinator.com/item?id=31698496">comments on Hacker News</a>. Big thanks. XSLT is a templating and styling language for XML and <a href="https://caniuse.com/?search=xslt">it has good browser support</a>.</p>
<p>With it you can transform an RSS feed into something that <em>looks like</em> a normal web page. And explain what to do next, if they don’t already know. <a href="https://thepcspy.com/static/feed.xslt">My XSLT is super-simple</a>, please have a look. I’ve dropped in a message explaining what RSS is, that you need an aggregator. It might be nice to offer email subscriptions from here directly one day.</p>
<h2 id="*-is-rss-really-%E2%80%9Cdead%E2%80%9D-if-you%E2%80%99re-still-using-it%3F" tabindex="-1">* Is RSS really <em><strong>“dead”</strong></em> if you’re still using it?</h2>
<p>A few people took exception with my leading claim that RSS seems dead. They’re still using it. You’re still using it. <em>Bloody hell, I just said I’m still using it</em>. How could it be dead?</p>
<p><strong>Latin is a dead language.</strong> People who make a special effort still understand it, and some even <em>use</em> it, and there’s plenty evidence it existed, scattered through modern languages… But as soon as the Roman Empire fell, and the Western Empire rotted away, around 400AD, poor education meant Latin died off rapidly. Without the central push and steering, local languages took over.</p>
<p>Well… RSS is in a similar predicament. Browsers stopped <em>speaking</em> RSS. They don’t detect it. They don’t offer subscription options to users. They used to a few years ago. That has to have had an impact on the number of people using it today. It’s almost 10 years since the last spec revision. The number of services providing feeds RSS and iCal (another important protocol) has plummeted as proprietary notification protocols have taken over in disparate third party services.</p>
<p>If you’re not going with me, consider this: <em>When was RSS last really <strong>alive</strong>?</em></p>
<p>I think this matters. It matters to me, and I’d wager that if you’re reading this, you probably still use RSS too. If we want it to carry on existing, being provided for us, we need to start thinking about the reasons it’s in decline —even if it’s not “dead”— and where is best to apply pressure to reverse that.</p>
CSS layouts are *so much* better than they used to be2022-06-09T00:00:00Zhttps://thepcspy.com/read/modern-css-is-amazing/<p>I’ve been doing this web thing a while, and in finally dropping IE11 support for my last few projects, I’ve been able to use raw CSS —not somebody else’s framework— and it’s been lovely to see how far CSS has come.</p>
<p>I’ve been doing this web thing a while, and in finally dropping IE11 support for my last few projects, I’ve been able to use raw CSS —not somebody else’s framework— and it’s been lovely to see how far CSS has come.</p>
<figure class="rim" data-type="image"><img src="https://thepcspy.com/read/modern-css-is-amazing/yell-cloud.jpg" alt="" loading="lazy" decoding="async" /></figure>
<p>You whipper-snappers might not appreciate it but CSS used to be pretty janky. You could style some of your content, but getting it into the right places, in a reproducible way was a headache. It was so inconsistent between browsers, and so incompatible with the designs we were paid to implement, we’d use ghastly devices like <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map">image <code><map></code></a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/frameset"><code><frameset></code></a> and <a href="https://css-tricks.com/in-defense-of-tables-and-floats-in-modern-day-development/">nested <code><table></code></a> elements. We’ve come a long way since then.</p>
<figure class="rim" data-type="image"><img src="https://thepcspy.com/read/modern-css-is-amazing/holy-grail.svg" alt="" loading="lazy" decoding="async" /></figure>
<p><a href="https://alistapart.com/article/holygrail/">The Holy Grail</a> was A List Apart’s famous article, a culmination of years of forebears delicately floating things around, abusing padding and negative margins to achieve something it took a <code><table></code> to do before. It’s hard to appreciate 16 years on, but that article was my bible for a while.</p>
<p>As CSS standards improve and <a href="https://thepcspy.com/read/ie6-usage-is-dropping-like-a-stone/">old versions of IE died off</a> we saw the rise of <em><strong>CSS Frameworks</strong></em>, third party code, pre-hacked for edge-cases, just follow their markup, use their classes and everything would work. Most of the time. I’ve been through a few: <a href="http://blueprintcss.org/">Blueprint</a>, <a href="https://960.gs/">960</a>, <a href="https://getbootstrap.com/">Bootstrap</a> and most recently <a href="https://tailwindcss.com/">Tailwind</a>.</p>
<p>And I hate them all. That’s not fair. They’ve helped me, professionally, cope with an increasing number of browsers, and increasingly complex layouts (<em>waves in responsive</em>), and they’ve definitely got better —depending on your opinion on <a href="https://tailwindcss.com/docs/utility-first">utility-first classes</a>— but they all <a href="https://developer.mozilla.org/en-US/docs/MDN/Guidelines/Code_guidelines/CSS#dont_use_resets">reset</a> to something slightly different, and while the form classes are genuinely helpful, and they all served a purpose for layout, I’d rather have not depended on any of them. It’s those moments where you notice that somebody decided that <code>display: table</code> was the best option to meet IE10 support. And until <a href="https://purgecss.com/">PurgeCSS</a> came along, they also meant a serious hit to the page weight.</p>
<p>But it’s 2022 now and I’m able to drop IE11 support in most new projects. I can drop all this other crap too. <strong>I’m naked again, writing real, raw, standards-abiding CSS</strong> without having to look up a billion utility classes, not having to inspect everything. I can just write layouts —my way— and concisely throw things onto the page.</p>
<p>I’m sure I’ll still use frameworks for complex components. Forms are a great example of something that starts off very easy and by the time you’re implementing a <code><fieldset></code> style and are trying to plug in your error feedback messages, you wish you’d never started. The standards have some way to go there.</p>
<h2 id="holy-grail-'22-%E2%80%94-layout-doesn%E2%80%99t-have-to-be-hard." tabindex="-1"><em>Holy Grail '22</em> — Layout doesn’t have to be hard.</h2>
<p>Let’s start with the HTML.</p>
<div class="rim">
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>header</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>header</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>nav</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>nav</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>aside</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>aside</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>footer</span><span class="token punctuation">></span></span>...<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>footer</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span></code></pre>
</div>
<p>The <a href="https://alistapart.github.io/code-samples/holygrail/example_3.html">original example 3</a> (view source <em>if you dare</em>) needed wrappers and hacks. Our modern markup can <em>mean something</em>. We can ditch the flabby wrapper containers. We can even re-order the elements so they make sense to screen readers and other scrapers.</p>
<p>And our CSS just paints those items into a 3×3 grid via <code>grid-template-areas</code> while the <code>grid-template-*</code> rules handle the sizing. There are so many different ways to handle this with <code>display: grid</code> but I like this one.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">html</span><span class="token punctuation">{</span> <span class="token property">height</span><span class="token punctuation">:</span> 100% <span class="token punctuation">}</span><br /><span class="token selector">body</span> <span class="token punctuation">{</span><br /> <span class="token property">min-height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> grid<span class="token punctuation">;</span> <br /> <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> 180px 1fr 130px<span class="token punctuation">;</span><br /> <span class="token property">grid-template-rows</span><span class="token punctuation">:</span> min-content 1fr min-content<span class="token punctuation">;</span><br /> <span class="token property">grid-template-areas</span><span class="token punctuation">:</span><br /> <span class="token string">"header header header"</span><br /> <span class="token string">"left center right"</span><br /> <span class="token string">"footer footer footer"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token selector">body > header</span> <span class="token punctuation">{</span> <span class="token property">grid-area</span><span class="token punctuation">:</span> header<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /><span class="token selector">body > nav</span> <span class="token punctuation">{</span> <span class="token property">grid-area</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /><span class="token selector">main</span> <span class="token punctuation">{</span> <span class="token property">grid-area</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /><span class="token selector">body > aside</span> <span class="token punctuation">{</span> <span class="token property">grid-area</span><span class="token punctuation">:</span> right<span class="token punctuation">;</span> <span class="token punctuation">}</span><br /><span class="token selector">body > footer</span> <span class="token punctuation">{</span> <span class="token property">grid-area</span><span class="token punctuation">:</span> footer<span class="token punctuation">;</span> <span class="token punctuation">}</span></code></pre>
<aside><details><summary>Why use <code>></code> child-selectors for everything but <code><main></code>?</summary>
<p>Elements like <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav"><code><nav></code></a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header"><code><header></code></a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer"><code><footer></code></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside"><code><aside></code></a> can all appear multiple times if the document requires it. It’s very common —for example— to have in-document headers that are <em>about</em> the document, not the site.</p>
<p>You’re only <em>allowed</em> one <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main"><code><main></code></a> so we can be lazy and not specify.</p>
</details></aside>
<figure class="rim" data-type="image"><a href="https://thepcspy.com/read/modern-css-is-amazing/demo/"><img src="https://thepcspy.com/read/modern-css-is-amazing/my-holy-grail.png" alt="My holy grail" loading="lazy" decoding="async" /></a></figure>
<p>That’s 100% width, 100% height, equal height centre columns.<br />
<a href="https://thepcspy.com/read/modern-css-is-amazing/demo/">The Holy Grail in its entirety in 30 lines and change</a>.</p>
<p>And it’s quickly adaptable. If you wanted a maximum width, like a lot of layouts (inc this one) you can just tune the <code>grid-template-columns</code> centre column from <code>1fr</code> to a <code>minmax</code> width, and use <code>justify-content</code> to align the grid to the centre of the <code><body></code> element. I’ll add some padding to push the grid away from the edges too.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">body</span> <span class="token punctuation">{</span><br /> <span class="token property">margin</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span><br /> <span class="token property">min-height</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>100% - 2rem<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* tune it to keep full height */</span><br /> <span class="token property">grid-template-columns</span><span class="token punctuation">:</span> 180px <span class="token function">minmax</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 690px<span class="token punctuation">)</span> 130px<span class="token punctuation">;</span><br /> <span class="token property">justify-content</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<figure class="rim" data-type="image"><a href="https://thepcspy.com/read/modern-css-is-amazing/demo-2/"><img src="https://thepcspy.com/read/modern-css-is-amazing/my-holy-grail-2.png" alt="My holy grail v2" loading="lazy" decoding="async" /></a></figure>
<p>Want spacing between zone? Use <code>gap</code>.<br />
Borders and padding can be baked into the sizing using <code>box-sizing</code>.</p>
<p><a href="https://thepcspy.com/read/modern-css-is-amazing/demo-2/">It’s <em>excruciatingly</em> simple</a>. This is so much better.</p>
<p>One last time, for the years of suffering and hacking and wasted effort, screw you, IE.</p>