Einblendungen laufen beim Scrollen, ohne Skript
CMS quality / php (8.2) (push) Canceled after 0s
CMS quality / php (8.4) (push) Canceled after 0s
CMS quality / browser (push) Canceled after 0s
CMS quality / mysql (push) Canceled after 0s

Umut: "Effekte gibts keine, sind die aktiv?" Nachgemessen: die
Zeigereffekte liefen alle. Die Einblendungen gab es seit Schema v3 - nur
benutzt hatte sie niemand, weil eine Animation beim Laden unterhalb der
Falz wertlos ist.

Mit animation-timeline: view() laufen dieselben Keyframes, wenn der
Abschnitt in den Blick kommt - hinter der Bewegungsschranke, hinter
@supports (Firefox und Safari behalten das Einblenden beim Laden) und mit
einem Bereich, der endet, bevor der Abschnitt in der Mitte steht.

Dabei hat axe einen Fehler gefunden, den ich selbst gebaut hatte: eine
Scroll-Zeitachse ist umkehrbar, also stand alles unterhalb der Falz
dauerhaft am Anfang der Kurve - bei opacity .35 blass, bei .85 immer noch
3,86:1 statt 7,1:1. Auf dem Scrollweg wird deshalb nur Bewegung animiert,
keine Deckkraft.

Benutzt wird es jetzt auch: alle drei Beitragsvorlagen bringen die
Einblendung je Abschnitt mit.

Geprueft: 400 Tests unter PHP 8.2 und 8.4, Editortest, Browserpruefung,
axe ohne Verstoss auf Startseite, Projekteseite und Beitrag - vor und
nach dem Durchscrollen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
kantarciandClaude Opus 5 committed 2026-09-13 12:07:50 +02:00
1 parent 0d6c1a17af
commit f0b634f0c1
5 files changed
+114 -13

No files matched your search

