
Mit CSS können Sie dynamische Layouts und Schnittstellen im Internet erstellen. Als Auszeichnungssprache ist es jedoch statisch - Sie können es nicht ändern, nachdem Sie den Wert festgelegt haben. Die Idee des Zufalls wird nicht diskutiert. Die Erzeugung von Laufzeit-Zufallszahlen ist ein Gebiet von JavaScript, nicht von CSS.
Oder nicht? Wenn wir ein wenig Benutzerinteraktion zulassen, können wir tatsächlich einen gewissen Grad an Zufälligkeit in CSS erzeugen. Werfen wir einen Blick darauf!
Zufälligkeit in anderen Sprachen
Es gibt Möglichkeiten, mithilfe von CSS-Variablen eine „dynamische Randomisierung“ zu erzielen, wie Robin Rendle in einem Artikel
über CSS-Tricks erklärt . Diese Lösungen sind jedoch nicht zu 100% CSS, da JavaScript erforderlich ist, um die CSS-Variable mit einem neuen Zufallswert zu aktualisieren.
Wir können Präprozessoren wie Sass oder Less verwenden, um zufällige Werte zu generieren. Sobald der CSS-Code kompiliert und exportiert wird, sind die Werte fest und die Zufälligkeit geht verloren.
Warum mache ich mir Sorgen um Zufallswerte in CSS?
In der Vergangenheit habe ich einfache Nur-CSS-Anwendungen wie
Quiz ,
CS Simons Spiel und
Magic Trick entwickelt , aber ich wollte etwas komplexeres machen.
* Ich werde erst zu einem späteren Zeitpunkt eine Diskussion über die Gültigkeit, Nützlichkeit oder Praktikabilität der Erstellung dieser Snippets in CSS hinterlassen.
Basierend auf der Tatsache, dass einige Brettspiele als State Machines (FSMs) dargestellt werden können, können sie mithilfe von HTML und CSS dargestellt werden.
Deshalb habe ich angefangen, das Spiel
"Leela" (es ist auch "Snakes and Ladders") zu entwickeln.
Dies ist ein einfaches Spiel. Kurz gesagt, das Ziel des Spiels ist es, den Chip vom Anfang bis zum Ende des Bretts voranzutreiben, Schlangen auszuweichen und zu versuchen, die Treppe zu erklimmen.
Das Projekt schien machbar, aber ich habe etwas verpasst, klar - Würfel!
Das Werfen von Würfeln (in anderen Spielen das Werfen von Münzen) ist eine allgemein anerkannte Methode, um Zufallswerte zu erhalten. Sie würfeln oder werfen eine Münze und erhalten jedes Mal einen unbekannten Wert. Alles scheint einfach.
Simulation eines zufälligen Knochenwurfs
Ich wollte die Ebenen mit Beschriftungen überlagern und mithilfe der CSS-Animation „drehen“ und freigeben, welche Ebene oben war. So etwas wie das:

Der Code zum Simulieren dieser Randomisierung ist nicht zu kompliziert und kann mithilfe von Animation und verschiedenen Animationsverzögerungen erreicht werden:
@keyframes changeOrder { from { z-index: 6; } to { z-index: 1; } } label { animation: changeOrder 3s infinite linear; background: #ddd; cursor: pointer; display: block; left: 1rem; padding: 1rem; position: absolute; top: 1rem; user-select: none; } label:nth-of-type(1) { animation-delay: -0.0s; } label:nth-of-type(2) { animation-delay: -0.5s; } label:nth-of-type(3) { animation-delay: -1.0s; } label:nth-of-type(4) { animation-delay: -1.5s; } label:nth-of-type(5) { animation-delay: -2.0s; } label:nth-of-type(6) { animation-delay: -2.5s; }
Die Animation wurde verlangsamt, um die Interaktion zu vereinfachen (aber immer noch schnell genug, um das unten erläuterte Hindernis zu erkennen). Pseudozufälligkeit ist auch klarer.
<label for="d1">Click here to roll the dice</label> <label for="d2">Click here to roll the dice</label> <label for="d3">Click here to roll the dice</label> <label for="d4">Click here to roll the dice</label> <label for="d5">Click here to roll the dice</label> <label for="d6">Click here to roll the dice</label> <div> <input type="radio" id="d1" name="dice"> <input type="radio" id="d2" name="dice"> <input type="radio" id="d3" name="dice"> <input type="radio" id="d4" name="dice"> <input type="radio" id="d5" name="dice"> <input type="radio" id="d6" name="dice"> <p>You got a: <span id="random-value"></span></p> </div>
@keyframes changeOrder { from { z-index: 6;} to { z-index: 1; } } label { animation: changeOrder 3s infinite linear; background: #ddd; cursor: pointer; display: block; left: 1rem; padding: 1rem; position: absolute; top: 1rem; user-select: none; } label:nth-of-type(1) { animation-delay: 0s; } label:nth-of-type(2) { animation-delay: -0.5s; } label:nth-of-type(3) { animation-delay: -1.0s; } label:nth-of-type(4) { animation-delay: -1.5s; } label:nth-of-type(5) { animation-delay: -2.0s; } label:nth-of-type(6) { animation-delay: -2.5s; } div { left: 1rem; position: absolute; top: 5rem; width: 100%; } #d1:checked ~ p span::before { content: "1"; } #d2:checked ~ p span::before { content: "2"; } #d3:checked ~ p span::before { content: "3"; } #d4:checked ~ p span::before { content: "4"; } #d5:checked ~ p span::before { content: "5"; } #d6:checked ~ p span::before { content: "6"; }
Aber dann bin ich auf eine gewisse Einschränkung gestoßen. Ich habe Zufallszahlen erhalten, aber manchmal hat das Feld selbst dann keinen Wert zurückgegeben, wenn ich auf "Würfel" geklickt habe.
Ich habe versucht, die Animationszeit zu erhöhen, und es schien ein wenig zu helfen, aber ich hatte immer noch einige unerwartete Werte.
Damals habe ich das getan, was die meisten Entwickler tun, wenn sie Hindernisse finden, die sie nicht lösen können. Ich habe mich bei StackOverflow um Hilfe bemüht. Ich empfehle es.
Zum Glück wird es immer Menschen geben, die bereit sind zu helfen, in meinem Fall war es
Temani Afif mit seiner Erklärung .
Wenn Sie versuchen zu vereinfachen, bestand das Problem darin, dass der Browser das Klickereignis nur auslöst, wenn sich das Element im aktiven Zustand befindet (wenn die Maus gedrückt wird), mit anderen Worten, es ist dasselbe Element, das aktiv ist, wenn die Maustaste gedrückt wird.
Aufgrund der sich ändernden Animation war die oberste Ebene (Beschriftung) beim Klicken mit der Maus nicht die oberste Ebene (Beschriftung), als die Maus gedrückt wurde, es sei denn, ich habe es schnell genug, gut oder langsam ausgeführt, sodass die Animation bereits vorhanden ist schaffte es, alle Werte des Zyklus durchzugehen. Aus diesem Grund hat die Verlängerung der Animationszeit dieses Problem ausgeblendet.
Die Lösung bestand darin, die „statische“ Position anzuwenden, um den Stapelkontext zu unterbrechen, und ein Pseudoelement wie :: before oder :: after mit einem höheren Z-Index als Ersatz zu verwenden. Somit befindet sich das aktive Label immer oben, wenn Sie mit der Maus darüber fahren.
label:active { margin-left: 200%; position: static; } label:active::before { content: ""; position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 10; }
Hier ist der Code mit einer Lösung mit schnellerer Animationszeit:
Nach dieser Änderung muss noch eine kleine Oberfläche zum Zeichnen von Pseudowürfeln erstellt werden, die mit der Maus angeklickt werden kann, und das CSS-
Spiel Snakes and Ladders wurde abgeschlossen.
Diese Technik hat einige offensichtliche Nachteile.
- Eine Interaktion mit dem Benutzer ist erforderlich - es ist erforderlich, auf eine Beschriftung zu klicken, um eine "Erzeugung von Zufallszahlen" zu bewirken.
- Die Methode lässt sich nicht gut skalieren - sie funktioniert hervorragend mit kleinen Wertesätzen, ist jedoch ein Schmerz für große Bereiche.
- Dies ist keine echte Zufälligkeit, aber dennoch eine Pseudozufälligkeit, und der Computer kann leicht bestimmen, welcher Wert zu jedem Zeitpunkt generiert wird.
Auf der anderen Seite handelt es sich jedoch um 100% CSS (Präprozessoren oder andere externe Helfer sind nicht erforderlich), und für eine Person kann es zu 100% zufällig aussehen.
Und ja, diese Methode kann nicht nur für Zufallszahlen verwendet werden, sondern auch für alles Zufällige. In diesem Fall haben wir damit „versehentlich“ einen Computer im Spiel „Stein-Papier-Schere“ ausgewählt.