Named Alternates for WordPress


Screenshot of Lynx, the text browser, showing named alternates.

HTML documents have the concept of an alternate representation of the document. For example, a page's header might say: <link rel="alternate" type="application/rss+xml" href="https://shkspr.mobi/blog/feed"> That tells you there's an alternative representation of the page, what sort of content it is, and where it is located. That's nice. But it's hard for a browser to tell the user what that page is. It might be able to guess from the type, but it isn't always certain. So the <link> element …

Continue reading →

Accents and eBooks


The phrase "Swords of Qadisiyyah." But the combining macron over the letter "a" has been rendered as a separate dash.

By and large, the English language doesn't use diacritical marks. Even our loanwords are stripped of them; we drink in a cafe rather than the more pretentious café. This has a consequence for HTML and, by extension, eBooks. As a quick primer, modern computing gives us two main ways of displaying a letter with an accent. The first is simple - encode every single accented letter as a separate "pre-composed" character. So è (U+00E8), é (U+00E0), ê (U+00EA, and ë (U+00EB) are all stored as diff…

Continue reading →


While attending IndieWebCamp in Brighton a few weeks ago, a bunch of us were talking about blogging. What is post? What should it contain? What's optional? Someone (probably Jeremy Keith said: A blog post doesn't need a title. In a literal sense, he was wrong. The HTML specification makes it clear that the <title> element is mandatory. All documents have title. But, in a practical sense, he was right. This blog post has an empty <h1> element - the document might be semantically invalid,…

Continue reading →

I can't use my number pad for 2FA codes


Computer number pad with the number 7 in the top left.

This has to be the most infuriating bug report I've ever submitted. I went to type in my 2FA code on a website - but no numbers appeared on screen. Obviously, I was an idiot and had forgotten to press the NumLock button. D'oh! I toggled it on and typed again. No numbers appeared. I switched to another tab, my numbers appeared when I typed them. So I was reasonably confident that my keyboard was working. I swapped back to the 2FA entry and tried again. Still nothing. Then I tried typing the…

Continue reading →

Use CSS to boost the font size of emoji with no extra markup


Group of emoji.

I want to make emoji bigger than the text that surrounds them. At my age and eyesight, it can be difficult to tell the difference between 😃, 😄, and 😊 when they are as small as the text. Is there a way to use CSS to increase the font size of specific characters without having to wrap them in an extra <span> or similar? Yes! Although it is a bit of a hack. This relies on 3 CSS features: src: local(), unicode-range,and size-adjust. Let me walk you through it. @font-face { font-family: &q…

Continue reading →

Using date-based CSS to make old web pages *look* old


Screenshot of an early BBC news website from the 1990s. The page looks old fashioned.

How do you know you're looking at an old website? You may have found a page which has lots of interesting information, but how can you tell it's a modern and relevant result? Some websites don't contain dates in their URls. There may not be a © date or publication date shown on the page. And the <meta> tags might not contain anything useful. If you're lucky, the site will look old fashioned: Unlike the BBC, most sites have adopted the "Eternal CSS" pattern. When fashions change, the entire …

Continue reading →

CSS only colour-scheme selector - no JS required


A light website with a photo of a kitten.

Yesterday I wrote about a lazy way to implement a manual dark mode chooser. Today I'll show you a slightly more sensible way to do it. It just uses CSS, no need for JavaScript. Here's a scrap of HTML which present a dropdown for a user to choose their colour scheme: <select id="colour-mode"> <option value="">Theme Selector</option> <option value="dark">Dark Mode</option> <option value="light">Light and Bright</option> <option value="eink">eInk</option> </select> It will look…

Continue reading →

Laziest Possible Dark-Mode Toggle - Using :has() and invert()


A dark website with a photo of a kitten.

I'm not saying this is a good way to make a dark mode website. I'm not even saying it's a sensible way to do dark mode. But I'm pretty sure this is the laziest way of getting dark mode on your site. And it is all done with less than a handful of CSS rules. It relies on the new-ish :has() CSS pseudo class and the positively ancient filter() CSS function. Here's the code in all its glory: body:has( > #dark-mode-checkbox:checked ) { filter: invert(1); background: #000; } …

Continue reading →

Hiding malicious commands in copy-and-pasted text


The HTML5 Logo.

Quite often websites will encourage you to copy and paste commands into your terminal. There are a variety of reasons why this is bad - not least because someone could hide malicious code. That's usually done with a bit of CSS to make the evil command invisible, or using Javascript to inject something unwanted into your keyboard. Here's method that I hadn't seen before. Copy this code and paste it into your terminal to see your external IP address: Notice anything weird about it? Depending …

Continue reading →

Improving the WordPress Comments Form with Client-Side Validation


The Logo for WordPress.

If you use WordPress's HTML5 comments, there's an annoying little gotcha. There's a four year old bug which prevents client-side form validation. HTML allows <input> elements to have a required attribute. In theory, that means the form shouldn't submit until the input is filled in. Sadly, WordPress uses novalidate on the form - as the name suggests it stops any validation. But! WordPress is very hackable. Here's how to make a comment form which does client-side validation and as a bonus…

Continue reading →

The minimal-div minimal-span philosophy of this blog


HTML Source Code.

If you've ever learned Mandarin Chinese, you'll know about "measure words". They're the sort of thing that trip up all new learners of the language. While 个 (gè) can be used as a generic measure word, using it everywhere makes you sound like an idiot (according to my old teacher). So you learn to use 个 for people, 包 for packets, and 根 for things which are long and thin. English has a similar construct. You might say "one bunch of flowers" or "two glasses of wine" or "three bowls of soup". You…

Continue reading →

How to use the new <search> element with WordPress


The Logo for WordPress.

There's a new HTML element in town! You can now use <search> to semantically mark up a search box. It's great for letting screen-readers and other assistive tech know what a form does. It's only supported in WebKit for now - other browsers will get it eventually. The WordPress default search widget hasn't yet updated, but I'm going to show you how you can start using it today! In your theme, create a new file called searchform.php - WordPress will automatically load it for the search widget. …

Continue reading →