+21 -11
View File
@@ -78,7 +78,7 @@ final class PostLayouts
'backgroundColor' => '@ink', 'color' => '#ffffff', 'textAlign' => 'center',
'display' => 'flex', 'alignItems' => 'flex-end', 'justifyContent' => 'center',
'minHeight' => '58vh', 'padding' => self::spacing('110px', '52px', '0px', '0px'),
]),
], [], ['entrance' => 'fade']),
self::narrow('text', [
self::heading('text-h', 'Über den Beitrag', 2, ['fontSize' => '28px', 'fontWeight' => '800', 'color' => '@ink']),
self::text('text-1', 'Schreibe hier den ersten Absatz. Er beantwortet am besten die Frage, warum jemand weiterlesen sollte.'),
@@ -88,9 +88,9 @@ final class PostLayouts
self::badge('galerie-label', 'Bildergalerie', true),
self::heading('galerie-h', 'Eindrücke', 2, ['fontSize' => '30px', 'fontWeight' => '800', 'color' => '@ink']),
self::gallery('galerie-bilder', 2),
], ['backgroundColor' => '@paper', 'padding' => self::spacing('60px', '60px', '0px', '0px')]),
self::section('weiter', [self::nav('weiter-nav')], ['padding' => self::spacing('50px', '50px', '0px', '0px')]),
self::section('aufruf', [self::cta('aufruf-band')], ['backgroundColor' => '@ink', 'color' => '#ffffff', 'padding' => self::spacing('62px', '62px', '0px', '0px')]),
], ['backgroundColor' => '@paper', 'padding' => self::spacing('60px', '60px', '0px', '0px')], [], ['entrance' => 'rise']),
self::section('weiter', [self::nav('weiter-nav')], ['padding' => self::spacing('50px', '50px', '0px', '0px')], [], ['entrance' => 'fade']),
self::section('aufruf', [self::cta('aufruf-band')], ['backgroundColor' => '@ink', 'color' => '#ffffff', 'padding' => self::spacing('62px', '62px', '0px', '0px')], [], ['entrance' => 'fade']),
];
}
@@ -103,13 +103,13 @@ final class PostLayouts
self::heading('kopf-titel', $title, 1, ['fontSize' => '42px', 'fontWeight' => '800', 'lineHeight' => 1.15, 'letterSpacing' => '-0.8px']),
self::text('kopf-vorspann', 'Ein Vorspann in zwei, drei Sätzen. Er steht für sich und sagt, worum es geht – wer nur ihn liest, weiß Bescheid.', ['fontSize' => '20px', 'lineHeight' => 1.6]),
], '70px', '30px'),
self::section('bild', [self::image('bild-1')], ['padding' => self::spacing('0px', '10px', '0px', '0px')]),
self::section('bild', [self::image('bild-1')], ['padding' => self::spacing('0px', '10px', '0px', '0px')], [], ['entrance' => 'zoom']),
self::narrow('text', [
self::text('text-1', 'Der erste Absatz des Haupttextes. Ab hier darf es ausführlich werden.'),
self::heading('text-h', 'Ein Zwischentitel', 2, ['fontSize' => '26px', 'fontWeight' => '800', 'color' => '@ink', 'margin' => self::spacing('34px', '12px', '0px', '0px')]),
self::text('text-2', 'Zwischentitel machen einen langen Text überhaupt erst lesbar. Setze alle drei bis fünf Absätze einen.'),
]),
self::section('weiter', [self::nav('weiter-nav')], ['backgroundColor' => '@paper', 'padding' => self::spacing('50px', '50px', '0px', '0px')]),
self::section('weiter', [self::nav('weiter-nav')], ['backgroundColor' => '@paper', 'padding' => self::spacing('50px', '50px', '0px', '0px')], [], ['entrance' => 'fade']),
];
}
@@ -132,7 +132,7 @@ final class PostLayouts
self::text('eck-daten', "Kunde: noch einzutragen\nLeistung: noch einzutragen\nJahr: noch einzutragen", ['fontSize' => '15px']),
]],
]],
], ['backgroundColor' => '@paper', 'padding' => self::spacing('72px', '48px', '0px', '0px')]),
], ['backgroundColor' => '@paper', 'padding' => self::spacing('72px', '48px', '0px', '0px')], [], ['entrance' => 'fade']),
self::narrow('text', [
self::text('text-1', 'Der Einstieg in den Beitrag. Was war die Aufgabe, und warum war sie nicht trivial?'),
self::heading('text-h', 'Der Weg', 2, ['fontSize' => '26px', 'fontWeight' => '800', 'color' => '@ink', 'margin' => self::spacing('30px', '12px', '0px', '0px')]),
@@ -140,16 +140,26 @@ final class PostLayouts
self::heading('text-h2', 'Das Ergebnis', 2, ['fontSize' => '26px', 'fontWeight' => '800', 'color' => '@ink', 'margin' => self::spacing('30px', '12px', '0px', '0px')]),
self::text('text-3', 'Was sich seitdem geändert hat – am besten ohne Superlative.'),
]),
self::section('galerie', [self::gallery('galerie-bilder', 3)], ['backgroundColor' => '@paper', 'padding' => self::spacing('56px', '56px', '0px', '0px')]),
self::section('weiter', [self::nav('weiter-nav')], ['padding' => self::spacing('50px', '50px', '0px', '0px')]),
self::section('galerie', [self::gallery('galerie-bilder', 3)], ['backgroundColor' => '@paper', 'padding' => self::spacing('56px', '56px', '0px', '0px')], [], ['entrance' => 'rise']),
self::section('weiter', [self::nav('weiter-nav')], ['padding' => self::spacing('50px', '50px', '0px', '0px')], [], ['entrance' => 'fade']),
];
}
// ---------------------------------------------------------------- Bausteine
private static function section(string $id, array $children, array $desktop = [], array $mobile = []): array
/**
* Ein Abschnitt, wahlweise mit Einblendung.
*
* Die Einblendung läuft beim Hineinscrollen, wo der Browser eine Scroll-Zeitachse kennt, und
* sonst beim Laden - beides ohne Skript, beides hinter der Bewegungsschranke. Deshalb darf
* sie auch weiter unten stehen, ohne ins Leere zu laufen.
*/
private static function section(string $id, array $children, array $desktop = [], array $mobile = [], array $effects = []): array
{
$block = ['id' => $id, 'type' => 'section', 'children' => $children];
if ([] !== $effects) {
$block['layout'] = ['effects' => $effects];
}
if ([] !== $desktop || [] !== $mobile) {
$block['style'] = array_filter(['desktop' => $desktop, 'mobile' => $mobile]);
}
@@ -164,7 +174,7 @@ final class PostLayouts
'maxWidth' => '820px',
'margin' => self::spacing('0px', '0px', 'auto', 'auto'),
'padding' => self::spacing($top, $bottom, '0px', '0px'),
]);
], [], ['entrance' => 'rise']);
}
private static function heading(string $id, string $text, int $level, array $style = []): array