Y a-t-il des nombres aléatoires dans CSS?

CSS vous permet de créer des mises en page dynamiques et des interfaces de projet Web. Mais CSS est un langage statique. Une fois qu'une certaine valeur est définie, elle ne peut pas être modifiée. L'idée de modifier aléatoirement certaines valeurs n'est pas considérée ici.



La génération de nombres aléatoires est un territoire de JavaScript que CSS n'entre pas. Mais que se passe-t-il si ce n'est pas entièrement vrai? En fait, si vous prenez en compte les actions effectuées par l'utilisateur, cela ajoutera un peu de hasard au CSS. L'auteur du document, dont nous publions la traduction aujourd'hui, propose d'en discuter.

Randomisation CSS externe


Vous pouvez utiliser des variables CSS pour implémenter quelque chose comme la «randomisation dynamique» en CSS. Voici quelques bonnes choses à ce sujet. Cependant, de telles solutions au problème ne sont pas du pur CSS. Ici, vous devez recourir aux fonctionnalités JavaScript pour écrire de nouvelles valeurs aléatoires dans les variables CSS.

Vous pouvez utiliser des préprocesseurs comme Sass ou Less pour générer des valeurs aléatoires. Mais après avoir compilé et exporté le code CSS, ces valeurs sont fixes et l'élément aléatoire est perdu. Dans un tweet sur ce sujet, cette approche de la définition des valeurs CSS est comparée à un choix aléatoire du nom du héros du roman, qui, une fois écrit sur papier, ne change pas.

Pourquoi suis-je intéressé à utiliser des valeurs aléatoires en CSS?


J'ai déjà développé des applications simples basées uniquement sur CSS. Ceci est un quiz , un jeu de Simon et des tours de cartes . Mais je voulais faire quelque chose de plus compliqué. Je n'aborde pas ici les questions de la justesse de cette approche, les questions de l'utilité ou de l'applicabilité pratique des projets basés uniquement sur CSS.

En partant du principe que certains jeux de société peuvent être représentés comme des machines à états finis (FSM), nous pouvons conclure que ces jeux peuvent être implémentés en utilisant uniquement HTML et CSS. Fort de cette idée, j'ai commencé à développer le jeu " Snakes and Ladders ". Ceci est un jeu simple. Son objectif est de lancer un dé et d'arriver du point de départ du terrain de jeu au dernier, tout en évitant les serpents et en essayant d'utiliser les escaliers.

Il m'a semblé que ce projet pouvait se faire en HTML et CSS. Cependant, je n'ai pas pris en compte quelque chose. Il s'agit de dés.

Le jet de dés (ainsi que le jet de pièce) sont universellement reconnus comme des «générateurs» de valeurs aléatoires. Chaque fois, en jetant un os ou une pièce de monnaie, nous obtenons quelque chose qui nous était inconnu auparavant.

Imitation de lancer de dés


J'allais superposer des calques avec des étiquettes et utiliser une animation CSS afin de les «faire défiler», en changeant le calque supérieur. Il ressemblait à celui illustré ci-dessous.


Simuler des animations de calques dans un navigateur

Le code qui implémente un tel système pour obtenir des valeurs aléatoires n'est pas particulièrement compliqué. Il comprend une description de l'animation en utilisant divers délais. Voici le code:

/*    z-index —     . */ @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; } 

Veuillez noter que l'animation a été ralentie afin qu'il soit plus facile d'interagir avec les éléments correspondants (mais elle s'est avérée suffisamment rapide pour provoquer un problème, qui sera discuté ci-dessous). Ici, la nature pseudo-aléatoire du mécanisme présenté est clairement visible.

Voici un projet sur CodePen qui vous permet d'explorer cette approche


Imitation de lancer de dés

En fait, ici, je suis tombé sur un problème. Mon programme a donné des valeurs aléatoires, mais parfois, même lorsque je cliquais sur un bouton simulant un lancer osseux, le système ne retournait rien du tout.

J'ai essayé d'augmenter le temps d'animation, ce qui, il me semble, a légèrement amélioré la situation, mais le système s'est toujours mal comporté.

C'est alors que j'ai fait ce que font tous les programmeurs, face à un problème qu'ils ne peuvent pas résoudre avec un moteur de recherche. J'ai posé une question sur StackOverflow.

À mon bonheur, ils m'ont tout expliqué et ont proposé une solution au problème.

Une description simplifiée de mon problème peut être représentée comme suit: "Le navigateur déclenche l'événement click d'un élément uniquement lorsque l'élément qui est actif au moment où l'événement mousedown se produit reste actif lorsque l'événement mouseup se produit."

Étant donné que les éléments se remplacent constamment - l'élément supérieur sur lequel l'événement mousedown se produit lorsque le bouton de la souris est enfoncé n'est pas toujours le même élément sur lequel, lorsque le bouton est mouseup événement mouseup se produit. Pour que le bouton soit enfoncé et relâché au moment où le même élément est en haut de la pile, le clic doit être effectué soit assez rapidement (pour que l'élément n'ait pas le temps de quitter le haut de la pile), soit plutôt lentement (pour que l'élément il y a une chance de revenir au sommet, en faisant un cercle complet). C'est pourquoi une augmentation du temps des animations a permis de masquer le problème.

La solution consistait à utiliser la valeur static pour la propriété position de l'élément actif, ce qui la supprimait de la pile d'éléments. De plus, un pseudo-élément, tel que ::before ou ::after , auquel une très grande valeur d' z-index été affectée, a pris sa place. Avec cette approche, l'élément actif serait toujours en haut de la pile lors du relâchement du bouton de la souris.

 /*           */ label:active {  margin-left: 200%;  position: static; } /* -         z-index */ label:active::before {  content: "";  position: absolute;  top: 0;  right: 0;  left: 0;  bottom: 0;  z-index: 10; } 

Voici un projet qui implémente cette solution et utilise une animation plus rapide.

Après avoir apporté cette modification au projet, je devais simplement ajouter mes réalisations au jeu. Voilà ce que j'ai.


Jeu terminé

Inconvénients de la méthode


La méthode aléatoire décrite ici présente des inconvénients évidents:

  • Pour son travail nécessite la participation des utilisateurs. La personne doit cliquer sur l'étiquette pour lancer le processus de «génération d'une valeur aléatoire».
  • Il n'évolue pas bien. Cette méthode est bien adaptée pour travailler avec de petits ensembles de valeurs, mais si vous avez besoin d'obtenir une valeur aléatoire à partir d'une large plage, il est très gênant de l'utiliser.
  • Son application permet d'obtenir des valeurs non aléatoires, mais pseudo-aléatoires. Le fait est que l'ordinateur peut facilement savoir quelle valeur "aléatoire" sera émise à un moment donné.

Résumé


La méthode présentée ici, malgré les limitations décrites ci-dessus, est basée sur du CSS pur. Pour l'utiliser, aucun préprocesseur ou certains mécanismes auxiliaires externes ne sont nécessaires. Et pour l'utilisateur, son utilisation donne l'impression que le programme produit des nombres complètement aléatoires.

Et en passant, cette méthode ne convient pas seulement pour générer des nombres aléatoires. Il vous permet de randomiser n'importe quoi. Par exemple - dans ce projet, il est basé sur le choix «aléatoire» que l'ordinateur fait dans le jeu «Stone, Scissors, Paper».


Le jeu "Stone, ciseaux, papier" en CSS pur

Chers lecteurs! Envisagez-vous d'utiliser les idées mises en évidence dans ce document dans vos projets?


Source: https://habr.com/ru/post/fr474310/


All Articles