Reduzierte Filmtechnik, Take Two

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Haben Sie diese nette Technik gesehen, um das <picture>-Element mit <source media=""> zu verwenden, um ein animiertes Bild (oder nicht) basierend auf einer prefers-reduced-motion-Media-Query bereitzustellen?

Nachdem wir dies in unserem Newsletter geteilt hatten, erhielten wir eine interessante Antwort von Michael Gale

Was ist mit Leuten, die ihre animierten GIFs lieben, aber einfach nicht wollten, dass die UI überall herumzoomt? Müssen sie jetzt eine Wahl zwischen Inhalt und UI treffen?

Ich fand das eine ziemlich interessante Frage.

Außerdem wird mein Gehirn heutzutage jedes Mal, wenn ich <img src="gif.gif"> sehe, in das Territorium von *WAS IST MIT MP4?!* getriggert, da ich richtig davon überzeugt bin, dass Videos im Web in jeder Hinsicht besser sind als GIFs. Es stellt sich heraus, dass einige Browser Videos direkt im <img>-Element unterstützen und, ob Sie es glauben oder nicht, Sie können Fallbacks dafür schreiben, mit – Trommelwirbel, bitte – auch für das <picture>-Element!

Versuchen wir, all diese Dinge zu kombinieren.

Hinzufügen einer MP4-Quelle

Das Einfache ist das Hinzufügen einer zusätzlichen <source> mit dem Video. Das bedeutet, wir benötigen drei Quellmediendateien

  1. Eine alternative nicht-animierte Grafik, wenn prefers-reduced-motion auf reduce gesetzt ist.
  2. Ein animiertes GIF als Standard.
  3. Ein MP4-Video als Ersatz für das GIF, wenn der Fallback unterstützt wird.

Zum Beispiel:

<picture>
  <source srcset="static.png" media="(prefers-reduced-motion: reduce)"></source>
  <source srcset="animated.mp4" type="video/mp4">
  <img srcset="animated.gif" alt="animated image" />
</picture>

Unter Standardbedingungen in Chrome werden nur das GIF heruntergeladen und angezeigt

Chrome DevTools showing only gif downloaded

Unter Standardbedingungen in Safari werden nur die MP4 heruntergeladen und angezeigt

Safari DevTools showing only mp4 downloaded

Wenn Sie prefers-reduced-motion: reduce in Chrome oder Safari aktiviert haben (auf meinem Mac gehe ich zu SystemeinstellungenBedienungshilfenAnzeigeBewegung reduzieren), laden beide Browser nur die statische PNG-Datei herunter.

Chrome DevTools showing png downloaded

Ich habe Firefox getestet und es scheint nicht zu funktionieren, stattdessen wird weiterhin die GIF-Version heruntergeladen. Firefox scheint prefers-reduced-motion zu unterstützen, aber vielleicht wird es noch nicht auf <source>-Elementen unterstützt? Ich bin mir nicht sicher, was da los ist.

Wäre es nicht ziemlich cool, eine einzige animierte Quelle bereitzustellen und ein Tool die anderen daraus generieren zu lassen? Ich wette, Sie könnten das mit etwas wie Cloudinary verkabeln.

Hinzufügen eines Schalters zur Anzeige der animierten Version

Wie Michael Gale erwähnte, scheint es schade zu sein, dass Sie von der Anzeige der animierten Version vollständig ausgeschlossen sind, nur weil Sie einen Schalter für reduzierte Bewegungen umgelegt haben.

Es sollte einfach genug sein, einen <button> zu haben, der JavaScript verwendet, um die Media-Query zu entfernen und den Browser zu zwingen, die animierte Version anzuzeigen.

Ich bin ziemlich sicher, dass es keinen praktischen Weg gibt, dies deklarativ in HTML zu tun. Wir können diesen Button auch nicht innerhalb des <picture>-Tags platzieren. Obwohl <picture> kein ersetztes Element ist, wird der Browser immer noch verwirrt und mag es nicht. Stattdessen rendert er es überhaupt nicht. Kein großes Ding, wir können einen Wrapper verwenden.

<div class="picture-wrap">
  
  <picture>
     <!-- sources  -->
  </picture>

  <button class="animate-button">Animate</button>

</div>

Wir können den Button über dem Bild positionieren. Dies ist nur eine willkürliche Wahl – Sie könnten ihn überall platzieren oder sogar das gesamte Bild tappbar machen, solange Sie denken, dass Sie dies den Benutzern erklären können. Denken Sie daran, den Button nur anzuzeigen, wenn die gleiche Media-Query übereinstimmt

.picture-wrap .animate-button {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .picture-wrap .animate-button {
     display: block;
  }
}

Wenn der Button geklickt (oder angetippt) wird, müssen wir die Media-Query entfernen, um die Animation zu starten, indem wir eine animierte Quelle herunterladen.

let button = document.querySelector(".animate-button");

button.addEventListener("click", () => {
  const parent = button.closest(".picture-wrap");
  const picture = parent.querySelector("picture");
  picture.querySelector("source[media]").remove();
});

Hier ist das in Aktion

Sehen Sie den Pen
Prefers Reduction Motion Technique PLUS!
von Chris Coyier (@chriscoyier)
auf CodePen.

Vielleicht ist das eine gute Komponente?

Wir könnten den Button, das Button-Styling und die Button-Funktionalität automatisch mit einer Web-Komponente einbinden. Hey, warum nicht?

Sehen Sie den Pen
Prefers Reduction Motion Technique als Web Component
von Chris Coyier (@chriscoyier)
auf CodePen.