Nummern-Animation, also stell dir vor, eine Zahl ändert sich von 1 zu 2, dann von 2 zu 3, dann von 3 zu 4 usw. über eine bestimmte Zeit. Wie ein Zähler, nur gesteuert durch die gleiche Art von Animation, die wir für andere Design-Animationen im Web verwenden. Das könnte nützlich sein, wenn man etwas wie ein Dashboard gestaltet, um den Zahlen etwas Pep zu verleihen. Erstaunlicherweise lässt sich dies jetzt mit CSS ohne viel Trickserei bewerkstelligen. Du kannst direkt zur neuen Lösung springen, wenn du möchtest, aber lass uns zuerst betrachten, wie wir es *früher* gemacht haben.

Eine ziemlich logische Methode für Nummern-Animationen ist die Änderung der Zahl in JavaScript. Wir könnten ein recht einfaches setInterval verwenden, aber hier ist eine schickere Antwort mit einer Funktion, die einen Start-, End- und Dauerwert akzeptiert, sodass du sie mehr wie eine Animation behandeln kannst.
Wenn wir bei CSS bleiben, könnten wir CSS-Zähler verwenden, um eine Zahl zu animieren, indem wir die Zählung bei verschiedenen Keyframes anpassen.
Eine andere Möglichkeit wäre, alle Zahlen hintereinander aufzureihen und nur jeweils eine durch Animation der Position anzuzeigen.
Ein Teil des sich wiederholenden Codes in diesen Beispielen könnte von einem Präprozessor wie Pug für HTML oder SCSS für CSS profitieren, die Schleifen anbieten, um sie vielleicht einfacher zu verwalten. Wir verwenden jedoch bewusst Vanilla, damit du die grundlegenden Ideen sehen kannst.
Die CSS-Lösung der neuen Schule
Mit der jüngsten Unterstützung für CSS.registerProperty und @property können wir CSS-Variablen animieren. Der Trick besteht darin, die benutzerdefinierte CSS-Eigenschaft als Integer zu deklarieren; auf diese Weise kann sie (wie jede andere ganze Zahl) interpoliert werden (z. B. innerhalb eines Übergangs).
@property --num {
syntax: '<integer>';
initial-value: 0;
inherits: false;
}
div {
transition: --num 1s;
counter-reset: num var(--num);
}
div:hover {
--num: 10000;
}
div::after {
content: counter(num);
}
Wichtiger Hinweis: Zum Zeitpunkt des Schreibens wird diese @property-Syntax nur in Chrome (und anderen Chromium-basierten Browsern wie Edge und Opera) unterstützt, daher ist sie nicht browserübergreifend kompatibel. Wenn du etwas nur für Chrome entwickelst (z. B. eine Electron-App), ist sie sofort nützlich, andernfalls warte. Die obigen Demos werden breiter unterstützt.
Die CSS-Eigenschaft content kann verwendet werden, um die Zahl anzuzeigen, aber wir müssen immer noch counter verwenden, um die Zahl in einen String umzuwandeln, da content nur <string>-Werte ausgeben kann.
Siehst du, wie wir die Animationen *gleiten* lassen können, genau wie jede andere Animation? Super cool!
Typisierte CSS-Variablen können auch in @keyframes verwendet werden:
Ein Nachteil? Zähler unterstützen nur ganze Zahlen. Das bedeutet, Dezimalzahlen und Brüche sind ausgeschlossen. Wir müssten den ganzzahligen und den Bruchteil separat irgendwie anzeigen.
Können wir Dezimalzahlen animieren?
Es ist möglich, eine Dezimalzahl (z. B. --number) in eine ganze Zahl umzuwandeln. Hier ist, wie es funktioniert
- Registriere eine CSS-Variable vom Typ
<integer>(z. B.--integer) mit dem angegebeneninitial-value. - Verwende dann
calc(), um den Wert zu runden:--integer: calc(var(--number)).
In diesem Fall wird --number auf die nächste ganze Zahl gerundet und das Ergebnis in --integer gespeichert.
@property --integer {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
--number: 1234.5678;
--integer: calc(var(--number)); /* 1235 */
Manchmal brauchen wir nur den ganzzahligen Teil. Es gibt eine trickreiche Methode dafür: --integer: max(var(--number) - 0.5, 0). Das funktioniert für positive Zahlen. calc() ist auf diese Weise nicht einmal erforderlich.
/* @property --integer */
--number: 1234.5678;
--integer: max(var(--number) - 0.5, 0); /* 1234 */
Den Bruchteil können wir auf ähnliche Weise extrahieren und dann mit einem Zähler in einen String umwandeln (aber denke daran, dass content-Werte Strings sein müssen). Um verkettete Strings anzuzeigen, verwende folgende Syntax:
content: "string1" var(--string2) counter(--integer) ...
Hier ist ein vollständiges Beispiel, das Prozentsätze mit Dezimalzahlen animiert.
Weitere Tipps
Da wir CSS-Zähler verwenden, kann das Format dieser Zähler auch andere Formate als Zahlen haben. Hier ist ein Beispiel, wie man die Buchstaben "CSS" zu "YES" animiert!
Oh, und hier noch ein Tipp: Wir können die Werte mit JavaScript debuggen, indem wir den berechneten Wert der benutzerdefinierten Eigenschaft abrufen.
getComputedStyle(element).getPropertyValue('--variable')
Das ist alles! Es ist erstaunlich, was CSS heutzutage leisten kann.
Das ist so clever! Es scheint, als hätten benutzerdefinierte Eigenschaften so viele geheime Kräfte, die die Community langsam aufdeckt.
Danke! ♥
Sehr clever, danke. Ich möchte nur ein paar Überlegungen zur Barrierefreiheit zu diesen Beispielen hinzufügen.
Diese funktionieren nicht für Tastaturnutzer, aber es ist einfach genug, sie hinzuzufügen (
tabindex="0"zum<div>, um es fokussierbar zu machen, und fügediv:hover, div:focus {in die Selektoren ein, um die Animation beim Fokus anzuwenden).Bildschirmlesegeräte lesen entweder den anfänglichen, voranimierten Wert (0) beim Navigieren vor. Beim Fokussieren oder bei der Keyframe-Animation scheint es einen Wert während der Animation anzunehmen und sich daran zu erinnern (z. B. mit VoiceOver hörte ich immer wieder "8" oder "61", obwohl visuell 100 angezeigt wurde).
Ich bin mir nicht sicher, ob es dafür eine elegante Lösung gibt – abgesehen von einer umständlichen Methode mit zwei divs.
Ein Vorteil dieses Ansatzes ist jedoch: Im Gegensatz zur JS-Version kann dies die Media Query
prefers-reduced-motionnutzen und den Endwert ohne Animation für Personen mit vestibulären/Bewegungsstörungen darstellen.Danke für die Antwort.
So funktioniert die Übergangsanimation. Mein Vorschlag ist auch
Das sollte sehr einfach zu implementieren sein.
Ich wollte das einmal animieren und habe die Anzahl der Animationswiederholungen auf 1 gesetzt, aber das Problem ist, dass es wieder auf Null zurückspringt. Wie kann ich es am letzten Wert, also bei 100%, stoppen lassen?
Ich spreche von diesem hier: https://codepen.io/chriscoyier/pen/NWNJpPe.
Danke.???
animation-fill-mode: forwards;
wirklich erstaunlich!! aber ich möchte es öfter als einmal tun.
wenn ich das div viermal dupliziere und jedem eine ID gebe, um die Animation abzuspielen.
es funktioniert nicht gut, nur ein oder zwei funktionieren, oder sie funktionieren, aber mit demselben Wert, und ich habe 4 verschiedene Werte. Wie animiere ich also 4 verschiedene Werte?
Schau dir meine Bearbeitung an: https://codepen.io/bgbos/pen/pobZvwJ
Ich habe sogar versucht, mit -num zu spielen, wie du sehen wirst, um es anders zu machen.
Ich schätze deine Hilfe.
Du hattest
--numund@keyframes counterzweimal definiert. Du musst diese Probleme und den schlechten Programmierstil beheben, bevor du dein Problem angehst.Ok, also haben wir hier diesen Code: https://codepen.io/bgbos/pen/pobZvwJ
Wie du siehst, hat jedes von ihnen einen anderen Anfangswert, an dem es stoppen soll, aber es stoppt alles bei einem Wert, ich weiß nicht warum, also wie mache ich das, bitte helft?
Entschuldige den schlechten Code, Sir, ich bin ein kompletter Anfänger.
Mit freundlichen Grüßen.
Gibt es eine Möglichkeit, mehrere Zähler auf einer Seite zu haben?
Kann eine benutzerdefinierte Eigenschaft in styled-components in React verwendet werden?
Hallo, Carter
Danke fürs Teilen. Das ist eine wirklich tolle Methode, um diesen Effekt zu erzielen.
Ich habe deine Lösung in meinem Projekt angewendet.
Aber es scheint auf Mobilgeräten und Safari nicht zu funktionieren.
Gibt es irgendeine Möglichkeit, dieses knifflige Problem zu lösen?
Nur Chrome unterstützt es derzeit und es ist nicht polyfill-fähig.
Also nein.
Ich habe bereits 2014 ein kleines Skript dafür erstellt.
https://github.com/yairEO/Do-in
Wie kann ich verhindern, dass die Zähler nach unten gehen oder zurückgesetzt werden? Ich möchte, dass der Zähler beim Endwert stoppt.
animation-fill-mode: forwards;
Du musst den Animations-Fill-Mode auf "forwards" setzen, dann bleibt er beim Endwert.
animation-fill-mode: forwards;
Das ist wunderbar, aber ich habe eine seltsame Frage. Wenn ich das verwenden möchte, um eine Anzeigetafel zu zeigen. Ich möchte, dass die Zahlen nicht wieder auf 0 zurückgesetzt werden. Gibt es eine Möglichkeit, dies zu verhindern?
Ist die Zahl nicht selbst gesetzt?
Mir ist ein seltsames Verhalten aufgefallen, wenn große Zahlen verwendet werden – der Zähler wird immer auf 0 gesetzt und springt dann am Ende der Animation zum Endwert. Die Länge der Animation macht keinen Unterschied.
div::after {
content: counter(num);
}
div:hover {
–num: 11000000;
}
Hat jemand Ideen, was das verursachen könnte?
Das gleiche Problem hier, aber meins springt nicht einmal und bleibt einfach bei 0. Ich habe mir die Haare ausgerauft, um zu verstehen, warum 2 meiner 4 Zähler nicht funktionierten, obwohl der Code identisch war, bis ich verstand, dass es an den Werten selbst lag. Es scheint, dass sobald man über 8 Ziffern geht, dies aufhört zu funktionieren.
Hat jemand herausgefunden, warum das passiert und ob es vielleicht eine Lösung gibt?
Ich habe hier ein Problem gemeldet: https://bugs.chromium.org/p/chromium/issues/detail?id=1217506
Warten wir auf einige Antworten.
EDIT: Das Problem wurde mit Priorität 2 zugewiesen.
EDIT2: Es wird in Chrome 93 behoben sein.
https://bugs.chromium.org/p/chromium/issues/detail?id=1217506#c6
Hallo! Ich habe animation-fill-mode: forwards; hinzugefügt.
Aber ich kann es nicht dazu bringen, am Ende zu stoppen. Kann mir jemand helfen?
Mein Code
animation-iteration-count: 1;
Kann dies an die Scroll-Position gebunden werden? Könnte ich zum Beispiel bewirken, dass der Zahlenzähler beim Scrollen nach unten steigt und beim Scrollen nach oben sinkt?
Du brauchst
IntersectionObserver.Ich habe eine Version mit IntersectionObserver erstellt, die einige Fallbacks für ältere Browser und prefers-reduced-motion enthält.
Weitere Erklärungen unter https://www.bronco.co.uk/our-ideas/experimenting-with-css-number-counters-with-fallback/