Bin ich jetzt behindert?

In der Umfrage State of CSS 2021 (an der jeder Web-Entwickler unter Euch teilnehmen sollte) gab es gegen Ende bei den demografischen Angaben diese Frage nach einer möglichen Art der Behinderung:

Und da geriet ich ins Grübeln: Zählt meine Ellbogensteife nun zu den Mobilitätseinschränkungen, nach denen dort gefragt wird? Es ist doch (hoffentlich) nichts Dauerhaftes! Und so kreuzte ich – aus falschem Stolz wohl – nichts an.

Dennoch erwische ich mich noch Tage später, wie ich über diese Frage nachdenke. Ich bin seit über vier Monaten krank geschrieben, weil ich nicht lange mit Tastaturen arbeiten kann, ohne dass nach kurzer Zeit überanstrengte Schulter- und Handgelenke schmerzen. Hätte ich also vielleicht doch etwas anderes ankreuzen sollen? Ich predige im Job immer und immer wieder, dass Accessbility im Web nicht nur heißt, die Seiten für blinde Nutzer zugänglich zu machen – aber wenn es um einen selber geht, wird man schnell zurückhaltend. Ist doch alles nicht so schlimm, ne?

ARIA in HTML

„ARIA in HTML“ ist jetzt eine Proposed Recommendation.

Temporal

Temporal ist zwar ein ungewöhnlicher Name, aber genau das, was ich mir mindestens seit moment.js wünsche.

Temporal.PlainTime, Temporal.TimeZone und Temporal.Duration sind jetzt hinter einem Flag in Safari Technology Preview.

Hallo Hyperion!

Um „demnächst“ hier auch mal link previews wie die ganz Großen (Facebook, Twitter, Lostfocus) anzuzeigen, brauche ich erstmal die zugehörigen Metadaten einer Webseite. Also habe ich gestern Abend mal php-ogp und php-mf2 zu Hyperion zusammengestöpselt.

Vary: Service Worker

Über Monate war der Service Worker meines Kegelclubs defekt: Zwar wurden Seiten aus dem Cache geholt, wenn man offline war, aber eben nicht die Kegelspiele – und gerade für die war doch dieses tolle Feature gedacht, sitzen wir doch oft auf Kegelbahnen ohne stabiles Internet!

Wie sich herausgestellt hat, war mein Wille, HTTP-konform zu sein, Schuld daran: Ich liefere unter einer URI mehrere Ressourcen aus, je nach Accept-Header. Die Kegelspiele können also in verschiedenen Varianten (HTML, JSON, XML, Markdown) abgefragt werden:

Accept: text/html
GET https://kegelclub-tüddern.de/kegelspiele/grosse-hausnummer

<!doctype html>
...
Accept: application/json
GET https://kegelclub-tüddern.de/kegelspiele/grosse-hausnummer

