Zum Inhalt springen
OneKitly

Was ein Minifier entfernen darf und was nicht

Veröffentlicht am 19.5.2025 · 15 Min. Lesezeit · Entwickler-Tools

Daniel Okonkwo

Daniel OkonkwoFront-end-Entwickler und Tech-Redakteur bei OneKitly

Web-Performance · Dateiformate

Anhand von 6 Quellen geprüft

Profil ansehen
Kurz gesagt

Ein Minifier darf nur bedeutungserhaltende Änderungen vornehmen, und die schwierigen Fälle sind durchweg Leerräume, die keine Dekoration sind. In CSS ist das Leerzeichen in div p ein Nachfahrenkombinator: Entfernt man es, trifft der Selektor etwas völlig anderes. Die Leerzeichen um >, + und ~ dürfen weg — esbuild machte aus .card > footer die Form .card>footer und ließ .card .card-title unangetastet. Innerhalb von calc() sind die Leerzeichen um + und − Pflicht: Chrome meldet CSS.supports für calc(100% - 2px) als true und für calc(100%-2px) als false, und die Zuweisung des zweiten lässt die Eigenschaft leer. Leerzeichen um * und / sind optional. In HTML ist Leerraum zwischen Inline-Elementen gerenderter Inhalt — zwei Spans maßen mit Leerzeichen 36,92 px und ohne 27,28 px, ein Versatz von 9,64 px — und innerhalb von pre und textarea ist er vollständig signifikant. In JavaScript bedeutet die automatische Semikolon-Einfügung, dass das Zusammenziehen von Zeilen das Verhalten ändert: Eine Funktion, deren return allein auf seiner Zeile steht, liefert undefined, bis man die Zeilen verbindet — dann liefert sie das Objekt. Und Umbenennung endet an der Zeichenkettengrenze: Property-Mangling machte aus einem funktionierenden Zugriff undefined. Zum Nutzen: Bei den Assets dieser Seite sparte Brotli allein 66,2 %, und vorheriges Minifizieren brachte nur 18,1 % obendrauf.

Minifizierung muss die Bedeutung erhalten, und interessant ist der Leerraum, der Bedeutung trägt: der Nachfahrenkombinator, die Leerzeichen in calc(), der Abstand zwischen zwei Inline-Elementen. Hier an echten Dateien gemessen, samt dem, was Brotli ohnehin gespart hätte.

Die einzige Regel: die Ausgabe muss sich identisch verhalten

Minifizierung ist ein Compilerdurchlauf mit einem einzigen Vertrag: Die Ausgabe muss beobachtbar identisch zur Eingabe sein. Nicht ähnlich, nicht nah genug — identisch in jedem Verhalten, auf das sich eine Seite stützen kann. Alles, was ein Minifier tut, folgt daraus, und jeder Minifizierungsfehler ist eine Stelle, an der jemand ein Byte für Dekoration hielt, obwohl die Spezifikation es als Daten führt.

Diese Unterscheidung erklärt, warum Minifier auf Basis regulärer Ausdrücke gefährlich sind und parserbasierte nicht. Ein Werkzeug, das Leerraum per Muster entfernt, weiß nicht, ob ein bestimmtes Leerzeichen zwei Token zur Lesbarkeit trennt oder zwei Token zu einer zusammengesetzten Bedeutung verbindet. Ein Werkzeug, das die Eingabe nach dem CSS-Syntax-Modul oder der ECMAScript-Grammatik tokenisiert, einen Baum baut und ihn neu ausgibt, kann den Fehler gar nicht machen: Wenn es etwas druckt, steht die Bedeutung im Baum längst fest.

Alles Folgende wurde ausgeführt, nicht erinnert. Die Beispiele wurden mit esbuild minifiziert, die Größen mit Nodes zlib bei gzip-Stufe 9 und Brotli-Qualität 11 gemessen, und die CSS- und Layoutaussagen in einem headless Chrome geprüft.

