Ein praktisches kleines System für animierte Eingänge in CSS

Avatar of Neale Van Fleet
Neale Van Fleet am

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

Ich liebe kleine Details, die einer Website mehr als nur ein statisches Dokument verleihen. Was wäre, wenn Webinhalte nicht einfach "erscheinen" würden, wenn eine Seite geladen wird, sondern stattdessen aufploppen, gleiten, verblassen oder sich drehen würden? Es mag übertrieben sein zu sagen, dass Bewegungen dieser Art immer nützlich sind, obwohl sie in einigen Fällen auf bestimmte Elemente aufmerksam machen, hervorheben, welche Elemente sich voneinander unterscheiden, oder sogar einen geänderten Zustand anzeigen können. Sie sind also auch nicht völlig nutzlos.

Deshalb habe ich eine Reihe von CSS-Dienstprogrammen zur Animation von Elementen zusammengestellt, wenn sie ins Blickfeld geraten. Und ja, das ist reines CSS. Es bietet nicht nur eine schöne Vielfalt an Animationen und Variationen, sondern unterstützt auch das Staggering dieser Animationen, fast wie eine Möglichkeit, Szenen zu erstellen.

Sie wissen schon, so etwas

Was wirklich nur eine schickere Version davon ist

Wir werden zuerst die Grundlage erläutern, die ich zur Erstellung der Animationen verwendet habe, dann auf die kleinen Verzierungen eingehen, die ich hinzugefügt habe, wie man Animationen stagert, und dann, wie man sie auf HTML-Elemente anwendet, bevor wir uns auch ansehen, wie man all dies tut und gleichzeitig die Vorlieben eines Benutzers für reduzierte Bewegungen berücksichtigt.

Die Grundlagen

Die Kernidee besteht darin, eine einfache CSS-@keyframes-Animation hinzuzufügen, die auf alles angewendet wird, was wir beim Laden der Seite animieren möchten. Machen wir es so, dass ein Element ausblendet, von opacity: 0 zu opacity: 1 in einer halben Sekunde

.animate {
  animation-duration: 0.5s;
  animation-name: animate-fade;
  animation-delay: 0.5s;
  animation-fill-mode: backwards;
}

@keyframes animate-fade {
  0% { opacity: 0; }
  100% { opacity: 1; }
}

Beachten Sie auch, dass eine animation-delay von einer halben Sekunde vorhanden ist, damit der Rest der Website etwas Zeit zum Laden hat. Der animation-fill-mode: backwards ist vorhanden, um sicherzustellen, dass unser anfänglicher Animationszustand beim Laden der Seite aktiv ist. Ohne dies erscheint unser animiertes Element, bevor wir es wollen.

Wenn wir faul sind, können wir den Tag damit beenden und einfach dabei bleiben. Aber CSS-Tricks-Leser sind natürlich nicht faul, also schauen wir uns an, wie wir so etwas mit einem System noch besser machen können.

Schickere Animationen

Es macht viel mehr Spaß, eine Vielzahl von Animationen zur Verfügung zu haben als nur ein oder zwei. Wir müssen nicht einmal viele neue @keyframes erstellen, um weitere Animationen zu erstellen. Es ist einfach genug, neue Klassen zu erstellen, bei denen wir nur ändern, welche Frames die Animation verwendet, während wir die gesamte Zeitplanung beibehalten.

Es gibt fast unendlich viele CSS-Animationen. (Siehe animate.style für eine riesige Sammlung.) CSS-Filter wie blur(), brightness() und saturate() sowie natürlich CSS-Transformationen können ebenfalls verwendet werden, um noch mehr Variationen zu erstellen.

Aber für den Moment beginnen wir mit einer neuen Animationsklasse, die eine CSS-Transformation verwendet, um ein Element "aufploppen" zu lassen.

.animate.pop {
  animation-duration: 0.5s;
  animation-name: animate-pop;
  animation-timing-function: cubic-bezier(.26, .53, .74, 1.48);
}

@keyframes animate-pop {
  0% {
    opacity: 0;
    transform: scale(0.5, 0.5);
  }

  100% {
    opacity: 1;
    transform: scale(1, 1);
  }
}

Ich habe eine kleine cubic-bezier()-Timingkurve hinzugefügt, courtesy of Lea Verou's unverzichtbarem cubic-bezier.com für einen federnden Sprung.

Verzögerungen hinzufügen

Wir können es besser machen! Zum Beispiel können wir Elemente so animieren, dass sie zu unterschiedlichen Zeiten erscheinen. Dies erzeugt ein Staggering, das für komplexe Bewegungen ohne viel Code sorgt.

Diese Animation auf drei Seitenelementen, die einen CSS-Filter und eine CSS-Transformation verwendet und jeweils um etwa ein Zehntel einer Sekunde gestagert wird, wirkt sehr gut

Alles, was wir dort getan haben, war, für jedes Element eine neue Klasse zu erstellen, die den Beginn der Animationen zeitlich versetzt, indem Werte für animation-delay verwendet werden, die nur eine Zehntelsekunde auseinander liegen.

