Multipage Version Zine, Issue 1
25 May 2024 | 12:00 am

I contributed two pages to Multipage Version, Mat Marquis’ new zine.

The zine is about HTML elements, and is intended to be printed out as physical media. It was a ton of fun to make, and so refreshing to get back to print media design for a bit.

Here are the two pages I contributed, as a sneak preview:

Two paper pages, printed in black and white. One is placed slightly over the other. The first page is a comic, made from collaged, photocopied black and white British horror comics. The first panel is a tank getting struck by shell fire and exploding, bodies flying from the blast. A narrative overlay reads, 'The WebAIM millions report' and one of the soldiers is screaming, 'Fuck!'. Underneath the panel is the URL for the WebAIM Millions report. The next panel shows a man grasping his head in exasperation, exclaiming, 'Christ almighty, we're getting mad at the wrong thing here.' The narrative overlay for this panel reads, 'An accessibility nerd'. The next panel uses textures to take the shape of a web browser. It is displaying a page with a title that reads, 'Browsers are a failure of imagination.' Following that is a tree with nodes that describe how heading elements could be improved. Suggestions here are implicit IDs if none are provided, UI to show the heading structure like with the headingsMap browser extension, visual errors rendered on screen, a preference to toggle click-to-copy deep links, and methods to grab the tree and show errors in the console. Underneath the browser panel are two men's faces, one younger and one older. The title of this section is 'Better tools for better education and outcomes. The younger man is staring in shock at a QR code that links to the headingsMap browser extension. Above his head is some free-floating text that reads, 'Get mad we wasted years only bikeshedding JavaScript rendering because it made Capitalism go faster.' The older man is scowling and scolding the viewer, and saying, 'Extensions for both Blink and Firefox! There's no excuse!' An asterisk after Firefox points to a small note that reads, '*Ed: WebKit is trash lol'. Above the older man's head is some free-floating text that reads, 'Content is king'. The second page is all black with gigantic white text set in a bold, sans-serif typeface. Each line of text is placed in a banner that uses a warning stripe border, and the banners overlay each other. The text reads, 'There is no document outline algorithm.' In the top-right corner is a small skull shape with text that reads, 'DOA: Dead on arrival'. Below the large text is a strip of tiny text that reads, 'Never was, never will be. Human language does not work that way. Just do it manually, it's fine. Version your spec you cowards. WHATWG/HTML commit 6682BDE.'

You should do yourself a favor and order a copy or ten. 100% of the profits goes to Trans Lifeline.

<code>contrast-color()</code> is a good thing, but also solving the problem at the wrong layer
21 May 2024 | 12:00 am

Browsers are a failure of imagination.

I understand that new browser features and functionality need to be rolled out with care, in that you need to accommodate a wide range of technological literacy and familiarity. This is to say nothing of built-up muscle memory and the risk of change aversion.

That said, the long view of the convergent evolution that are web browsers leaves me wanting.

Functionality that would be genuinely beneficial to the people using these applications day in and day out take a backseat to things like optimizing esoteric JavaScript debugging techniques, inventing new ways to generate advertising metrics, and collapse our climate via an unrelenting torrent of AI hype.

To further explain this point of view, I’d like to talk about contrast-color(), a new CSS function.


This function is part of the level 5 color module for CSS. This module contains a lot of things I’m excited for, and is part of CSS’ current Renaissance moment.

contrast-color() unlocks the ability the browser to automatically intervene for color contrast-related considerations. It “automatically provides a color with guaranteed color contrast when used as a text color on a solid background of the specified color.”

This is pretty damn cool. Given that we know:

  1. Minimum compliant contrast thresholds,
  2. Font size used, and
  3. At least one color value

We can instruct the browser to generate a color value for the text or the background it is placed on that is WCAG conformant.

// [1] Set a Custom Property
// [2] Use @supports for better guardrails
// [3] Use contrast-color() and a Custom Property in conjunction

