Einblendungen laufen beim Scrollen, ohne Skript
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:
1 parent
0d6c1a17af
commit
f0b634f0c1
5 files changed
+114
-13
No files matched your search
+38
-2
@@ -767,6 +767,40 @@ final class CmsTest extends TestCase
|
||||
(new DocumentValidator())->validate($document);
|
||||
}
|
||||
|
||||
public function testEntranceEffectsRunOnScrollWhereTheBrowserCanAndOnLoadOtherwise(): void
|
||||
{
|
||||
// Umut: „Effekte gibt es keine“. Es gab sie - aber nur beim Zeigen, nicht beim Laden, und
|
||||
// eine Einblendung beim Laden ist unterhalb der Falz wertlos: sie ist vorbei, bevor
|
||||
// jemand hinsieht. Mit einer Scroll-Zeitachse läuft dieselbe Animation, wenn der
|
||||
// Abschnitt in den Blick kommt - ohne eine Zeile JavaScript.
|
||||
$css = (string) file_get_contents(__DIR__.'/../public/assets/enhancements.css');
|
||||
self::assertStringContainsString('@supports (animation-timeline: view())', $css);
|
||||
self::assertStringContainsString('animation-timeline: view()', $css);
|
||||
|
||||
// Beides steht hinter der Bewegungsschranke, und der Rückfall ist die Fassung von vorher:
|
||||
// ein Browser ohne Scroll-Zeitachse zeigt alles, nur eben beim Laden animiert.
|
||||
$geschuetzt = explode('@media (prefers-reduced-motion: no-preference) {', $css);
|
||||
self::assertStringNotContainsString('animation-timeline', $geschuetzt[0], 'Keine Bewegung außerhalb der Schranke.');
|
||||
self::assertSame(1, substr_count($css, '@supports (animation-timeline: view())'));
|
||||
|
||||
// Der wichtigste Teil, und er ist mit Messen bezahlt: auf dem Scrollweg wird **keine
|
||||
// Deckkraft** animiert. Eine Scroll-Zeitachse ist umkehrbar, also stünde alles unterhalb
|
||||
// der Falz dauerhaft am Anfang der Kurve - bei Deckkraft 0,85 wird aus #3d4d5c ein
|
||||
// #78838d, und damit 3,86:1 statt 7,1:1. axe hat genau das gemeldet.
|
||||
self::assertStringContainsString('@keyframes kant-scroll-rise { from { transform: translateY(20px) } to { transform: none } }', $css);
|
||||
self::assertStringContainsString('@keyframes kant-scroll-fade { from { transform: translateY(10px) } to { transform: none } }', $css);
|
||||
$scrollteil = explode('@supports (animation-timeline: view())', $css)[1];
|
||||
self::assertStringNotContainsString('opacity', explode('.fx-delay-long', $scrollteil)[0], 'Auf dem Scrollweg bleibt der Text voll deckend.');
|
||||
|
||||
// Und die drei Beitragsvorlagen bringen die Einblendung von sich aus mit.
|
||||
foreach (array_keys(PostLayouts::all()) as $key) {
|
||||
$document = PostLayouts::document($key, 'Ein Beitrag');
|
||||
$mitEffekt = array_filter($document['blocks'], static fn (array $block): bool => isset($block['layout']['effects']['entrance']));
|
||||
self::assertCount(count($document['blocks']), $mitEffekt, $key.': jeder Abschnitt blendet ein.');
|
||||
(new DocumentValidator())->validate($document);
|
||||
}
|
||||
}
|
||||
|
||||
public function testANewPostStartsFromOneOfThreeLayouts(): void
|
||||
{
|
||||
// Umut wollte mehrere Aufbauten zur Auswahl. Ein leeres Dokument ist für eine Seite
|
||||
@@ -911,9 +945,11 @@ final class CmsTest extends TestCase
|
||||
// Die Bewegung steht vollständig hinter der Bewegungsschranke, der Hinweis selbst nicht:
|
||||
// wer weniger Bewegung eingestellt hat, sieht ihn trotzdem.
|
||||
$effects = (string) file_get_contents(__DIR__.'/../public/assets/enhancements.css');
|
||||
// Der erste Abschnitt steht vor der ersten Schranke; alles dahinter ist geschützt.
|
||||
$guarded = explode('@media (prefers-reduced-motion: no-preference) {', $effects);
|
||||
self::assertStringContainsString('.post-card:hover, .post-card:focus-within {', end($guarded));
|
||||
self::assertStringContainsString('transform: scale(1.06)', end($guarded));
|
||||
$geschuetzt = implode('', array_slice($guarded, 1));
|
||||
self::assertStringContainsString('.post-card:hover, .post-card:focus-within {', $geschuetzt);
|
||||
self::assertStringContainsString('transform: scale(1.06)', $geschuetzt);
|
||||
self::assertStringNotContainsString('transform: translateY(-8px)', $guarded[0], 'Keine Bewegung außerhalb der Schranke.');
|
||||
|
||||
// Und über die Tastatur erreichbar: der Zustand hängt auch an :focus-within.
|
||||
|
||||
Reference in new issue
Block a user