.delay-1 { animation-delay: 0.6s; }  
.delay-2 { animation-delay: 0.7s; }
.delay-3 { animation-delay: 0.8s; }

Alles andere ist genau gleich. Und denken Sie daran, dass unsere Basisverzögerung 0.5s beträgt, sodass diese Hilfsklassen von dort aufzählen.

Zugänglichkeitspräferenzen berücksichtigen

Lasst uns gute Web-Bürger sein und unsere Animationen für Benutzer entfernen, die ihre Einstellung für reduzierte Bewegung aktiviert haben.

@media screen and (prefers-reduced-motion: reduce) {
  .animate { animation: none !important; }
}

Auf diese Weise wird die Animation nie geladen und die Elemente erscheinen wie gewohnt. Hier ist es jedoch erwähnenswert, dass "reduzierte" Bewegung nicht immer "keine" Bewegung bedeutet.

Animationen auf HTML-Elemente anwenden

Bisher haben wir eine Basisanimation sowie eine etwas schickere gesehen, die wir mit gestagerten Animationsverzögerungen, die in neuen Klassen enthalten sind, noch schicker machen konnten. Wir haben auch gesehen, wie wir gleichzeitig die Benutzereinstellungen für Bewegungen berücksichtigen können.

Auch wenn es Live-Demos gibt, die die Konzepte demonstrieren, haben wir noch nicht wirklich durchgearbeitet, *wie* wir unsere Arbeit auf HTML anwenden. Und das Coole ist, dass wir dies auf fast jedes Element anwenden können, egal ob es sich um ein div, span, article, header, section, table, form... handelt, Sie verstehen schon.

Hier ist, was wir tun werden. Wir möchten unser Animationssystem auf drei HTML-Elemente anwenden, wobei jedes Element drei Klassen erhält. Wir könnten den gesamten Animationscode direkt auf das Element schreiben, aber die Aufteilung gibt uns ein kleines Animationssystem, das wir wiederverwenden können.

  • .animate: Dies ist die Basisklasse, die unsere Kernanimationsdeklaration und -zeitplanung enthält.
  • Der Animationstyp: Wir verwenden unsere "Pop"-Animation von zuvor, aber wir könnten auch die verwenden, die ausblendet. Diese Klasse ist technisch optional, aber sie ist eine gute Möglichkeit, unterschiedliche Bewegungen anzuwenden.
  • .delay-<number>: Wie wir bereits gesehen haben, können wir verschiedene Klassen erstellen, die verwendet werden, um den Beginn der Animation auf jedem Element zu verzögern, was zu einem schönen Effekt führt. Diese Klasse ist ebenfalls optional.

Unsere animierten Elemente könnten also jetzt so aussehen

<h2 class="animate pop">One!</h2>
<h2 class="animate pop delay-1">Two!</h2>
<h2 class="animate pop delay-2">Three!</h2>

Zählen wir sie ein!

Fazit

Schauen Sie sich das an: Wir begannen mit einem scheinbar einfachen Satz von @keyframes und verwandelten ihn in ein voll funktionsfähiges System zum Anwenden interessanter Animationen für Elemente, die ins Blickfeld geraten.

Das macht natürlich unglaublich Spaß. Aber die wichtigste Erkenntnis für mich ist, wie die Beispiele, die wir uns angesehen haben, ein vollständiges System bilden, das verwendet werden kann, um eine Basislinie, verschiedene Arten von Animationen, gestaggerte Verzögerungen und einen Ansatz zur Berücksichtigung von Benutzereinstellungen für Bewegungen zu erstellen. Dies sind für mich alle Zutaten für ein flexibles System, das einfach zu bedienen ist. Es gibt uns viel für wenig, ohne viel zusätzlichen Ballast.

Was wir behandelt haben, könnte tatsächlich eine vollständige Animationsbibliothek sein. Aber natürlich habe ich dort nicht aufgehört. Ich habe meine gesamte CSS-Datei mit Animationen in ihrer ganzen Pracht für Sie. Dort gibt es mehrere weitere Animationstypen, darunter 15 Klassen mit verschiedenen Verzögerungen, die zum Staggering von Dingen verwendet werden können. Ich benutze diese in meinen eigenen Projekten, aber es ist immer noch ein früher Entwurf und ich würde mich über Feedback dazu freuen. Bitte genießen Sie es und lassen Sie mich in den Kommentaren wissen, was Sie denken!

/* ==========================================================================
Animation System by Neale Van Fleet from Rogue Amoeba
========================================================================== */
.animate {
  animation-duration: 0.75s;
  animation-delay: 0.5s;
  animation-name: animate-fade;
  animation-timing-function: cubic-bezier(.26, .53, .74, 1.48);
  animation-fill-mode: backwards;
}

/* Fade In */
.animate.fade {
  animation-name: animate-fade;
  animation-timing-function: ease;
}

@keyframes animate-fade {
  0% { opacity: 0; }
  100% { opacity: 1; }
}

