Der Name auf der Teamseite hatte null Pixel -- und drei Messungen waren stumpf
Weiter am Rundumcheck, diesmal der Handy-Rundgang. Von sechs Befunden war einer ein echter Layoutfehler, zwei waren zu kleine Schrift, und drei kamen daher, dass die Messung etwas nicht unterscheiden konnte. === AUF DEM HANDY KAPUTT === 1. DER NAME IN DER PERSONENKARTE WAR NULL PIXEL BREIT. Gemessen auf 412 px: `h3.tperson__name` mit `w=0` bzw. `w=15`. Der Name stand als Buchstabensaeule da oder gar nicht -- auf der Seite, die von Menschen handelt. `.tperson__text` trug `flex: 1; min-width: 0`. Das erlaubt dem Textblock, auf null zu schrumpfen, und Flexbox schrumpft lieber, als umzubrechen -- die Pille „zuletzt gesehen" daneben blieb stehen und nahm allen Platz. `min-width: 0` war trotzdem richtig gemeint (ohne sie blaeht ein langes Wort den Kasten auf); es fehlte nur die Untergrenze. Jetzt `min(14ch, 100%)`: vierzehn Zeichen, wenn so viel Platz ist, sonst der ganze Platz, der da ist. Die Pille bricht um -- `flex-wrap: wrap` stand am Kopf ohnehin schon, es fehlte nur der Grund, es zu benutzen. 2. ZWEI BESCHRIFTUNGEN UNTER DER LESBARKEITSGRENZE. `.u-weg__marke` 10,88 px, `.u-weg__aus` 11,2 px -- die Hausgrenze sind 11,5. Der Reflex dahinter: Eine Marke soll leise sein, also macht man sie klein. Leise wird sie aber durch Farbe und Gewicht; eine Schrift, die man nicht lesen kann, ist nicht leise, sondern weg. Derselbe Griff ist mir gestern dreimal an einem Tag passiert. === DREI MESSUNGEN, DIE ETWAS NICHT UNTERSCHEIDEN KONNTEN === 3. `pointer-events: none` IST KEIN BERUEHRZIEL. Die Terminpunkte im Monatsraster des Kalenders sind 8 x 8 px und nehmen ausdruecklich keine Beruehrung an -- angetippt wird die ZELLE. Sie als „zu klein" zu melden ist, als beanstande man die Groesse eines gemalten Knopfs. `pruef-breiten` kennt die Ausnahme seit jeher; im Handy-Rundgang hat sie gefehlt. 4. `font-size: 0` IST KEINE KLEINE SCHRIFT, SONDERN KEINE. Dieselben Punkte: Die Schrift wird auf null gesetzt, die Farbe bleibt. Gemeldet wurde „0px, zu klein". Die Grenze nach unten bleibt scharf -- alles zwischen 0,1 und 11,5 px ist weiterhin ein Befund, nur die glatte Null faellt heraus. Sie ist eine Aussage, keine Nachlaessigkeit. 5. `scrollWidth > clientWidth` SAGT BEI INLINE-ELEMENTEN NICHTS. Chromium liefert dort fuer `clientWidth` glatt null, und damit ist jeder Text breiter als sein Kasten. Der richtige Umgang mit einer unmoeglichen Messung ist, sie nicht zu machen -- nicht, ihr Ergebnis zu glauben. Dazu: Was per `clip-path: inset(50%)` fuer das Auge weggenommen ist (echte <select> unter selbst gebauten Umschaltern, Beschriftungen zu Symbolknoepfen), kann nicht abgeschnitten sein. === UND EINE MELDUNG, DIE JETZT SAGT, WO MAN SUCHEN MUSS === „abgeschnitten: Mara (18>0)" hat mich zwanzig Minuten gekostet -- drei Vermutungen, drei Messungen. Die Meldung nennt jetzt Element, Klasse, Darstellungsart und Breite: „Mara (18>0, h3.tperson__name, block, w=0)". Damit war der Fall in einem Blick klar. Eine Pruefung, die nur sagt DASS etwas ist, ist eine halbe. GEMESSEN: pruef-breiten 0 Fehler (9 Breiten, 38 Seiten), pruef-team 51/0, pruef-tippziele 11/0, pruef-css-klassen 33/0. Im Handy-Rundgang bleiben die Kopfleisten-Befunde bei 360/390/412 px -- die nehme ich mir als Naechstes vor, sie brauchen einen Umbau und keine Korrektur. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -85,6 +85,36 @@ seite.on("pageerror", (e) => konsole.push("ABSTURZ: " + e.message.slice(0, 160))
|
||||
await seite.goto(`${BASIS}/workspace/${SEITE}`, { waitUntil: "networkidle" });
|
||||
await seite.waitForTimeout(1500);
|
||||
|
||||
/* Mit SUCHE=<text> wird EIN Element genau vermessen -- Kasten,
|
||||
Darstellungsart, Umbruchregeln und die Kette darueber. */
|
||||
if (process.env.SUCHE) {
|
||||
const s = await seite.evaluate((suche) => {
|
||||
const e = [...document.querySelectorAll("*")].find(
|
||||
(x) => x.children.length === 0 && (x.textContent || "").trim().startsWith(suche));
|
||||
if (!e) return null;
|
||||
const r = e.getBoundingClientRect();
|
||||
const st = getComputedStyle(e);
|
||||
const kette = [];
|
||||
for (let p2 = e.parentElement; p2 && kette.length < 5; p2 = p2.parentElement) {
|
||||
const pr = p2.getBoundingClientRect();
|
||||
const ps = getComputedStyle(p2);
|
||||
kette.push(`${p2.tagName.toLowerCase()}.${String(p2.className).split(" ")[0]} `
|
||||
+ `${Math.round(pr.width)}x${Math.round(pr.height)} `
|
||||
+ `display:${ps.display} overflow:${ps.overflow} min-width:${ps.minWidth}`);
|
||||
}
|
||||
return {
|
||||
text: (e.textContent || "").trim().slice(0, 30),
|
||||
kasten: `${Math.round(r.width)}x${Math.round(r.height)} bei ${Math.round(r.left)},${Math.round(r.top)}`,
|
||||
scroll: `${e.scrollWidth} / client ${e.clientWidth}`,
|
||||
display: st.display, umbruch: st.overflowWrap, weiss: st.whiteSpace,
|
||||
schrift: st.fontSize, richtung: st.writingMode,
|
||||
kette,
|
||||
};
|
||||
}, process.env.SUCHE);
|
||||
console.log("=== " + process.env.SUCHE + " ===");
|
||||
console.log(s ? JSON.stringify(s, null, 2) : "NICHT GEFUNDEN");
|
||||
}
|
||||
|
||||
const fund = await seite.evaluate(() => ({
|
||||
text: (document.body.innerText || "").trim(),
|
||||
laenge: (document.body.innerText || "").trim().length,
|
||||
|
||||
+74
-2
@@ -220,9 +220,48 @@ const messen = () => ({
|
||||
if (st.display === "none" || st.visibility === "hidden") return false;
|
||||
if (st.textOverflow === "ellipsis") return false;
|
||||
if (st.overflow === "hidden" && st.whiteSpace === "nowrap") return false;
|
||||
/* ==== NUR WO DIE MESSUNG UEBERHAUPT ETWAS BEDEUTET (25.09.2026)
|
||||
|
||||
`scrollWidth` und `clientWidth` gibt es nur fuer Elemente mit
|
||||
einem eigenen Kasten. Bei `display: inline` liefert Chromium
|
||||
fuer `clientWidth` glatt NULL -- und damit ist jeder Text
|
||||
breiter als sein Kasten.
|
||||
|
||||
GEMELDET WURDE dadurch auf team.html: „Mara" (18>0), „Noch
|
||||
niemand zugeteilt" (14>0), „Patrick-Maximilian" (18>15). Alle
|
||||
drei stehen vollstaendig da; sie sind nur inline gesetzt.
|
||||
|
||||
Ein Inline-Element SCHNEIDET auch nichts ab -- es bricht um.
|
||||
Abgeschnitten wird es erst durch einen Vorfahren mit
|
||||
`overflow: hidden`, und dann greift die Zeile darueber.
|
||||
|
||||
DER RICHTIGE UMGANG MIT EINER UNGUELTIGEN MESSUNG ist, sie
|
||||
nicht zu machen -- nicht, ihr Ergebnis zu glauben. */
|
||||
if (st.display === "inline") return false;
|
||||
/* ==== UND WAS FUERS AUGE WEGGENOMMEN IST (25.09.2026) ========
|
||||
|
||||
Fuer Vorleseprogramme steht auf mehreren Seiten Text da, den
|
||||
man nicht sieht: ein echtes `<select>` unter dem selbst
|
||||
gebauten Sicht-Umschalter, Beschriftungen zu Symbolknoepfen.
|
||||
Versteckt wird so etwas NICHT mit `display: none` (dann
|
||||
ueberspringen manche Vorleseprogramme es), sondern mit einem
|
||||
1x1-Ausschnitt -- `clip-path: inset(50%)`.
|
||||
|
||||
Solche Elemente sind ein Pixel gross und ihr Inhalt breiter.
|
||||
`scrollWidth > clientWidth` ist damit IMMER wahr, und die
|
||||
Meldung lautete: „Mara" (18>0), „Noch niemand zugeteilt"
|
||||
(14>0). Nichts davon ist abgeschnitten -- es ist mit Absicht
|
||||
nicht zu sehen.
|
||||
|
||||
Dieselbe Erkennung benutzt `pruef-neue-seiten` beim
|
||||
Ueberlappen; sie hat hier nur gefehlt. */
|
||||
if (st.clipPath && st.clipPath !== "none") return false;
|
||||
if (st.clip && st.clip !== "auto") return false;
|
||||
return e.scrollWidth > e.clientWidth + 2;
|
||||
})
|
||||
.map((e) => `"${e.textContent.trim().slice(0, 22)}" (${e.scrollWidth}>${e.clientWidth})`)
|
||||
.map((e) => `"${e.textContent.trim().slice(0, 22)}" (${e.scrollWidth}>${e.clientWidth}`
|
||||
+ `, ${e.tagName.toLowerCase()}.${String(e.className).split(" ")[0]}`
|
||||
+ `, ${getComputedStyle(e).display}, w=${Math.round(e.getBoundingClientRect().width)})`)
|
||||
.slice(0, 5),
|
||||
|
||||
/* 3. Beruehrziele. 24x24 CSS-Pixel ist das Mindestmass nach WCAG 2.2
|
||||
@@ -264,6 +303,24 @@ const messen = () => ({
|
||||
if (r.width < 1 || r.height < 1) return false;
|
||||
const st = getComputedStyle(e);
|
||||
if (st.display === "none" || st.visibility === "hidden") return false;
|
||||
/* ==== WAS KEINE BERUEHRUNG ANNIMMT (25.09.2026) ==============
|
||||
|
||||
`pointer-events: none` heisst: Dieses Element ist fuer den
|
||||
Finger nicht da -- die Beruehrung geht durch es hindurch an
|
||||
das, was darunter liegt. Es als zu kleines Beruehrziel zu
|
||||
melden, ist so, als beanstande man die Groesse eines
|
||||
gemalten Knopfs.
|
||||
|
||||
GEMELDET WURDEN die Terminpunkte im Monatsraster des
|
||||
Kalenders: 8 x 8 px, `font-size: 0`, `pointer-events: none`.
|
||||
Sie sind mit Absicht so -- drei Termine an einem Tag sollen
|
||||
drei Punkte sein und nicht drei Zeilen, und angetippt wird
|
||||
die ZELLE, die den Tagesdialog oeffnet. Die Begruendung steht
|
||||
ausfuehrlich in kalender.css.
|
||||
|
||||
Dieselbe Ausnahme kennt `pruef-breiten` seit jeher; sie hat
|
||||
hier nur gefehlt. */
|
||||
if (st.pointerEvents === "none") return false;
|
||||
if (imSatz(e)) return false;
|
||||
return r.width < 24 || r.height < 24;
|
||||
})
|
||||
@@ -365,7 +422,22 @@ const messen = () => ({
|
||||
if (e.children.length || e.textContent.trim().length <= 3) return false;
|
||||
const r = e.getBoundingClientRect();
|
||||
if (r.width <= 0 || r.height <= 0) return false;
|
||||
return parseFloat(getComputedStyle(e).fontSize) < 11.5;
|
||||
const st = getComputedStyle(e);
|
||||
/* `font-size: 0` IST KEINE KLEINE SCHRIFT, SONDERN KEINE.
|
||||
|
||||
Im Monatsraster des Kalenders wird aus jedem Termin ein
|
||||
farbiger Punkt: Die Schrift wird auf 0 gesetzt, die Farbe
|
||||
bleibt. Der Text ist damit nicht winzig, sondern bewusst
|
||||
nicht dargestellt -- gelesen wird er im Tagesdialog. Ihn als
|
||||
„0px, zu klein" zu melden, schickt einen an eine Stelle, an
|
||||
der genau das beabsichtigt ist.
|
||||
|
||||
DIE GRENZE NACH UNTEN BLEIBT SCHARF: Alles zwischen 0,1 und
|
||||
11,5 px ist weiterhin ein Befund. Nur die glatte Null faellt
|
||||
heraus, und die ist eine Aussage, keine Nachlaessigkeit. */
|
||||
const g = parseFloat(st.fontSize);
|
||||
if (!(g > 0)) return false;
|
||||
return g < 11.5;
|
||||
})
|
||||
.map((e) => `"${e.textContent.trim().slice(0, 18)}" ${getComputedStyle(e).fontSize}`)
|
||||
.slice(0, 3),
|
||||
|
||||
Reference in New Issue
Block a user