B2: Die Regeln sind eine Flaeche statt sechs Kacheln
"lass bitte die ganzen regeln viel geiler und spezieller aussehen und nicht sehr viele kacheln sondern eine riesige wo alles schön aussieht und richtig geil, übersichtlich" Vorher sechs Kaesten untereinander: jeder mit Rand, Grund und Abstand, dazwischen jedes Mal ein Schnitt. Beim Lesen faengt man damit sechsmal neu an -- Regeln lesen sich aber als EIN Text, nicht als sechs Merkzettel. JETZT EINE FLAECHE. Die Abschnitte bleiben, ihre Kaesten nicht: innerhalb der Flaeche trennt eine Linie statt einer Luecke. Dazu ein Schein in der Hausfarbe oben links, der nach einem Drittel ausgelaufen ist -- Text auf einem Verlauf liest sich unruhig, und diese Flaeche ist zum Lesen da. UEBERSICHTLICH HEISST: EINE SPRUNGLEISTE. Eine lange Flaeche ohne Wegweiser ist nicht uebersichtlicher als sechs Kaesten, nur laenger. Die Leiste klebt oben, nennt alle Abschnitte und hebt den hervor, in dem man gerade steht (IntersectionObserver -- beim Rollen zu rechnen kostet auf einem Handy spuerbar Strom). SIE WIRD GELESEN, NICHT GEPFLEGT: Die Eintraege kommen aus den Ueberschriften, die ohnehin dastehen, und fehlende ids entstehen dabei. Eine Liste von Hand waere die, die beim siebten Abschnitt fehlt -- und niemand merkte es, weil die Seite ja funktioniert. Die fuenf Regeln tragen ihre Zahl jetzt in einem eigenen Kreis. Die wichtigste Liste der Seite sah aus wie jede andere Aufzaehlung. ZWEI DINGE, DIE ERST DAS BILDSCHIRMFOTO GEZEIGT HAT 1. AUF DEM HANDY BRAUCHTE DIE LEISTE SECHS ZEILEN -- rund ein Drittel des Bildes, und sie klebt oben fest, also dauerhaft. Ein Wegweiser, der mehr Platz braucht als der Weg, ist keiner. Jetzt eine Zeile, die man seitlich schiebt, mit scroll-snap. Am Rechner bleibt der Umbruch: Dort ist Platz, und alles auf einen Blick schlaegt alles hinter einer Schiebebewegung. 2. DANACH WAR SIE GANZ WEG -- hinter der Kopfleiste. Ursache: `--kopf-hoehe` wurde nur in chat.js gemessen. Auf jeder anderen Seite galt der Rueckfallwert 64 px, und auf einem 390-px-Schirm ist die Kopfleiste rund 115 px hoch. Eine Zahl, die eine Seite misst und eine andere raet, ist schlimmer als gar keine: Auf der einen stimmt sie, auf der anderen nicht, und niemand sucht den Fehler bei einer Zahl. Die Messung steht jetzt in kopf.js -- die Datei liegt auf JEDER Seite -- und zaehlt wie vorher Kopfleiste plus Band mit dem fremden Namen, bei jeder Aenderung neu. chat.js ruft sie nur noch auf. Mitgelaufen und gruen: pruef-treff (80/0), pruef-treff-werkzeuge (73/0), pruef-chat-optik, pruef-css-klassen. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -435,3 +435,182 @@
|
||||
.zulauf__wann { margin-left: 0; }
|
||||
.zulauf__titel { flex-basis: 100%; }
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
DIE REGELN SIND EINE FLÄCHE (22.09.2026)
|
||||
=====================================================================
|
||||
|
||||
Filipe: „lass bitte die ganzen regeln viel geiler und spezieller
|
||||
aussehen und nicht sehr viele kacheln sondern eine riesige wo alles
|
||||
schön aussieht und richtig geil, übersichtlich"
|
||||
|
||||
Vorher sechs Kästen untereinander: jeder mit Rand, Grund und
|
||||
Abstand, dazwischen jedes Mal ein Schnitt. Beim Lesen fängt man
|
||||
damit sechsmal neu an — Regeln lesen sich aber als EIN Text.
|
||||
|
||||
DIE ABSCHNITTE BLEIBEN, IHRE KÄSTEN NICHT. Innerhalb der Fläche
|
||||
trennt eine Linie statt einer Lücke. Der Text steht damit in einem
|
||||
Zug, und man sieht trotzdem, wo ein Thema anfängt.
|
||||
|
||||
WARUM NICHT EINFACH ALLES UNTEREINANDER OHNE ALLES: Weil „eine
|
||||
Fläche" und „unübersichtlich" sonst dasselbe wären. Deshalb kommt
|
||||
die Sprungleiste dazu (regel-sprung, gebaut in treff-regeln.js) —
|
||||
sie ist der Preis dafür, dass die Trennung wegfällt.
|
||||
===================================================================== */
|
||||
.regelflaeche {
|
||||
position: relative;
|
||||
margin: 0 0 18px;
|
||||
padding: 4px 22px 22px;
|
||||
background:
|
||||
/* Ein Schein oben links in der Hausfarbe -- er gibt der großen
|
||||
Fläche eine Richtung, ohne dass darin gelesener Text auf einem
|
||||
Verlauf steht: Nach etwa einem Drittel ist er ausgelaufen. */
|
||||
linear-gradient(170deg,
|
||||
color-mix(in srgb, var(--akzent) 9%, transparent) 0%,
|
||||
color-mix(in srgb, var(--akzent) 3%, transparent) 18%,
|
||||
transparent 34%),
|
||||
color-mix(in srgb, var(--tinte) 94%, #ffffff 6%);
|
||||
border: 1px solid var(--rand);
|
||||
border-radius: var(--radius-klein, 12px);
|
||||
}
|
||||
@media (max-width: 620px) {
|
||||
.regelflaeche { padding: 2px 14px 16px; }
|
||||
}
|
||||
|
||||
/* ---- Die Abschnitte darin ------------------------------------------- */
|
||||
/* KEIN EIGENER KASTEN MEHR. `background: none` und nicht „dieselbe
|
||||
Farbe": Eine zweite Fläche in derselben Farbe wäre beim nächsten
|
||||
Farbwechsel eine, die nicht mitzieht. */
|
||||
.regelflaeche .treff-abschnitt {
|
||||
margin: 0;
|
||||
padding: 22px 0;
|
||||
background: none;
|
||||
border: 0;
|
||||
border-top: 1px solid color-mix(in srgb, var(--rand) 70%, transparent);
|
||||
scroll-margin-top: 90px;
|
||||
}
|
||||
/* Der erste braucht keine Linie nach oben -- darüber steht die
|
||||
Sprungleiste, die schon eine hat. */
|
||||
.regelflaeche .treff-abschnitt:first-of-type { border-top: 0; }
|
||||
|
||||
/* Die Überschrift wird größer und bekommt eine Marke davor: In einer
|
||||
durchgehenden Fläche muss sie den Anfang tragen, den vorher der
|
||||
Kastenrand getragen hat. */
|
||||
.regelflaeche .treff-abschnitt__titel {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
font-size: 1.16rem; font-weight: 700;
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
.regelflaeche .treff-abschnitt__titel::before {
|
||||
content: ""; flex: none;
|
||||
width: 4px; height: 1.05em; border-radius: 2px;
|
||||
background: linear-gradient(180deg,
|
||||
var(--akzent), color-mix(in srgb, var(--akzent) 30%, transparent));
|
||||
}
|
||||
|
||||
/* ---- Die Sprungleiste ----------------------------------------------- */
|
||||
.regelflaeche__leiste {
|
||||
position: sticky; top: var(--kopf-hoehe, 64px); z-index: 3;
|
||||
display: flex; flex-wrap: wrap; gap: 6px;
|
||||
margin: 0 -22px 0; padding: 12px 22px;
|
||||
background: color-mix(in srgb, var(--tinte) 96%, #ffffff 4%);
|
||||
border-bottom: 1px solid var(--rand);
|
||||
}
|
||||
/* AUF DEM HANDY EINE ZEILE, NICHT SECHS (22.09.2026).
|
||||
---------------------------------------------------------------------
|
||||
Im Bildschirmfoto bei 390 px brauchte die Leiste SECHS Zeilen und
|
||||
damit rund ein Drittel des Bildes -- und sie klebt oben fest, also
|
||||
dauerhaft. Ein Wegweiser, der mehr Platz braucht als der Weg, ist
|
||||
keiner.
|
||||
|
||||
Filipe zu diesem Auftrag ausdruecklich: auch auf dem Handy „richtig
|
||||
gut und einfach zu benutzen".
|
||||
|
||||
Jetzt eine Zeile, die man seitlich schiebt. `scroll-snap` laesst sie
|
||||
an den Knoepfen einrasten, damit kein halber Knopf am Rand steht,
|
||||
und der Rand rechts bleibt frei, damit man sieht, DASS es weitergeht
|
||||
-- eine Leiste, die genau am Bildrand endet, sieht aus, als waere
|
||||
sie zu Ende.
|
||||
|
||||
Am Rechner bleibt der Umbruch: Dort ist Platz, und alles auf einen
|
||||
Blick ist besser als alles hinter einer Schiebebewegung. */
|
||||
@media (max-width: 620px) {
|
||||
.regelflaeche__leiste {
|
||||
margin: 0 -14px 0; padding: 10px 14px;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
scroll-snap-type: x proximity;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.regelflaeche__leiste::-webkit-scrollbar { display: none; }
|
||||
.regelflaeche__sprung { flex: none; scroll-snap-align: start; }
|
||||
}
|
||||
.regelflaeche__sprung {
|
||||
padding: 6px 11px; border-radius: 999px;
|
||||
font-size: .78rem; font-weight: 600;
|
||||
color: var(--text-leise); text-decoration: none;
|
||||
border: 1px solid var(--rand);
|
||||
background: rgba(255, 255, 255, .03);
|
||||
/* 44 px hoch ist auf einem Handy das Mindestmaß für einen Finger --
|
||||
hier über die Zeilenhöhe erreicht, nicht über eine feste Höhe:
|
||||
So wächst der Knopf mit, wenn jemand die Schrift größer stellt. */
|
||||
line-height: 1.7; min-height: 34px;
|
||||
display: inline-flex; align-items: center;
|
||||
}
|
||||
.regelflaeche__sprung:hover {
|
||||
color: var(--text);
|
||||
border-color: color-mix(in srgb, var(--akzent) 45%, transparent);
|
||||
}
|
||||
.regelflaeche__sprung:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
|
||||
/* WO MAN GERADE IST. Gesetzt von treff-regeln.js über einen
|
||||
IntersectionObserver -- nicht beim Rollen gerechnet, das kostet auf
|
||||
einem Handy spürbar Strom. */
|
||||
.regelflaeche__sprung[data-hier="ja"] {
|
||||
color: #0a121e;
|
||||
background: color-mix(in srgb, var(--akzent) 84%, #ffffff);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
/* ---- Die fünf Regeln tragen ihre Zahl -------------------------------- */
|
||||
/* „viel geiler und spezieller": Die wichtigste Liste der Seite sah aus
|
||||
wie jede andere Aufzählung. Jetzt steht die Zahl in einem eigenen
|
||||
Kreis links daneben — dieselbe Sprache wie die Stufen an anderen
|
||||
Stellen des Hauses, und auf einem Handy sofort als Liste erkennbar. */
|
||||
.regelflaeche .regel-liste {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
counter-reset: regel;
|
||||
}
|
||||
.regelflaeche .regel-liste li {
|
||||
position: relative;
|
||||
counter-increment: regel;
|
||||
margin: 0 0 12px;
|
||||
padding: 0 0 0 40px;
|
||||
min-height: 28px;
|
||||
}
|
||||
.regelflaeche ol.regel-liste li::before {
|
||||
content: counter(regel);
|
||||
position: absolute; left: 0; top: 0;
|
||||
width: 28px; height: 28px; border-radius: 50%;
|
||||
display: grid; place-items: center;
|
||||
font-size: .8rem; font-weight: 700;
|
||||
color: color-mix(in srgb, var(--akzent) 70%, #ffffff);
|
||||
background: color-mix(in srgb, var(--akzent) 14%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--akzent) 34%, transparent);
|
||||
}
|
||||
/* Unnummerierte Listen bekommen einen Punkt an derselben Stelle --
|
||||
sonst sprängen die Zeilen zwischen den Abschnitten hin und her. */
|
||||
.regelflaeche ul.regel-liste li::before {
|
||||
content: "";
|
||||
position: absolute; left: 11px; top: 9px;
|
||||
width: 7px; height: 7px; border-radius: 50%;
|
||||
background: color-mix(in srgb, var(--akzent) 55%, transparent);
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.regelflaeche { border: 1px solid CanvasText; }
|
||||
.regelflaeche .treff-abschnitt { border-top: 1px solid CanvasText; }
|
||||
.regelflaeche__sprung { border: 1px solid CanvasText; }
|
||||
.regelflaeche__sprung[data-hier="ja"] { border: 2px solid Highlight; }
|
||||
}
|
||||
|
||||
+14
-21
@@ -2584,27 +2584,20 @@
|
||||
einem anderen Element.
|
||||
|
||||
Gezaehlt wird deshalb ALLES, was ueber der Flaeche liegt. */
|
||||
const UEBER_DER_FLAECHE = ['.kopfleiste', '.fremd-band'];
|
||||
function kopfMessen() {
|
||||
const teile = UEBER_DER_FLAECHE.map((w) => document.querySelector(w)).filter(Boolean);
|
||||
if (!teile.length) return;
|
||||
const h = Math.ceil(teile.reduce((s, e) => s + e.getBoundingClientRect().height, 0));
|
||||
document.documentElement.style.setProperty('--kopf-hoehe', `${h}px`);
|
||||
}
|
||||
kopfMessen();
|
||||
window.addEventListener('resize', kopfMessen);
|
||||
/* Das Band entsteht erst, wenn kopf.js weiss, wer angemeldet ist --
|
||||
also nach dieser Messung. Ohne diesen Beobachter bliebe der erste
|
||||
Wert stehen, und die Flaeche waere genau um das Band zu lang. */
|
||||
if (window.MutationObserver) {
|
||||
new MutationObserver(kopfMessen).observe(document.body, { childList: true });
|
||||
}
|
||||
/* Auch wenn die Leiste selbst sich ändert (Glocke erscheint, Name
|
||||
wird eingesetzt) -- ohne das bliebe der erste Messwert stehen. */
|
||||
if (window.ResizeObserver) {
|
||||
const kopf = document.querySelector('.kopfleiste');
|
||||
if (kopf) new ResizeObserver(kopfMessen).observe(kopf);
|
||||
}
|
||||
/* DIE MESSUNG STEHT SEIT DEM 22.09.2026 IN kopf.js.
|
||||
|
||||
Sie stand hier, weil sie hier gebraucht wurde. Als die Regelseite
|
||||
dieselbe Zahl brauchte, war sie dort nicht da -- und der
|
||||
Rueckfallwert (64 px) lag auf einem Handy um rund 50 px daneben.
|
||||
Eine Zahl, die eine Seite misst und eine andere raet, ist
|
||||
schlimmer als gar keine.
|
||||
|
||||
kopf.js liegt auf JEDER Seite und misst dasselbe: Kopfleiste plus
|
||||
Band mit dem fremden Namen, bei jeder Aenderung neu. Hier bleibt
|
||||
nur ein Aufruf fuer den Fall, dass die Chatseite vor kopf.js
|
||||
fertig ist. Zweimal messen schadet nicht; zweimal RECHNEN haette
|
||||
geschadet. */
|
||||
window.kopfhoeheMessen?.();
|
||||
|
||||
/* ---------- Start -------------------------------------------------------- */
|
||||
/* Der Verwerfen-Knopf der Antwortleiste. Zusaetzlich beendet Escape
|
||||
|
||||
@@ -2300,4 +2300,64 @@
|
||||
});
|
||||
return wartende;
|
||||
};
|
||||
|
||||
/* =====================================================================
|
||||
WIE HOCH IST ALLES, WAS OBEN FESTKLEBT? --kopf-hoehe (22.09.2026)
|
||||
=====================================================================
|
||||
|
||||
STAND BIS HEUTE NUR IN chat.js. Dort wurde es gebraucht, dort
|
||||
wurde es gebaut. Als die Regelseite eine Leiste bekam, die
|
||||
ebenfalls unter der Kopfleiste kleben soll, stand die Variable
|
||||
dort nicht zur Verfuegung -- der Rueckfallwert (64 px) galt, und
|
||||
auf einem 390-px-Schirm ist die Kopfleiste rund 115 px hoch. Die
|
||||
Leiste verschwand hinter ihr. Nichts war kaputt, man sah sie nur
|
||||
nicht.
|
||||
|
||||
Eine Zahl, die eine Seite misst und eine andere raet, ist
|
||||
schlimmer als gar keine: Auf der einen stimmt sie, auf der
|
||||
anderen nicht, und niemand sucht den Fehler bei einer Zahl.
|
||||
|
||||
GEZAEHLT WIRD ALLES, WAS UEBER DEM INHALT LIEGT -- nicht nur die
|
||||
Kopfleiste. Das Band mit dem fremden Namen (.fremd-band, weiter
|
||||
oben in dieser Datei) kommt dazu, sobald jemand mit fremder Sicht
|
||||
unterwegs ist. Wer nur die Leiste misst, liegt genau um die Hoehe
|
||||
dieses Bands daneben.
|
||||
|
||||
DREI ANLAESSE ZUM NACHMESSEN, und alle drei sind noetig:
|
||||
* Fenstergroesse geaendert
|
||||
* am Koerper kommt etwas dazu (das Band entsteht erst, wenn
|
||||
kopf.js weiss, wer angemeldet ist -- also NACH der ersten
|
||||
Messung)
|
||||
* die Leiste selbst aendert sich (Glocke erscheint, Name wird
|
||||
eingesetzt)
|
||||
===================================================================== */
|
||||
var UEBER_DEM_INHALT = ['.kopfleiste', '.fremd-band'];
|
||||
function kopfhoeheMessen() {
|
||||
var teile = UEBER_DEM_INHALT
|
||||
.map(function (w) { return document.querySelector(w); })
|
||||
.filter(Boolean);
|
||||
if (!teile.length) return;
|
||||
var h = Math.ceil(teile.reduce(function (summe, e) {
|
||||
return summe + e.getBoundingClientRect().height;
|
||||
}, 0));
|
||||
document.documentElement.style.setProperty('--kopf-hoehe', h + 'px');
|
||||
}
|
||||
window.kopfhoeheMessen = kopfhoeheMessen;
|
||||
|
||||
function kopfhoeheBeobachten() {
|
||||
kopfhoeheMessen();
|
||||
window.addEventListener('resize', kopfhoeheMessen);
|
||||
if (window.MutationObserver) {
|
||||
new MutationObserver(kopfhoeheMessen).observe(document.body, { childList: true });
|
||||
}
|
||||
if (window.ResizeObserver) {
|
||||
var leiste = document.querySelector('.kopfleiste');
|
||||
if (leiste) new ResizeObserver(kopfhoeheMessen).observe(leiste);
|
||||
}
|
||||
}
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', kopfhoeheBeobachten);
|
||||
} else {
|
||||
kopfhoeheBeobachten();
|
||||
}
|
||||
}());
|
||||
|
||||
@@ -89,4 +89,61 @@
|
||||
+ 'auch, damit man sie zurücknehmen kann.';
|
||||
}
|
||||
})();
|
||||
|
||||
/* =====================================================================
|
||||
DIE SPRUNGLEISTE -- AUS DEN ABSCHNITTEN GEBAUT (22.09.2026)
|
||||
=====================================================================
|
||||
|
||||
Filipe: „nicht sehr viele kacheln sondern eine riesige wo alles
|
||||
schön aussieht und richtig geil, übersichtlich"
|
||||
|
||||
Die eine Flaeche loest das Zerstueckeln. Sie loest aber nicht das
|
||||
Finden: Eine lange Flaeche ohne Wegweiser ist nicht
|
||||
uebersichtlicher als sechs Kaesten, nur laenger. Deshalb oben eine
|
||||
Leiste mit allen Abschnitten.
|
||||
|
||||
SIE WIRD GELESEN, NICHT GEPFLEGT. Die Eintraege kommen aus den
|
||||
Ueberschriften, die ohnehin dastehen. Eine Liste hier waere die,
|
||||
die beim siebten Abschnitt fehlt -- und niemand merkte es, weil
|
||||
die Seite ja funktioniert.
|
||||
|
||||
DIE NUMMERN ENTSTEHEN HIER EBENFALLS: Ein Abschnitt ohne `id`
|
||||
bekommt eine, sonst kann man nicht auf ihn zeigen. Feste ids im
|
||||
HTML waeren dieselbe Pflegearbeit noch einmal.
|
||||
|
||||
Keine Leiste bei weniger als zwei Abschnitten -- dann waere sie
|
||||
ein Wegweiser auf sich selbst. */
|
||||
(function sprungleiste() {
|
||||
const leiste = document.getElementById('regel-sprung');
|
||||
if (!leiste) return;
|
||||
const abschnitte = [...document.querySelectorAll('.regelflaeche .treff-abschnitt')];
|
||||
if (abschnitte.length < 2) { leiste.hidden = true; return; }
|
||||
for (const [i, a] of abschnitte.entries()) {
|
||||
const titel = a.querySelector('.treff-abschnitt__titel');
|
||||
if (!titel) continue;
|
||||
if (!a.id) a.id = `regel-${i + 1}`;
|
||||
const b = document.createElement('a');
|
||||
b.className = 'regelflaeche__sprung';
|
||||
b.href = `#${a.id}`;
|
||||
b.textContent = titel.textContent.trim();
|
||||
leiste.append(b);
|
||||
}
|
||||
/* WO STEHE ICH GERADE? Der Eintrag zum sichtbaren Abschnitt wird
|
||||
hervorgehoben. Ohne das ist die Leiste eine Liste von Links;
|
||||
mit ihr ist sie eine Standortanzeige.
|
||||
|
||||
IntersectionObserver und kein Rechnen beim Rollen: Letzteres
|
||||
laeuft bei jedem Pixel und kostet auf einem Handy spuerbar
|
||||
Strom. Gibt es ihn nicht, bleibt die Leiste eine einfache
|
||||
Liste -- sie funktioniert dann nur ohne Hervorhebung. */
|
||||
if (!('IntersectionObserver' in window)) return;
|
||||
const zuId = new Map(abschnitte.map((a) => [a.id, leiste.querySelector(`[href="#${a.id}"]`)]));
|
||||
const beobachter = new IntersectionObserver((eintraege) => {
|
||||
for (const e of eintraege) {
|
||||
const link = zuId.get(e.target.id);
|
||||
if (link) link.dataset.hier = e.isIntersecting ? 'ja' : 'nein';
|
||||
}
|
||||
}, { rootMargin: '-45% 0px -45% 0px' });
|
||||
for (const a of abschnitte) beobachter.observe(a);
|
||||
})();
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user