The site uses cookies that you may not want. Continued use means acceptance. For more information see our privacy policy.

Ink Cream, the New Theme

Finally a fresh coat of paint on this old heap! Sit and read some of how it came to be.

For a while now the site has used the default theme, Twenty Twenty One. I liked it okay, but one thing that bothered me was that the dark mode wasn’t customizable, was kind of bland.

The other thing to know is that I use Stylus to clean up or modify styles on various websites I visit. For some time I’ve been using a semi-dark theme (the same light gray background as the light mode background here) on many news sites, and occasionally a dark version on others (again, same background as the dark theme here). That kind of daily testing led me to find it preferable, and so I wanted to bring that design to this site.

Browsing through Google’s selection, many fonts come close to being great but had at least one or two flaws I couldn’t abide.

The basic premise of the light theme is that websites don’t need to be white-backgrounds. We have shades of gray to use here. And that dark modes don’t need to be white-on-black. Again, we have shades. For the most part, I would be happy to use light themes if they weren’t pure white. All the web designers that shook their fists at the need to create dark variants could have made a compromise, but I haven’t seen any of them do so.

Even at night, the light theme of this site isn’t particularly bad to my eyes, though the dark mode is certainly nicer.

I found, a starter theme. It provided a solid base to build on. I later found out that WordPress is soon (sometime next year) to release a “Block theme” built for their new Gutenberg blocks system. I may eventually rebuild for that, or switch to it. It offers “full site editing,” which may kill off traditional themes. I’m not entirely sold yet, but I’m keeping an open mind and waiting to try it out and see what it offers.

I tried to add some functionality with plugins, but they mostly don’t offer an off-switch for their default styles, and trying to dequeue their styles is hit-or-miss, so I built more functionality into the theme itself. If I end up migrating to the new system, I may have to rework that functionality into plugins.

The one decision that skipped a plugin but I didn’t implement myself is code highlighting. After looking at client-side (JavaScript) options and server-side (plugin) options for code highlighting, I decided to go with neither. I can run code through pygmentize when I compose an article, and then I can add the markup directly to the post. I already self-handle other elements, like images. So if I get the itch to actually highlight code, that’s what I’ll do.

One of the big non-technical challenges was finding good typefaces. I opted to use Google Fonts to load nicer typefaces here. (I load them with WebFontLoader.) Browsing through Google’s selection, many fonts come close to being great but had at least one or two flaws I couldn’t abide. One had an inverted at-symbol (@), another had a capital C that looked too much like a G. Most sans-serif fonts don’t properly distinguish between uppercase I and lowercase L.

In the end, I dropped trying to have a separate serif face for headings, in part to keep the site light, and in part because trying to find two faces was too much.


Having not done much web development in a long while, here are some of the newer things I used in building the stylesheet.