{
  ...

Gedacht war das mal für eine potentielle iOS-App, um direkt eine JSON-Repräsentation zu haben. Ohje … 🤷🏻‍♂️ Pro-Tipp: Baut keine APIs, bevor Ihr sie nicht auch braucht!

Aber nun gut. HTTP-Konformität, hm? Also ein ganz kleiner Exkurs: Wenn sich die Response einer URI aufgrund eines beliebigen Request-Headers ändern kann, so muss man diese Request-Header mit dem Vary-Response-Header auflisten. In meinem Fall ist das:

Vary: Accept, Accept-Encoding

Den Header setzt man vor allem wegen Caching:

The Vary HTTP response header determines how to match future request headers to decide whether a cached response can be used rather than requesting a fresh one from the origin server. It is used by the server to indicate which headers it used when selecting a representation of a resource in a content negotiation algorithm.

Wegen Caching! Dieser Vary-Header war der Grund für den defekten Service Worker, denn Letzterer versuchte nun immer, diese eine Ressource direkt aus dem Netz statt aus dem Cache zu holen!

Die Lösung im Service Worker ist ignoreVary:

// cache will not be used for requests with Vary header, response is undefined
const response = await caches.match(request);

// cache will ignore Vary header, response is the cached ressource
const response = await caches.match(request, { ignoreVary: true });

Aaaalter … Das hat mich heute Abend gute drei Stunden Ausprobier- und Suchzeit gekostet. Aber hey, wieder was gelernt! 😓

Lange Attributwerte in den Firefox Devtools

Martin ärgert sich, dass lange Attributwerte in den Firefox Devtools gekürzt werden. Hat es mich auch schon einige Male.

Aber: Man kann das abschalten, wie ich erst neulich herausfand!

Der einfachste Weg geht über die Devtools-Einstellungen. „Truncate DOM attributes“ abhaken, fertig.

Wer es etwas granularer einstellen möchte, kann devtools.markup.collapse* in about:config bemühen.

Statische Ressourcen besser cachen

Ich habe vor einigen Wochen die Website meines Musikvereins einem Relaunch unterzogen. Nicht nur das Frontend ist erneuert, auch den kompletten technischen Unterbau habe ich neu geschrieben. So ist auch das Caching statischer Ressourcen neu, also CSS, Skripte oder Bilder. Im Folgenden beschreibe ich, was ich getan habe. Vorab: Ich nutze kein CMS oder Framework.

Weiterlesen …

create-launch-images ist da

Ein kleines „Abfallprodukt“ meines letzten privaten Projekts habe ich gerade auf GitHub und npm gepusht: create-launch-images

iOS erstellt für PWAs leider immer noch keine Launch-Screens auf Basis des Web App Manifests – die Bilder (und es sind nicht wenige!) muss man selber bereitstellen. Das war ich leid, darum habe ich kurzerhand ein Node-Script geschrieben, das das Manifest auswertet und mit dem größten darin hinterlegten PNG-Icon, dem name oder short_name und der background_color die Launch-Screens für iPhone 6 und höher erstellt.

Der Code ist sicher nicht der Schönste, Robusteste oder gar Performanteste, funktioniert aber für meine Zwecke ganz gut. Darum habe ich das mit meow zu einem kleinen CLI-Tool verdrahtet und veröffentlicht, damit Ihr auch was davon habt. Natürlich ohne Gewähr, ist ja auch v0.0.1! 😁

Weiterlesen …

Feierabend

So. 9 Stunden Code geschrubbt; es verbleiben noch zwei Kleinigkeiten, die hebe ich mir für morgen auf. Und dann endet ein Projekt, das ich laut Things am 24.03.2017 begonnen habe, dessen erster Commit laut GitHub am 03.04.2018 stattfand und das inzwischen 101.688 Changes hat.

Adressleiste im iOS-Safari einfärben

Eine nette Sache, die im mobilen Chrome (und in einer Reihe von anderen Browsern) funktioniert, ist das Einfärben der Adressleiste. Man setzt einfach dazu einfach ein Meta-Tag:

<meta name="theme-color" content="lime">

Im iOS-Safari ist das nicht möglich, auch nicht mit dem Web App Manifest.

Beim längst überfälligen Redesign der Vereinsseite bin ich aber zufällig auf einen netten Effekt gestoßen: Mittels einer background-color auf dem body färbt diese Farbe die Adressleiste ein. Die „normale“ Hintergrundfarbe legt man dann auf dem direkten Kind-Element des Bodys. Zum Beispiel so:

body {
  /* this will color the address bar in iOS/iPadOS Safari */
  background-color: lime;
  /* reset body margin for full background-color of wrapper */
  margin: 0;
}

body > *:first-child {
  /* apply default background-color and “body” padding here */
  padding: 1em;
  background-color: white;
}

Das Ergebnis wäre dieses:

Ups, der Content ist zu kurz, die Hintergrundfarbe soll so aber nicht aussehen. Der Trick ist, jetzt noch eine Hintergrundfarbe auf html zu setzen:

html {
  background-color: white;
}

Idealerweise ist es die gleiche Farbe wie die des ersten Kind-Elements. Aber man kann natürlich auch etwas kreativer sein und eine ganz andere Farbe nehmen:

Hinweis am Rande: Im macOS-Safari sorgt die Farbe übrigens für das Einfärben der Scrollleiste.