/* Pop In */
.animate.pop { animation-name: animate-pop; }

@keyframes animate-pop {
  0% {
    opacity: 0;
    transform: scale(0.5, 0.5);
  }
  100% {
    opacity: 1;
    transform: scale(1, 1);
  }
}

/* Blur In */
.animate.blur {
  animation-name: animate-blur;
  animation-timing-function: ease;
}

@keyframes animate-blur {
  0% {
    opacity: 0;
    filter: blur(15px);
  }
  100% {
    opacity: 1;
    filter: blur(0px);
  }
}

/* Glow In */
.animate.glow {
  animation-name: animate-glow;
  animation-timing-function: ease;
}

@keyframes animate-glow {
  0% {
    opacity: 0;
    filter: brightness(3) saturate(3);
    transform: scale(0.8, 0.8);
  }
  100% {
    opacity: 1;
    filter: brightness(1) saturate(1);
    transform: scale(1, 1);
  }
}

/* Grow In */
.animate.grow { animation-name: animate-grow; }

@keyframes animate-grow {
  0% {
    opacity: 0;
    transform: scale(1, 0);
    visibility: hidden;
  }
  100% {
    opacity: 1;
    transform: scale(1, 1);
  }
}

/* Splat In */
.animate.splat { animation-name: animate-splat; }

@keyframes animate-splat {
  0% {
    opacity: 0;
    transform: scale(0, 0) rotate(20deg) translate(0, -30px);
    }
  70% {
    opacity: 1;
    transform: scale(1.1, 1.1) rotate(15deg);
  }
  85% {
    opacity: 1;
    transform: scale(1.1, 1.1) rotate(15deg) translate(0, -10px);
  }

  100% {
    opacity: 1;
    transform: scale(1, 1) rotate(0) translate(0, 0);
  }
}

/* Roll In */
.animate.roll { animation-name: animate-roll; }

@keyframes animate-roll {
  0% {
    opacity: 0;
    transform: scale(0, 0) rotate(360deg);
  }
  100% {
    opacity: 1;
    transform: scale(1, 1) rotate(0deg);
  }
}

/* Flip In */
.animate.flip {
  animation-name: animate-flip;
  transform-style: preserve-3d;
  perspective: 1000px;
}

@keyframes animate-flip {
  0% {
    opacity: 0;
    transform: rotateX(-120deg) scale(0.9, 0.9);
  }
  100% {
    opacity: 1;
    transform: rotateX(0deg) scale(1, 1);
  }
}

/* Spin In */
.animate.spin {
  animation-name: animate-spin;
  transform-style: preserve-3d;
  perspective: 1000px;
}

@keyframes animate-spin {
  0% {
    opacity: 0;
    transform: rotateY(-120deg) scale(0.9, .9);
  }
  100% {
    opacity: 1;
    transform: rotateY(0deg) scale(1, 1);
  }
}

/* Slide In */
.animate.slide { animation-name: animate-slide; }

@keyframes animate-slide {
  0% {
    opacity: 0;
    transform: translate(0, 20px);
  }
  100% {
    opacity: 1;
    transform: translate(0, 0);
  }
}

/* Drop In */
.animate.drop { 
  animation-name: animate-drop; 
  animation-timing-function: cubic-bezier(.77, .14, .91, 1.25);
}

@keyframes animate-drop {
0% {
  opacity: 0;
  transform: translate(0,-300px) scale(0.9, 1.1);
}
95% {
  opacity: 1;
  transform: translate(0, 0) scale(0.9, 1.1);
}
96% {
  opacity: 1;
  transform: translate(10px, 0) scale(1.2, 0.9);
}
97% {
  opacity: 1;
  transform: translate(-10px, 0) scale(1.2, 0.9);
}
98% {
  opacity: 1;
  transform: translate(5px, 0) scale(1.1, 0.9);
}
99% {
  opacity: 1;
  transform: translate(-5px, 0) scale(1.1, 0.9);
}
100% {
  opacity: 1;
  transform: translate(0, 0) scale(1, 1);
  }
}

/* Animation Delays */
.delay-1 {
  animation-delay: 0.6s;
}
.delay-2 {
  animation-delay: 0.7s;
}
.delay-3 {
  animation-delay: 0.8s;
}
.delay-4 {
  animation-delay: 0.9s;
}
.delay-5 {
  animation-delay: 1s;
}
.delay-6 {
  animation-delay: 1.1s;
}
.delay-7 {
  animation-delay: 1.2s;
}
.delay-8 {
  animation-delay: 1.3s;
}
.delay-9 {
  animation-delay: 1.4s;
}
.delay-10 {
  animation-delay: 1.5s;
}
.delay-11 {
  animation-delay: 1.6s;
}
.delay-12 {
  animation-delay: 1.7s;
}
.delay-13 {
  animation-delay: 1.8s;
}
.delay-14 {
  animation-delay: 1.9s;
}
.delay-15 {
  animation-delay: 2s;
}

@media screen and (prefers-reduced-motion: reduce) {
  .animate {
    animation: none !important;
  }
}