CSS: das Leerzeichen, das ein Kombinator ist

In einem Selektor ist Leerraum zwischen zwei zusammengesetzten Selektoren der Nachfahrenkombinator. div p wählt jedes p in einem div; divp wählt einen nicht existierenden Elementtyp, und .card .card-title wählt ein .card-title in einem .card, während .card.card-title ein Element wählt, das beide Klassen trägt. Das Leerzeichen ist ein Token, keine Formatierung, und kein korrekter Minifier entfernt es.

Die anderen drei Kombinatoren sind Satzzeichen, ihre umgebenden Leerzeichen sind frei. Gibt man esbuild die vier Formen div p, div>p, div + p und div ~ p, kommen exakt div p, div>p, div+p und div~p zurück. Das Nachfahren-Leerzeichen überlebte, die um >, + und ~ nicht, denn diese Zeichen sind für sich eindeutig. Im Beispielstylesheet geschah dasselbe mit echten Regeln: .card .card-title kam unverändert durch, während .card > footer, .card + .card und .card ~ .aside-note enger wurden.

Der At-Regel-Fall ist feiner und lohnt einen Blick. Die Media Query @media (min-width: 600px) and (max-width: 900px) kam als @media(min-width:600px)and (max-width:900px) heraus. Das Leerzeichen vor and verschwand, denn eine schließende Klammer beendet das vorige Token bereits. Das Leerzeichen nach and blieb, denn and( würde als Funktionstoken statt als Bezeichner mit folgender Klammer tokenisiert. Die ganze Disziplin in einer Zeile: Ein Leerzeichen ist genau dann entfernbar, wenn die beiden Token links und rechts nicht zu einem anderen einzelnen Token verschmelzen können.

CSS: die Leerzeichen innerhalb von Werten

calc() ist das schärfste Beispiel, denn die Anforderung ist asymmetrisch. Die CSS-Values-Spezifikation verlangt Leerraum auf beiden Seiten von + und −, weil ein Token wie -2px sonst als einzelne negative Dimension gelesen wird und der Ausdruck seinen Operator verliert. Chrome bestätigt das genau: CSS.supports für width und calc(100% - 2px) liefert true, während calc(100%-2px), calc(100% -2px) und calc(100%- 2px) alle false liefern. Die Zuweisung style.width = calc(100%-2px) hinterlässt die Eigenschaft als leere Zeichenkette, denn die ganze Deklaration wird als ungültig verworfen.

Multiplikations- und Divisionsoperatoren haben dieses Problem nicht, und der Browser bestätigt es: calc(100%*2) und calc(100%/2) melden beide true. Ein Minifier, der die Grammatik versteht, könnte diese beiden also zusammenziehen und die anderen nicht. In der Praxis ist esbuild konservativ und behielt jedes Leerzeichen in calc(100% - 2 * var(--gap)) — richtig beim Minus, eine kleine verpasste Gelegenheit beim Stern.

Zwei weitere Kategorien unantastbaren Leerraums tauchten im selben Lauf auf. Zeichenkettenwerte sind wörtlich: Die Deklaration content: „ new “ behielt beide Paare innerer Leerzeichen, denn diese Zeichen werden ins Dokument eingefügt. Und benutzerdefinierte Eigenschaften sind Tokenströme statt geparster Werte, weshalb esbuild --card-bg: #ffffff das Leerzeichen nach dem Doppelpunkt ließ, während es dasselbe Leerzeichen aus color: var(--card-fg) entfernte. Der Rest des Beispiels zeigt, was ein Minifier gewinnt, wenn er die Wertgrammatik versteht: rgba(0, 0, 0, 0.08) wurde #00000014, #0000ff wurde #00f, 150ms wurde .15s, opacity 0.7 wurde .7, margin: 0 0 8px 0 wurde margin:0 0 8px, und ::after wurde :after.

HTML: Leerraum zwischen Inline-Elementen ist Inhalt

Die CSS-Leerraumverarbeitung reduziert eine Folge von Leerzeichen im normalen Fluss auf ein einzelnes Leerzeichen — aber auf ein Leerzeichen, nicht auf nichts. Zwischen zwei Inline-Elementen wird dieses Leerzeichen gerendert und belegt Breite, sein Löschen verschiebt also das Layout. In einem headless Chrome bei 16 px Monospace gemessen, endeten zwei benachbarte Spans, die in der Quelle durch einen Zeilenumbruch getrennt waren, bei x = 36,92, während dieselben zwei Spans ohne Leerraum dazwischen bei x = 27,28 endeten. Der Unterschied von 9,64 px ist genau ein Leerzeichen und macht den Unterschied zwischen einer Linkzeile, die one two three liest, und einer, die onetwothree liest.

Deshalb sind aggressive HTML-Minifier konfigurierbar und ihre Voreinstellungen meist vorsichtig. Fünf Leerzeichen und zwei Zeilenumbrüche auf ein Leerzeichen zu reduzieren ist im normalen Fluss immer sicher. Das letzte verbliebene Leerzeichen zwischen zwei Inline-Boxen zu löschen ist es nicht, und ein Minifier, der das pauschal tut, formatiert Menüs, Brotkrumenpfade, Tag-Listen und Inline-Icons stillschweigend um. Jedes Werkzeug, das anbietet, Leerraum zwischen Tags zu entfernen, bietet an, dein Layout gegen Bytes einzutauschen.

Zwei Elemente sind absolut tabu: pre und textarea. Beide haben standardmäßig white-space: pre, jedes Leerzeichen, jeder Tabulator und jeder Zeilenumbruch darin bleibt also erhalten und wird gerendert. Die Beispielseite enthält einen eingerückten Codeblock und ein Textarea mit bedeutsamen führenden Leerzeichen, und der für die Messung genutzte Leerraum-Kollabierer brauchte für beide eine ausdrückliche Ausnahme. Jeder Minifier ohne diese Ausnahme zerstört Codebeispiele und vorausgefüllte Formularfelder stillschweigend. Dieselbe Sorgfalt gilt innerhalb von script- und style-Elementen sowie für den führenden Zeilenumbruch direkt nach einem öffnenden pre-Tag, den der HTML-Parser laut Spezifikation verwirft — eine Feinheit, die selbstgebaute Werkzeuge in beide Richtungen falsch macht.

JavaScript: automatische Semikolon-Einfügung und Umbenennung

ECMAScript fügt an bestimmten Zeilenumbrüchen Semikolons ein, was einen Zeilenumbruch bedeutungstragend macht. Der kanonische Fall ist ein return allein auf seiner Zeile. Die Ausführung von function f(){ return \n { ok: true } } lieferte undefined, weil direkt nach return ein Semikolon eingefügt wird. Derselbe Code auf einer Zeile lieferte { ok: true }. Ein naiver Minifier, der Zeilen zusammenzieht, ändert also den Rückgabewert der Funktion. Die Gegenrichtung beißt ebenfalls: Der Ausschnitt let x = 1 \n ++x wertet x zu 2 aus, während das Zusammenziehen dieser beiden Zeilen SyntaxError: Invalid left-hand side expression in postfix operation wirft.

Ein parserbasierter Minifier kann keinen der beiden Fehler machen, denn beim Drucken ist das Semikolon längst entschieden. Gibt man dieselbe Funktion mit isoliertem return an esbuild, entsteht function t(){}export const r=void 0; — er erhielt die Semantik, sah, dass die Funktion nur undefined liefern kann, und faltete den Aufruf zu void 0. Das ist der Unterschied zwischen einer Texttransformation und einem Compiler.

Die andere JavaScript-Gefahr ist die Umbenennung, und ihre Grenze ist exakt: Ein Minifier darf alles umbenennen, dessen sämtliche Referenzen er sieht, und sonst nichts. Lokale Variablen und Funktionsparameter zählen dazu, und daher stammt der Großteil der Ersparnis. Objekteigenschaftsnamen nicht, denn eine Eigenschaft kann über eine Zeichenkette erreicht werden, der der Minifier nicht folgen kann. Vorgeführt: Ein Modul, das [config.userName, o[userName], o[retryCount]] zurückgab, lieferte bei einfacher Minifizierung [ada, ada, 3] und nach Einschalten des Property-Manglings [ada, undefined, undefined]. Der Punktzugriff wurde mit der Definition umbenannt; die beiden Zeichenkettenzugriffe fragten weiter nach den alten Namen und fanden nichts. Dieselbe Falle erwischt alles, was zur Laufzeit über den Namen erreicht wird — aus einer Variablen gebauter Klammerzugriff, JSON-Umwege, Framework-Bindungen und direktes eval.

Gemessen: was Minifizierung nach der Kompression wert ist

Minifizierung und Kompression entfernen überlappende Redundanz, deshalb wirkt die zweite von beiden immer weniger eindrucksvoll. An den handgeschriebenen Beispielen: Das CSS ging von 1 434 auf 1 066 Byte, ein Minus von 25,7 %, nach Brotli standen aber 552 gegen 459 — nur 16,8 %. Das JavaScript ging von 1 518 auf 747 Byte, ein Minus von 50,8 %, nach Brotli 552 gegen 395, also 28,4 %. Das HTML ging von 1 033 auf 782 Byte, 24,3 %, nach Brotli 322 gegen 302 — 6,2 % oder zwanzig Byte.

Fasst man die drei zu einer Seitennutzlast zusammen, liegt die ehrliche Zahl auf dem Tisch. Die rohen Assets summieren sich auf 3 985 Byte, Brotli bringt sie auf 1 346 — 66,2 % Ersparnis allein durch Kompression, ohne Buildschritt. Erst minifizieren, dann komprimieren ergibt 1 102 Byte. Der Grenzbeitrag der Minifizierung über eine ohnehin vorhandene Kompressionsschicht beträgt also 244 Byte: 18,1 %. Real und mitnehmenswert, aber eine Größenordnung unter dem, was die Rohbytezahl nahelegt.

Vier echte Dateien aus diesem Repository zeigen, wie stark die Antwort vom Inhalt abhängt. globals.css schrumpfte roh um 68,2 % und nach Brotli um 70,2 % — spektakulär, und vollständig dadurch erklärt, dass 2 084 seiner 3 393 Byte Kommentare sind, wobei alle dreizehn Regelblöcke auf beiden Seiten erhalten bleiben. app-shell.module.css, das überwiegend aus echten Deklarationen besteht, ergab roh 4,4 % und nach Brotli 5,8 %. Zwei inhaltsschwere TypeScript-Module ergaben roh 10,8 % und 6,5 %, nach Brotli aber nur 3,4 % und 2,3 %, denn eine Datei aus überwiegend Zeichenkettenliteralen enthält kaum etwas, das ein Minifier anfassen darf. Faustregel: Minifizierung zahlt sich im Verhältnis dazu aus, wie viel deiner Datei Kommentare, Einrückung und lange lokale Bezeichner sind, und gar nicht auf Daten.

Eine funktionierende Reihenfolge

Schalte zuerst die Kompression ein, denn sie ist der größte Einzelgewinn, braucht keinen Buildschritt und kann nichts kaputt machen. An diesen Beispielen entfernte Brotli allein 66,2 % der Bytes. Minifiziere danach mit einem parserbasierten Werkzeug je Sprache in dessen Voreinstellungen. Greife dann, nur bei gemessenem Grund, zu den aggressiven Optionen — Property-Mangling, Leerraumentfernung zwischen Tags — und behandle jede als Änderung, die getestet werden muss, denn jede ist eine Stelle, an der der Vertrag der Bedeutungserhaltung bewusst gelockert wurde.

Zwei Gewohnheiten sind mehr wert als jede Minifier-Einstellung. Entferne Kommentare und toten Code an der Quelle, statt darauf zu bauen, dass der Minifier sie bemerkt — globals.css bestand zu 61 % aus Kommentaren, und diese eine Tatsache erklärt seine gesamte Reduktion von 68 %. Und prüfe die Ausgabe, nicht das Versprechen: Schick das minifizierte Bündel durch deine Testsuite und vergleiche die komprimierten Größen beider Seiten statt der rohen, denn die Rohzahl schmeichelt, und die komprimierte ist die, die deine Nutzer tatsächlich herunterladen.

Über esbuild laufen gelassene Transformationen an Beispielstylesheet und -modul, jeweils mit Verdikt
VorherNachherSicher?Warum
.card > footer.card>footerJaDas > ist für sich eindeutig; die Leerzeichen tragen nichts
.card .card-title.card .card-title (unverändert)Darf sich nicht ändernDas Leerzeichen ist der Nachfahrenkombinator; ohne es wird ein Element mit beiden Klassen gewählt
calc(100% - 2px)calc(100% - 2px) (unverändert)Darf sich nicht ändernChrome meldet calc(100%-2px) als nicht unterstützt und verwirft die Deklaration
content: „ new “content:„ new “ (Leerzeichen behalten)Darf sich nicht ändernZeichenketteninhalte werden wörtlich ins Dokument eingefügt
rgba(0, 0, 0, 0.08)#00000014JaAchtstelliges Hex stellt exakt dieselbe Farbe dar
margin: 0 0 8px 0margin:0 0 8pxJaDie Kurzform spiegelt den zweiten Wert, wenn der vierte fehlt
return allein auf seiner ZeileZeilenumbruch von einem Textwerkzeug entferntNeinDie Funktion lieferte vorher undefined und danach das Objekt
o.userName und o[userName]Property-Mangling benennt nur das erste umNeinDas gemessene Ergebnis ging von [ada, ada, 3] auf [ada, undefined, undefined]
CSS-KompressorMinifiziere CSS durch Entfernen von Kommentaren und Leerraum, um die Stylesheet-Größe zu senken.Tool ausprobieren

Häufige Fragen

Wenn mein Server schon gzip oder Brotli sendet, muss ich noch minifizieren?
Ja, aber erwarte einen weit kleineren Gewinn, als die Rohzahlen nahelegen, und bring zuerst die Kompression zum Laufen. An der Beispielseite gemessen brachte Brotli allein 3 985 Byte roher Assets auf 1 346 — 66,2 % Ersparnis ganz ohne Buildschritt. Minifizieren vor dem Komprimieren erreichte 1 102 Byte, der Grenzbeitrag der Minifizierung lag also bei 244 Byte oder 18,1 % obendrauf. Das lohnt sich und kostet pro Anfrage nichts, sobald der Build es erledigt. Beide überlappen, weil sie dieselbe Redundanz angreifen: wiederholte lange Bezeichner, Einrückungsfolgen und Kommentartext sind genau das, was ein Wörterbuchkompressor am besten beseitigt. Klar gewinnt Minifizierung dort, wo Kompression nicht hinkommt, weil es semantisch statt textuell ist — Beseitigung toten Codes, Konstantenfaltung, Entfernen unerreichbarer Zweige, Kürzen von Farb- und Einheitensyntax. Die Reihenfolge zählt: Kompression an, dann minifizieren, dann die komprimierten Größen messen, nicht die rohen.
Mein Layout hat sich nach dem Einschalten der HTML-Minifizierung verschoben. Warum?
Mit ziemlicher Sicherheit, weil der Minifier Leerraum zwischen Inline-Elementen entfernt hat, der gerenderter Inhalt und keine Formatierung ist. Die CSS-Leerraumverarbeitung reduziert eine Folge von Leerzeichen und Zeilenumbrüchen im normalen Fluss auf ein Leerzeichen — eines, nicht null —, und dieses überlebende Leerzeichen belegt Breite zwischen zwei Inline-Boxen. In einem headless Chrome bei 16 px Monospace gemessen endeten zwei Spans mit einem Zeilenumbruch dazwischen bei x = 36,92 und dasselbe Paar ganz ohne Leerraum bei x = 27,28: 9,64 px Unterschied, genau ein Leerzeichen. Über eine Navigationsleiste, eine Tag-Liste oder eine Zeile Inline-Links hinweg ist dieser Unterschied sofort sichtbar und wirkt wie ein Fehler. Suche nach einer Option in der Art von collapseWhitespace mit aggressivem oder konservativem Modus und wähle den konservativen. Willst du keinen Abstand zwischen zwei Inline-Elementen, entferne ihn in CSS mit einem Flex- oder Grid-Container oder über font-size am Elternelement, damit das Markup unabhängig vom Layout bleibt.
Ist es je sicher, Objekteigenschaften umzubenennen?
Nur wenn du garantieren kannst, dass jeder Zugriff auf die Eigenschaft für den Minifier sichtbar ist — praktisch heißt das, eine Namenskonvention einzuführen und dem Werkzeug mitzuteilen. Das übliche Muster ist, nur Eigenschaften mit einem Muster wie einem abschließenden Unterstrich zu mangeln, sodass interne Felder umbenannt werden und alles Öffentliche unberührt bleibt. Kaputt macht es jeder Zugriff über eine Zeichenkette. Hier vorgeführt: Ein Modul, das [config.userName, o[userName], o[retryCount]] zurückgab, lieferte bei gewöhnlicher Minifizierung [ada, ada, 3] und nach Aktivierung des Property-Manglings [ada, undefined, undefined] — der Punktzugriff wanderte mit der Definition, die beiden Zeichenkettenzugriffe nicht. Derselbe Fehlermodus umfasst aus einer Variablen gebauten Klammerzugriff, aus JSON stammende Schlüssel, Framework-Templates, die über den Namen binden, und alles, was mit Object.keys durchlaufen wird. Weil der Bruch still ist und nur auf dem Codepfad auftaucht, der die Zeichenkette nutzt, behandle Property-Mangling als Optimierung, die einen vollständigen Testlauf verlangt, nicht als Häkchen.
Kann ich einen Minifier mit regulären Ausdrücken schreiben?
Du kannst etwas schreiben, das meistens funktioniert, und das ist das schlechtestmögliche Ergebnis, denn die Fehlschläge sind selten und still. Ein Muster, das Leerraumfolgen entfernt, unterscheidet einen Nachfahrenkombinator nicht von Einrückung, weiß nicht, dass das Leerzeichen vor einem Minus in calc() grammatisch verlangt ist, sieht nicht, dass ein Zeilenumbruch vor einer schließenden Klammer ein return zu undefined macht, und weiß nicht, dass die Zeichen in einer Zeichenkette Inhalt sind. Jede dieser Unterscheidungen erfordert eine Tokenisierung nach der echten Grammatik. Der für die HTML-Messung dieses Artikels benutzte Leerraum-Kollabierer ist bewusst naiv, und er brauchte eine ausdrückliche Ausnahme für pre und textarea, bevor er überhaupt korrekte Ausgabe lieferte — und wäre auf einer Seite mit Inline-Skripten, die spitze Klammern in Zeichenketten enthalten, weiterhin unsicher. Die praktische Antwort: Nimm pro Sprache ein parserbasiertes Werkzeug und stecke deine Mühe in die Eingabe — weniger ausgelieferte Kommentare, kein toter Code, kürzere lokale Namen dort, wo sie der Lesbarkeit nicht schaden.
Warum hat das Minifizieren meiner datenlastigen Datei kaum geholfen?
Weil ein Minifier nur Syntax anfassen darf und eine Datendatei fast ausschließlich Inhalt ist. Zeichenkettenliterale müssen Byte für Byte überleben, zur Laufzeit genutzte Objektschlüssel dürfen nicht umbenannt werden, und Zahlen sind bereits so kurz, wie sie werden. Die Messungen dieses Artikels zeigen das Muster deutlich: Zwei inhaltsschwere TypeScript-Module aus diesem Repository schrumpften roh um 10,8 % und 6,5 %, nach Brotli aber nur um 3,4 % und 2,3 %, denn das Wenige, was die Minifizierung entfernte, waren Einrückung und Satzzeichen, die der Kompressor ohnehin zusammengedrückt hätte. Vergleiche das mit globals.css, das um 68,2 % schrumpfte — vollständig deshalb, weil 2 084 seiner 3 393 Byte Kommentare waren. Ist eine Datendatei wirklich groß, liegt der Hebel nicht in der Minifizierung, sondern in Format und Auslieferung: Leg die Daten hinter eine API, damit Seiten nur holen, was sie zeigen, teile sie auf, damit eine Route ihren eigenen Ausschnitt lädt, oder hol sie aus dem JavaScript-Bündel in JSON, das der Browser schneller parst und separat cacht.

Artikel, die dich interessieren könnten

Alle Ratgeber
RatgeberVerschönern oder minifizieren: wofür beides gut ist und was es am Gewicht ändertVier echte Stylesheets durch den Minifier, roh und nach gzip gemessen. Alle Leerzeichen zu entfernen sparte 48, 103, 104 und 147 komprimierte Bytes; die Kommentare zu entfernen 57, 1 358, 2 420 und 1 042. Dazu die fünf Eingaben, an denen dieser Minifier scheitert.AnleitungHEX vs. RGB: Farben lesen und umrechnenHEX und RGB sind zwei Schreibweisen für dieselben Farben. Hier steht, wie du jede liest, umrechnest und Transparenz hinzufügst.ErklärungVerläufe, Banding und warum die Mitte matschig aussiehtIn sRGB zu interpolieren mittelt gammacodierte Zahlen: Die Mitte von Rot nach Grün ist #808000, obwohl die Halblicht-Antwort #bcbc00 lautet — 57,2 % zu wenig Licht. Banding ist ein eigenes Rechenproblem: 8 Bit ergeben 256 Stufen, und ein dunkler Verlauf hat womöglich nur 28. Hier sind beide, durchgerechnet.ErklärungFarbschemata sind Geometrie auf einem Kreis — und der Kreis stimmt nichtKomplementär, Triade, Analog und geteilt-komplementär sind bloß Drehungen: addiere 180°, 120°, 30° oder 150° zu einem Farbton. Die Arithmetik ist trivial. Das Problem ist, dass der HSL-Farbtonkreis nicht wahrnehmungsgleichmäßig ist — Gelb und Blau bei gleicher HSL-Helligkeit unterscheiden sich um den Faktor 12,85 in der Leuchtdichte — eine erzeugte Palette muss also anschließend auf Kontrast geprüft werden.ErklärungKontrastverhältnis: wie die WCAG es tatsächlich berechnetDas WCAG-Verhältnis lautet (L1 + 0,05) ÷ (L2 + 0,05), und L ist die relative Leuchtdichte, nicht die Helligkeit. Grün trägt 71,52 % davon und Blau 7,22 % — deshalb besteht reines Blau auf Weiß mit 8,59:1, während mittleres Grau mit 3,95:1 durchfällt. Hier ist die ganze Rechnung, von Anfang bis Ende durchgeführt.ErklärungWie Instagram-Schriften wirklich funktionieren (es sind keine Schriften)Nichts wird formatiert. Jeder Buchstabe wird durch ein anderes Unicode-Zeichen ersetzt, das zufällig fett oder kursiv aussieht — weshalb ein Screenreader Kauderwelsch vorliest und manche Geräte leere Kästchen zeigen.

Ähnliche Tools

Quellen

Hast du einen Fehler in diesem Artikel entdeckt?