:root {
--color-secondary: #FFEDEF; // [1]

.my-selector {
@supports (color: contrast-color(#FFEDEF)) { // [2]
background-color: var(--color-secondary);
color: contrast-color(var(--color-secondary)); // [3]

At its core, contrast-color() is new tool that will help ensure an accessible, and therefore usable web. This is fundamentally a good thing!

If I’m understanding the syntax correctly, it can also serve as a “clamp” for color variables. The idea here is it could work with things like color-mix() to create guardrails for dynamically generated color values.

// [1] Use constrast-color() for the last color calculation
// [2] Dynamically mix --color-accent into --color-secondary

.my-selector {
@supports (color: contrast-color(#FFEDEF)) {
background-color: var(--color-secondary);
color: contrast-color( // [1]
color-mix( // [2]
in srgb,
var(--color-accent) 70%

Technology does not exist in a vacuum

We also need to consider the larger contexts contrast-color() will be introduced into.

Thanks to the pervasive devaluation of both the frontend and CSS as industry concerns, awareness of, and actual use of contrast-color()’s is likely going to only be found in two general areas:

  1. Hobby websites for folks who like CSS and the frontend, and
  2. The design systems where these sorts of people tend to wind up working.

Design systems that utilize more mature concepts such as color tokens likely already have mechanisms to perform what contrast-color() does. These design systems also tend to be more accessible, either by principle or by legal compulsion. For example, Primer already has this infrastructure in place.

This also means that organizations and websites without this sort of infrastructure are far less likely to consider compliance, or possess the knowledge or resources to enact it.

We also need to consider unproductive mindsets about disability

When contrast-color() is mentioned, it is usually done so along with a reference to the prefers-contrast media feature.

If you are unfamiliar with prefers-contrast, it is a way to adjust your website if an operating system preference for a higher contrast experience is enabled. Think of it like dark mode or preferring reduced motion.

The macOS System Settings preference pane, set to show the Display subsection of the Accessibility category. The Increased Contrast switch toggle has been flipped to the on position, and a bright orange rectangle has been drawn around it to better visually emphasize it. The active increased contrast setting has added black borders between different UI elements, and increased the contrast of the text and icons.

The idea here is that you’d apply contrast-color() in scenarios where someone has requested a higher contrast experience, with the understanding that it’d help to ensure that experience delivers on its promise.

.my-selector {
color: var(--color-primary);
background-color: var(--color-secondary);

@media (prefers-contrast: more) {
color: contrast-color(var(--color-primary));

Unfortunately, this thinking also sets up an ugly, “us versus them” mentality. It also presupposes that people:

  • Are aware there is text content they cannot perceive,
  • Are aware of having a low vision condition,
  • Accept having a low vision condition, and
  • Are aware of, and use the preference to do something about this.

It also assumes that the operating system has the preference toggle to enable in the first place, which isn’t always a given.

If you go down this rabbit hole—and I hope you don’t—far better to flip your thinking and start with an accessible default, and then make the alternate experiences non-compliant:

.my-selector {
color: var(--color-primary);
background-color: var(--color-secondary);

@media (prefers-contrast: less) {
color: var(--color-tertiary);

This removes the burden of the people consuming your content needing to expend additional effort to counteract your inaccessible choices.

Further issues

Another assumption here is that people want a high contrast experience for everything, which isn’t necessarily true. For more thinking here, I suggest comparing it to Bramus Van Damme’s post, Dark Mode Toggles Should be a Browser Feature.

Furthermore, leaning on a high contrast theme to do the heavy lifting creates a scenario where the default view may be too light to be functional. This means someone may not be able to actually perceive the mechanisms needed to enable an experience that can work for them.

Experiences should be accessible by default.

Delegating accommodation to mode-based operation enables designers to continue bad practices and ableist notions about aesthetics. It’s also a ton more overhead design and code considerations to manage and maintain—better to tackle this problem on the education layer.

Targeting the right layer

Speaking of layers, I now pose the question: Why does all this have to be the website or webapp author’s responsibility?

Deep knowledge of CSS is rare, and not incentivized. Browsers already calculate, and are therefore aware of foreground and background color values. Given both of those considerations, are we missing out on a better way to go about this?

I would love to see this sort of feature implemented on the browser level. And guess what? There’s prior art that can be referenced.

FixA11y, Kilian Valkhof’s excellent browser extension. It’s a great resource, and we’re lucky to have it. And if you haven’t heard of it before? Well, it’s part of the larger point I’m driving at.

A browser extension dialog. It is titled, 'Fix contrast', and has a subtitle that reads, 'Fix color contrast issues on websites automatically' Next to the title is a checked checkbox with a label that reads, 'Active'. In the dialog's main body there two sections. The first is labeled, 'Set minimum contrast level', has options to set as either 'Medium' or 'High'. The second section is labeled, 'Or choose your own values (advanced)'. In this section are two range sliders with the ability to set small and large text sizes. There is also a checkbox labeled, 'Change background color when needed'. Finally, there is a dialog footer with options to sponsor on Ko-fi and the other is a prompt to download Polypane.

Layer seven

My question here is why isn’t this kind of functionality a stock piece of browser UI?

A two panel comic showing how pressing a button on the browser's UI changes too-light text's color to a color that is legible. The button is placed next to the back, forward, and home buttons, right before the URL bar. The browser and web content are illustrated in an abstract, wireframe style.

We can do better than that, as well. Much like with the prefers-contrast operating system preference, use of this hypothetical feature would rely on you knowing it exists in the first place.

Again, browsers are aware of most of the foreground and background colors at play, and therefore the ratio between them. What if they intervened to tell you that they could fix things for you, and then did if you requested it?

A dialog prompt placed over a browser displaying web content that is too light to be legible. The dialog's title reads, 'Adjust contrast?', and its body content reads, 'Automatically update text and background colors to be more legible.' There are three prompts following the body content, one to update, one to cancel, and one to investigate more options. The, dialog browser and web content are illustrated in an abstract, wireframe style.

This would allow someone to become aware of the preference in a moment when it is needed. It could also be configured to be a global preference, or something tweaked on a per-site basis.

Additionally, this sort of thinking unlocks opportunities to tweak the desired contrast ratio itself on a global, site, or session-based basis.

I’m heartened to see Arc experimenting in this area, which is a hop, skip, and a jump away from integrating Midnight Lizard-style functionality. I’m also hopeful that other weird browsers might move the conversation forward here.

In the gutter, staring at the stars

I understand that making browsers takes an incredible amount of thankless effort. I also understand many people who do work on browsers may be sympathetic to my line of thinking.

I’m not mad at these individuals. I just see what is possible and wish for more.

Creating new features that help people, but don’t help extract profit are far less likely to be incentivized. At the same time, insufficient text contrast is known to be one of the most prevalent accessibility issues on the web.

This circumstance we find ourselves in is what drives my dissatisfaction. It’s my hope that in reading this you learn not only about contrast-color(), but also how to interrogate the larger environment it exists in and how it comes to be.

In the meantime, I am going to continue using baseline accessible color palettes, advocating for integrating contrast-color() where appropriate, and hoping for better.

I love my slightly smart tiny TV
13 May 2024 | 12:00 am

details { font-size: var(--scale1); margin-top: 0.25rem !important; } details summary { line-height: 1.2; } details p { line-height: 1.35; margin-top: var(--scale0); }

I swear this isn’t a sponsored post.

I impulse bought a TinyTV 2 recently. It serves a weirdly specific need, namely adding to my tiny living room’s tiny living room:

A cozy-looking minature living room placed on the shelf of a piece of normal-sized furniture. The living room has a tiny wooden dresser bureau with gold knobs. A book, vase, and a hand-knit potted fern sit atop the dresser. To the left and right of it are two potted plants, one reminiscent of a monstera and the other a snake plant. In front of the bureai is a small square of fabric decorated with abstract geometric shapes, serving as a carpet. Placed on the carpet are a mini white dog, a mini chicken with three even smaller chicks, two little blobs with smiley faces, and a tiny vase holding angel's breath flowers. There is Above the bureau is a proportinately small decorative mirror and five pieces of art, some with ornate golden frames. In front of the bureau and to the left of the carpet is the tiny TV. It looks like how a TV from the 1940s might, with a large boxy frame, faux wood exterior, and a front metal speaker grill flanked by two control dials. The TV's frame is also held up off the ground via four small faux wooden legs. Finally, a penny is placed on the side of the carpet opposite of the TV, to better communicate the sense of scale.
I live in a small place. It’s a whole thing, don’t worry about it.

The device itself is a bit of a technical marvel, provided you’re also an ancient nerd like I am. It has a 1.9" by 1.4" by 1.0" form factor that houses:

  • An Itty-bitty 216 by 135 pixel color display,
  • Eight gigabytes of flash storage,
  • A tinny speaker,
  • An infrared receiver for its companion teeny-tiny five button remote, and a
  • USB-C port.

This is all just a little bit mind-blowing given that my first MP3 player held a whopping 16 megabytes’ worth of data.

Smart in a very specific way

You add video to the TinyTV by plugging it into a computer and dragging AVI video files onto the root of the USB drive it mounts as.

And that’s it.

There’s no filename convention you need to use, no labyrinthine subdirectories to spelunk, or esoteric file format you need to convert videos to.

There’s also no limit on video length past the device’s eight gigabyte storage cap. In fact, one of the videos I include is a copy of an hour-long montage of capybaras set to vaporwave music.

Each video file corresponds to a “channel” on the TV. Channel order is assigned via alphanumeric sorting of the video’s filename, combined with a preference toggle. This means you could manually curate an order by using something like a numbered prefix.

You could also be like me and give yourself the grace of chucking them on in whatever order they land on and not think twice about it. This act has felt freeing, given how much I have to methodically curate so many of my other aspects of my digital life.

There is also a companion web experience that uses the Web USB API to write to the device and set preferences:

A list of preferences titled, 'TV Settings'. The instructions read, 'Change settings on TinyTV 2, Mini, or DIY Kit. The preferences each have an on or off radio switch, except for the volume setting, which is a range slider set to its max value of 6. The settings are loop video, live video, alphabatize playback, static effect, show channel number, show volume, and random start time. I have configured my TinyTV to not loop video or show live video, to sort alphabetically and change channels with a static effect, starting at a random start time. The channel number and volume are also set to display. Following the preferences are two buttons, one labeled, 'Format TV' and the other labeled, 'Disconnect'.

All this site does is have a slightly more easy way to modify a plaintext configuration file stored on the drive’s root. In addition, the preference option names are actually human-readable:


This sets my TinyTV set to jump to a random point in the video when the channel is changed, then change to the next channel in sequence when the current video is done.

This so perfectly recreates the aimless, serendipity-searching channel surfing experience of my childhood.

But wait, there’s more

TinyCircuits was under no obligation to do this, but they also provide a free companion app for converting video files to a format that works for the device.

The app is also refreshingly direct. You:

  • Pick a video file,
  • Set the specific model of TinyTV it’ll be added to,
  • Set if you want it stretched or cropped to fit, and then
  • Set a destination to export to.

The app is also just a tad unpolished-feeling, but that’s honestly part of the charm. More importantly, it also has effortlessly handled all the incoming video file formats I’ve thrown at it.

Sure, you could do all your video processing via the command line, but this app is the dream of UI made manifest—taking a complicated terminal command with enough variables that it isn’t worth automating and instead turn it into a few clicks.

It’s also about what isn’t there

I paid for the device and got it. There isn’t a TinyTV+ subscription model, paid feature unlocks, drip email campaigns, or founders emailing me to “pick my brain.”

It also does not have:

An act of care

You might think that all those missing “features” are not included by way of omission. However, I choose to believe it is premeditated and intentional given how detail-oriented the entire endeavor feels.

Seriously. They didn’t have to, but there’s a little burst of static effect that fires between channel changes:

Skip channel surfing YouTube embed.

Channel surfing video description

A small, retro-style TV placed on a wooden dining room table, with a soft-focus bookshelf behind it.

The video opens with the TV displaying footage of Beavis and Butthead laughing on the couch, then changes to a weird-looking cartoon that passes by too quickly to be identified. Following that is footage of Nightmare At 20,000 Feet from The Twilight zone, a Sesame Street clip of Cookie, Cookie, Cookie starts with C, a German version of the Duck Tales cartoon opening, a short Metal Gear 1 cartoon action sequence, and part of the Pinball Number Count by The Electric Company.

The TV then lingers on Freddie Mercury singing a part of Under Pressure, then changes to a Sailor Moon show break. It then shows the Sealab 2021 “Uh-oh” clip for a fraction of a second before then changing to the Conan the Barbiarian cartoon opening. The channel then changes to a snippet of Nirvana’s Smells Like Teen Spirit music video, then to a clip of the Zelda cartoon show. After that is a snippet of a Popsicles commerial, and then Ron Popeil performing an infomercial for the Ronco food dehydrator.

The "rise from your grave" sequence from Altered Beast is shown for a infinitesimally brief moment, followed by Jean Luc Picard sitting in the captain’s chair of the Enterprise. The video then concludes with Mark Mothersbaugh wearing his iconic energy dome hat in the Whip It music video.

There is a brief burst of static and an accompanying hissing noise between each channel change. The tiny TV looks like how a television from the 1940s might, with a large boxy frame, faux wood exterior, and a front metal speaker grill flanked by two control dials. The TV's frame is also held up off the ground via four small faux wooden legs.

There's also a pure nostalgia-tripping power down effect. It's ridiculous.

If someone from TinyCircuits somehow discovers and reads this: Thank you! This little gizmo has brought a lot of fun to my life, and your pride in craft is both noticed and appreciated.

A realization

Getting this tiny, slightly smart TV made me realize how disenchanted I’ve become by contemporary computing culture, and all of the exhausting, extractive, exploitative bullshit that surrounds it.

A one and done transaction got me a device that does its job well—in fact, far better than it has any right to for its price. This threw into sharp relief how rare that is in the current, bloom-off-the-rose, enshitified era of Silicon Valley.

It also does not place me in the headspace that requires a paranoid mind. I won’t need to search for, and archive media in its best possible version on a local device.

Videos I copy to the TinyTV won’t disappear from the streaming service I pay for one day without warning. They also won’t be sold off as part of some venture capital debt shell game, regardless of how much I enjoyed the content.

Additionally, using it does not make me feel like I’m helping contribute to the pointless acceleration of climate collapse by way of overhyped chatbots powered by theft. It also does not feel like I am indirectly helping to bolster the meta-agendas of cryptofascists.

Good enough can be great

Touching back on not needing to archive, I know I’m looking to more evoke a feeling than perfectly archive something I half-remember from my childhood.

I use whatever version of the video I can get my hands on, knowing it’ll be intentionally shrunk down, downsampled, and demade. And if I can’t find a source video, it’s fine.

It feels so liberating.

A small part of this is definitely because I’m wallowing in self-imposed nostalgia. There’s a rule I made up for myself of (mostly) sticking to content from the mid 80s to early 90s. This rule also ensures the content the TinyTV displays—and the experience it creates—matches its form factor.

Skip Whatchamacallit YouTube embed.

Whatchamacallit commercial video description

A small, retro-style TV placed on a wooden dining room table, with a soft-focus bookshelf behind it.

The TV turns on to show a commercial that opens with a photocopy collage animation of a Steampunk airship driven by a man in a old-fashioned suit and hat. It then transitions to a smiley face pin, followed by a young black and white cartoon woman holding a candy bar called Whatchamacallit. The candy bar is colored, to better emphasize it. The cartoon's illustration style is minimal like a linocut illustration, and reminiscent of a Charles Burns comic.

This is followed by a UFO getting struck by a laser beam and exploding, which morphs to video footage of a large stream of melted chocolate being poured into a swirling vat. Another black and white cartoon scene is then shown, this time of a man eating a color chocolate bar. This scene then has numbered shoe-prints overlaid over it to show dance steps.

Following that is a Monty Python-style collage animation of some sort of surreal organ on wheels, which wipes to show a human finger drawing a taut, sticky material upwards from the pool it is resting in. After that is another black and white cartoon woman who gently bites the tip of her finger almost seductively.

A three by three grid of esoteric objects rotate through quick enough that they cannot be identified. This then transitions to a question mark overlay, which, in turn, transitions to an umbrella blocking a rain of peanuts. The rain scene then fades for another black and white cartoon woman. She is holding a color candy bar in one hand and outstretches the other to feel the peanut rain, which continues to fall in the background.

When the peanut rice rain scene concludes the commercial then does an up-close pan across the candy bar's wrapper, which reads, “Hershey's Whatchamacallit. Caramel, peanut flavor crisp, milk chocolate”. The type for “Whatchamacallit” is set in bold, playful sans serif, with the letters dancing up and down the typeface’s baseline.

After the pan, the commercial then shows an illustration of a leopard leaping to swallow a jeweled bauble. The leopard is split down the middle and connected by a coiled spring. Following the tiger’s jump is video footage of the candy bar being split down the middle, pulled apart to reveal connecting threads of sticky caramel.

Finally, there is a young black and white cartoon man wearing circular glasses who looks inquisitively at the viewer and then looks up the term “Whatchamacallit” in the dictionary. An illustration of the candy bar is shown next to the word, which glows with color once identified.

During the entire commercial a song about the candy bar is playing. It has a haunting, quizzical, dream-like wavy synth-pop quality to it.

The tiny TV looks like how a television from the 1940s might, with a large boxy frame, faux wood exterior, and a front metal speaker grill flanked by two control dials. The TV's frame is also held up off the ground via four small faux wooden legs.

A larger part of this feeling is because the device is simple, straightforward, unambitious, and intentionally imperfect. And dwelling in those qualities is joy.

Don’t get we wrong: simpler isn’t necessarily better, and nostalgia can be a trap. But the technology the TinyTV is paying tribute to, and the media I load onto it was far more innocent about where things would wind up.

Sharing joy

Surprise! A lot of my friends are also gigantic, ancient nerds.

I’ve had so much fun showing my friends the TinyTV. They openly smile, giggle, and laugh with a genuine sense of delight when first seeing and operating it. Heck, I know two of them straight-up bought one for themselves right after.

And this delight is the actual, earnest version of the term. It’s not the tech-diluted meaning, where a stakeholder can push their own “numbers go up“ agenda to make some part of the experience worse.

It’s such a rare thing these days to see technology evoke this kind of unvarnished, positive emotion when it comes to anything tech-related. This feeling is why I felt compelled to commit ~1,250 words to code to ramble on about a little electronic tchotchke.

It’s less about the retrocomputing, and more about the joy of the experience. Even more importantly, it’s about the joy of sharing this experience with others.

I encourage you to find your own version of the TinyTV: A simple, straightforward digital experience that brings uncomplicated fun into your and other people’s lives.

Skip that’s all folks YouTube embed.

That’s all folks video description

A small, retro-style TV placed on a wooden dining room table, with a soft-focus bookshelf behind it.

The phrase, “That’s all Folks!” written out in cursive, placed in front of brightly-colored concentric rings. After the script is written out it is followed by the phrases “Looney Tunes” and “A Warner Brothers Production”.

The background music is a jaunty, big band production that sounds a little tinny due to the speaker quality.

The TV is then turned off. There is a burst of black and white static that closes into an ever-shrinking circle that is finally reduced to a dot before dissappearing completely.

The tiny TV looks like how a television from the 1940s might, with a large boxy frame, faux wood exterior, and a front metal speaker grill flanked by two control dials. The TV's frame is also held up off the ground via four small faux wooden legs.

More News from this Feed See Full Web Site