Newsletter
  • Get a newsletter digest every Friday:
Contact

Send me feedback, tips, bug reports, and anything else:

About me and the blog

My name is Marcin Wichary (he/him). I’ve worked as a UX designer, typographer, front-end person, and manager at Google, Medium, and Figma. I’ve also written a book about keyboards and typing, gave talks, and published essays about design, typography, and technology.

Unsung is my blog about software craft and quality.

More info about Unsung

Send me feedback, tips, bug reports, and anything else:

More info about Unsung

Cursed knowledge

Cursed knowledge I learned while building Unsung that I wish I didn’t have to know. (Please note some of this might be skill issue – let me know!)

August 2026–September 2026
  • iPhone Mirroring allows to record a lock screen, but doesn’t show a keyboard used to enter a password. iPhone’s on-device recording doesn’t allow to record a lock screen.
  • It seems to be possible to use -webkit-text-stroke: .008em currentcolor to simulate grade, and that seems to be working okay on all the retina devices? (I probably just jinxed it.)
  • pointer-events: none has an inheritance model that was unexpected to me: you can disable pointer events on a (larger) parent and enable them again with pointer-events: auto on a smaller child, which can be helpful.
  • pointer-events: none doesn’t include right clicks.
  • In Safari on desktop, you have to specifically include font-optical-sizing: none for opsz variable axis to work. (At least Safari on Sequoia, but even if this was fixed in Safari on Tahoe, I think it is fair to criticize Apple for tying Safari releases to OS releases and then releasing an OS that no one wants to update to.)
  • vector-effect="non-scaling-stroke" is treated differently by Chrome and Safari when the SVG is applied as a background image and scaled, and I don’t think it is possible to target them individually.
  • Firefox doesn’t yet support all the cool unit stuff, which makes some CSS calculations harder – forcing to use the tan(atan2()) hacks for unit conversion. But Safari seems to have some problems in some tan(atan2()) scenarios, resulting in abnormally large results. Luckily, it is possible to target them individually using @supports (opacity: calc(1px / 1px)).
December 2025–July 2026
  • In 2026, emails still don’t support inline videos.
  • RSS readers sanitize HTML in different ways, making for example inline video tricky. Some RSS readers do not offer to play video at all, but wrapping videos in <a> links to make them active in those readers overrides inline playback controls in other readers.
  • You can use QuickTime Player to record screen from your USB-connected iPhone, and even your Apple TV over wi-fi, but the option to use is New Movie Recording, not New Screen Recording.
  • You can make videos with full 8-bit transparency, but they have to be encoded differently for Safari and differently for Chrome.
  • Browsers do not allow you to check video’s framerate (out of fears of fingerprinting), so you have to pass that on as metadata from elsewhere.
  • It is possible for simultaneous video playback to slow down or even crash user’s browser, especially on mobile – inexplicably, browsers do not seem to be garbage collecting or throttling those to prevent crashing.
  • Videos sometimes have subtle borders on their edges. It apparently has to do with rounding up the width/​height internally by video decoders to multiples of 8px or 16px, but making sure the width/​height is divisible by those large multiples is not realistic for small video, and even trying to do that didn’t get rid of borders reliably, anyway.
  • Pixel density in images is sometimes stored (or ImageMagick outputs it) in centimeters, which means that after conversion it arrives as 143.99ppi instead of 144ppi.
  • On (touch) smartphones, a click event has pointerType == "click" on iPhone, but "touch" on a Pixel Phone.
  • In CSS, there is no way to easily make responsive images with consistent aspect ratio and min width and max width without resorting to object-position, which makes laying multiple images side by side impossible as the container doesn’t wrap around the image. The only way I found to do this is by using unpleasant manual aspect ratio calculations (which you can see on this site for every image).
  • There are still ways where the (already very messy) CSS syntax for word wrapping doesn’t account for all the common possibilities, and you have to manually or programmatically insert zero-width spaces to allow for breaking (e.g. URLs). In my experience, it’s very hard to tell CSS “break, but only if you absolutely have to.”
  • After all these years, you still have to specify -webkit-user-select: none; next to user-select: none; to cover all your bases.

This page is inspired by Cursed Knowledge by Immich.