Having been out of the loop, I didn’t realize :is() and :where() existed. I only use the latter, as it doesn’t influence the scoring of selectors. It lets you do things like:

    .recipe :where(.ingredient, .tool, .container) {
        font-weight: bold;

This saves you creating three separate selectors if you want all “important” items under a recipe to be boldfaced.


I knew that math functions existed, but clamp() is really nice. You give it three values:

  • minimum
  • variable
  • maximum

And it will let the outcome vary only within the bounds you set. Most of the time the variable will involve something with vw units, so that the outcome varies based on the screen width, but there are other ways to use it.

Custom property fallbacks

I’ve used custom properties in my user styles for awhile, so that I don’t have to recreate things like colors for every site I create a custom style for. But I didn’t know there are fallbacks. I only use them for filling the SVGs in the social media buttons:

    html:not([dark]) .soc-fill,
    html[dark] .soc-link:focus-visible .soc-fill {
        fill: var(--ic-soc-c0, #000);

    html[dark] .soc-fill,
    html:not([dark]) .soc-link:focus-visible .soc-fill {
        fill: var(--ic-soc-c1, #FFF);

I set fill values (--ic-soc-cN) for some icons, if the service calls for a particular color in their brand guide, but if not I can fallback to black or white (depending on the dark or light theme and whether or not keyboard focus is happening).

Other small bits

Testing in chromium taught me about will-change that hints the browser to expect repaints of an element. It probably isn’t that necessary given it’s only for the theme-mode toggle in the upper right, but it’s cool to know about. I was also able to use a media query for prefers-reduced-motion to stop that animation if someone has a relevant OS setting turned on.

I tried to get accessibility correct. Some of that was helped by WordPress itself, other parts helped by the underscores base. Proper accessibility design helps everyone, including people in early stages of a sight disorder or even someone who’s stressed or drunk or tired.

To improve accessibility, I removed placeholder text in form inputs. After trouble finding good colors that were within the contrast bounds, I did some thinking and reading. I decided that the only real purpose of placeholder text is to make forms look less plain. Multi-field forms need visible labels anyway, and with those the placeholders don’t really add anything to the design.

If you’re relying on hidden labels being read by screen-readers, that leaves people who may have some accessibility needs out in the cold. The exception is single-field forms (like search), where the button next to the field provides enough information for people without screen readers.

I also tried to make keyboard navigation work correctly and with good focus coverage. I actually like how the focus looks more than the lesser design like hovering. I might eventually collapse them into the same design, though I have slight concerns that could be too confusing. Having separate styles for :hover and :focus-visible seems cleaner.


The darkmode toggle button and its JavaScript is slightly modified from Henry Egloff: “How to Code a Simple Dark Mode Toggle”.

After looking at the options, I went with remedy.css for a “reset” (github: Jen Simmons: cssremedy). I still didn’t use most of it. I’m not targeting Internet Explorer. In general I don’t want to target browsers more than a few years old.

I got a lot of help from the usual:

(Probably forgot some others. It’s the Internet, lots of good and helpful stuff around! Many thanks!)

I’m sure there’s other things I forgot. But that’s enough words for now. Hope visitors enjoy the new look.

Fixing Broken Things

Some thoughts about how to fix things that are broken.

For me, the Things in the title refers mostly to software, but it could be anything. Today there are two broken things, one which I’ve already fixed.

The first thing that was broken was this blog. I’m not sure how long the problem lasted, but if you attempted to access it sometime between just a bit ago and whenever it broke, it didn’t work. You would’ve gotten an error.

My method of fixing it was roughly:

  1. Notice it’s broken.
  2. Confirm it’s actually broken (eg, that it wasn’t a connection problem or browser-related problem).
  3. See how broken it is.
  4. Fix it.

The first step came for free, as it usually does, except when things break in very subtle/spooky ways. This actually ties in with the third step as much as the second step.

The second step entailed opening the site in a different browser and trying a few other things like making a request with curl -I <domain>. Again, this also ties in with step three.

The third step was getting on the server itself and really finding the root of the problem. In this case, the problem was that the version of PHP the server runs changed, making something that was probably a warning before into a full error.

The fix wasn’t hard once I had that direct, small, known problem.

But the key point here is that the first three steps and step four are basically two steps, and that they’re both essentially the same process.

Part one is getting the problem understood, modeled. Part two is getting a solution understood, modeled.

Both are scientific in their best case: forming a hypothesis, testing it, and observing the results.

Either can block. Sometimes you can’t find the problem, and sometimes a solution is elusive. Sometimes to find the problem would require access or tools that aren’t available. Same for finding or implementing a solution.

The other problem giving me a rash today is my Firefox profile. This profile has been with me for a long time. It’s from at least 2005, as it came with me when I switched to GNU/Linux in 2006. It’s only recently had some problems:

  1. A particular website which I don’t frequent causes a complete and utterly bad situation: it eats all my memory and then starts eating my swap.
  2. Firebug just won’t work.

For reference, I’ve got six gibibytes of RAM, which never get filled. Within a minute of visiting the website in question, swap begins to be flooded, my RAM being completely filled.

In both cases, using a different profile fixes the problem, but even in safe mode on this profile the problem persists (can’t check Firebug from safe mode, but some console errors reinforce the fact that it wouldn’t work there).

The question is whether it’s worth it to try to track down the problem with the profile. It’s probably not. Recently Firefox introduced a feature (available in Firefox 13, currently beta) that will reset my profile, but it’s currently disabled for me in Iceweasel. That’s seems to be due to Iceweasel being dependent upon XUL runner on Debian, in order to not install the same support libraries for all Mozilla applications.

Using the web console, one can see that the following migrators are available:

  • browser/chrome
  • browser/firefox
  • browser/ie
  • browser/safari

While I could force the issue, without knowing what would happen, this would be risky. An alternative would be to create a new profile, throw some data in, and try it there first, to see if it’s safe.

There are other ways to achieve the equivalent of a reset, the most useful being to use the Firefox Sync service to store the data, then attach a new profile to Sync and let it handle the rest.

If I decide to go for a new profile, this will fit the bill nicely. But it remains to be seen if I can still figure out what the problem with this profile is.

And here’s where we depart. Next week, I’ll leave a note about the outcome. I’ll probably replace the profile either way, but it would be neat to know what the problem is.