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;
}
}
„Alles andere ist genau gleich. Und denken Sie daran, dass unsere Basisverzögerung 0,5 s beträgt, sodass diese Hilfsklassen von dort aufzählen.“
Vielleicht übersehe ich etwas, aber ich sehe das in Ihrem Beispiel nicht. Die 0,6 s, 0,7 s und 0,8 s überschreiben die 0,5 s, die definiert wurden. So wie es in Ihrer Erklärung formuliert ist, habe ich verstanden, dass die Verzögerung 0,5 s + 0,6 s, 0,5 s + 0,7 s, 0,5 s + 0,8 s betragen würde.
Ich bin ziemlich sicher, dass dies implizieren soll
„Die Standardverzögerung beträgt 0,5 s, daher müssen wir nur Hilfsfunktionen erstellen, die von dort aufzählen.“
Absolut erstaunlich
Mir gefällt die Art und Weise, wie Sie Verzögerungen klassifiziert haben, und diese Animationsbibliothek und der Ease-Rechner sind für mich neu.
Es ist vielleicht ein bisschen geschummelt, aber ich mag Animista wirklich (ich würde es lieber, wenn die Leute suchen, anstatt Links zu posten, aber .net zur Klarheit, nicht Werbung).
Sie können jeden Teil visualisieren und anpassen, sogar Verläufe, und dann den CSS-Code überall kopieren und einfügen. Es verwendet ähnliche Namenskonventionen.
Es tut also nicht alles für Sie, aber es ist der beste Animationseditor, den ich je benutzt habe.
Gut gemacht. Ich habe vor einiger Zeit ein ähnliches (aber nicht so umfangreiches) kleines Helferprogramm erstellt.
Eine Sache, die ich nie erreicht habe, die aber für Ihr Projekt lohnenswert sein könnte, ist, wie Sie CSS-Variablen verwenden könnten, um die Verzögerungsklasse dynamisch zu machen und somit nicht auf ein nummeriertes Klassensystem angewiesen zu sein (z. B. die Möglichkeit von „.delay-18“ berücksichtigen müssen).
Zum Beispiel, wenn Sie über generierte Elemente auf einer Produktseite schleifen, auf der Sie 20 Produkte laden, würde jedes Element seinen Indexwert an das CSS übergeben und es würde die Mathematik durchführen, um seine Animation zu verzögern.
Sie könnten auch etwas Ähnliches mit nth-child tun, wo das CSS herausfindet, wo sich das Element in der Reihenfolge befindet.
Viel Glück!
Wenn es sich um generierte Daten handelt, könnten Sie potenziell die Gesamtzahl der Elemente als CSS-Variable innerhalb des übergeordneten Elements festlegen und diese dann verwenden, um die Verzögerung dynamisch anzupassen.
Ich liebe diese Idee, ich habe nur noch nicht den idealen Weg gefunden, sie zu implementieren. Ich bin offen für Ideen, wie man das machen könnte.
Ich generiere einen Container mit
nKindern (die Anzahl der Kinder als benutzerdefinierte Eigenschaft auf dem Container festgelegt und jedes Kind hat den Index als benutzerdefinierte Eigenschaft).Dies erzeugt das folgende HTML
Und für das Styling setze ich normalerweise eine Animationsdauer
tals SCSS-Variable (wenn sie nicht dynamisch sein muss, ist es besser für die Leistung, keine CSS-Variable zu verwenden) und die Basisverzögerung auft/nund multipliziere dann diese Basisverzögerung mit dem Item-Indexifür die tatsächliche Item-Verzögerung. Die Basisverzögerung könnte jedoch auch etwas anderes sein.Etwas anderes, das ich in diesem Fall tun würde, wäre, all diese
100%Keyframes wegzulassen, sie sind völlig unnötig. Das sind die Eigenschaftswerte, wenn keine Animation vorhanden ist, der Browser weiß, dass er zu diesen animieren soll, wenn sie nicht explizit geschrieben sind.Und im
animate-dropFall istopacity: 1nur im95%Keyframe notwendig. Ich würde auch einen einzigen Wert für gleichmäßiges Skalieren verwenden, da es schrecklich verwirrend ist, Dinge wiescale(1.1, 1.1)zu sehen – ich habe mir das etwa fünfmal angesehen, um herauszufinden, was der Unterschied zwischen diesen beiden Werten ist. Wenn ich zwei Werte inscale()sehe, erwarte ich, dass sie unterschiedlich sind.Etwas späte Antwort, aber wir machen genau das bei animxyz.com, wo wir den gesamten Boilerplate-Code für die Erstellung von Animationen wie dieser übernehmen und Sie sie einfach mit Attributen, die Utility-Klassen ähneln, und CSS-Variablen komponieren lassen.
Mit einer Index-CSS-Variablen verarbeiten wir eine beliebige Anzahl von Elementen mit gestagerten Verzögerungen, sogar umgekehrten Verzögerungen, falls erforderlich.
Nur zur Information, ich habe dies für eine generierte Fotogalerie verwendet.
Anstatt eine Menge delay-X-Klassen zu erstellen, habe ich die Verzögerung einfach als Style-Attribut auf das Element gesetzt.
Vor der Schleife wird der Zähler auf die Basisverzögerung (0,5) gesetzt und dann wird jede Iteration um 0,1 erhöht. Solange Sie sie in der Reihenfolge generieren, in der Sie sie anzeigen möchten, funktioniert dies gut.
Ana – Danke für diese Kommentare. Ich werde den Code aktualisieren, wenn ich die Gelegenheit dazu habe.
Jill – Toll zu sehen, dass das für etwas verwendet wird. Danke!
Würden diese netten Animationen die Web-Vital-Metriken negativ beeinflussen?
Es müsste untersucht werden. Es ist möglich.
Schön
So habe ich im Max WordPress Theme im Jahr 2013 CSS-Animationen erstellt. Die Klasse „load“ wurde hinzugefügt, wenn das Element in den tatsächlichen „Ansichtsbereich“ der Seite kam.
Coole Sache! Ich denke, es könnte von einigen Variablen profitieren, die bestimmte wiederkehrende Werte speichern, sowie von einigen Parametern, die konstant sind.
Zum Beispiel könnte der cubic-bezier() selbst mit Variablen serviert werden, ähnlich wie bei einem komponierbaren hsl(), aber auf einer höheren Abstraktionsebene sogar eine Variable halten, die einfach den Typ „–timing-function-type: cubic-bezier();“ speichert, um Timings auszutauschen. Überflüssig, aber trotzdem.
Die Animationsverzögerungs-Dienstprogramme am Ende sollten einen inkrementellen Wert haben, der calc() für mehr Flexibilität anwendet, aber ich weiß nicht, ob das leistungsmäßig wichtig ist. Aber die Wartung zur Aktualisierung und Anpassung auf Komponentenebene würde erheblich verbessert, wie es meiner Meinung nach bei Designsystemen der Fall ist; sie dienen zuerst der DX, nicht der UX.
Das ist das Ergebnis, von dem der Endbenutzer profitiert, der Prozess der Einrichtung ist das, von dem "wir" profitieren müssen.
Zuletzt ist "prefers reduce motion" etwas, das nicht "gar keine Bewegung" bedeutet. Was ist Ihre Meinung dazu, die Funktion zu unterstützen, wenn bestimmte UI-Nachrichten möglicherweise Bewegung benötigen, um Botschaft und Bedeutung zu vermitteln?
Vielleicht grabe ich zu tief, aber ich mag ein durch und durch bescheidenes und hartes System wie dieses. Ich habe es als Referenz für mein eigenes DS verwendet, mit einigen dieser Feedbackpunkte, die rechtzeitig angewendet wurden.
Vielen Dank fürs Teilen!
Danke für diesen Kommentar.
Ich hatte nicht daran gedacht, eine Variable innerhalb des cubic-bezier zu verwenden, aber es ist potenziell ziemlich genial. Sie könnten den dritten Wert als (sozusagen) Verlangsamung und den vierten Wert als Überschwingen betrachten.
Was die Verwendung von calc für die Verzögerungen betrifft, so hatte ich tatsächlich ursprünglich eine Variation davon! Es ist großartig, aber ich habe es zur Vereinfachung des Artikels weggelassen. Es wäre eine großartige Sache, es wieder hinzuzufügen, wahrscheinlich als Multiplikatorvariable, die zu den Verzögerungsklassen hinzugefügt wird. Ich werde dies wahrscheinlich irgendwann zu meiner Produktionsversion hinzufügen.
Sehr wahr bezüglich reduzierter Bewegung. Ich hatte erwogen, alle Animationen in Ausblendungen ohne Verzögerung zu verwandeln, wenn die Bewegungsreduzierung aktiviert ist. Das könnte ein besserer Ansatz sein als gar keine Animationen.
Ich mochte es,
calc()mit benutzerdefinierten Eigenschaften zu verwenden, die im Element platziert sind, um die Fade-in-Reihenfolge zuzuweisen.