Unverified Commit 55f0e6f7 authored by berumuron's avatar berumuron
Browse files

Ajoute l’article Aléatoire en CSS

parent 84200b49
---
title: De l’aléatoire en CSS ?
date: 2021-04-09 17:00
---
Ces derniers temps, un mini-projet me trottait en tête : un site qui propose
des idées de choses rapides à dessiner. La liste serait établie au préalable
par moi-même ou par des propositions externes, mais tout serait statique. Le
cahier des charges me semblait suffisamment simple pour que je puisse me passer
d’un langage dynamique à la fois côté serveur et client (ni <abbr>PHP</abbr>,
ni JavaScript en somme). C’était sans compter que je voulais que les idées
soient suggérées de manière aléatoire.
En y réfléchissant hier soir, je me suis demandé : « et si on pouvait générer
de l’aléatoire en <abbr>CSS</abbr> ? » La réponse courte est « non », mais il
existe également une réponse longue et elle m’a été donnée par le site
CSS-Tricks : « [<em lang="en">Are There Random Numbers in CSS?</em>](https://css-tricks.com/are-there-random-numbers-in-css/) ».
**Attention, n’utilisez pas cette technique en production.** Elle n’est ni
accessible, ni très maintenable. Il s’agit avant tout de jouer avec
<abbr>CSS</abbr>. Vous êtes prévenu‧e ! 😄
Le principe est assez simple : il consiste à superposer plusieurs `label` avec
le même texte, les uns au-dessus des autres, puis à modifier leur `z-index` en
boucle à l’infini grâce à une `animation`. Ainsi, le clic surviendra sur un
`label` que le visiteur ne saura pas prévoir. Les `label` sont associés à des
champs `radio` : il suffit alors d’adapter l’affichage en fonction du sélecteur
`input:checked`.
Ce qui est marrant avec cette méthode, c’est que la génération d’aléatoire est
déplacée de l’ordinateur au visiteur.
Pour ma part, j’ai adapté la solution parce qu’elle ne me convenait pas tout à
fait : j’ai préféré me baser sur des liens avec ancre et le sélecteur associé,
`:target`. En effet, en cliquant sur un lien avec l’attribut `href="#1"` par
exemple, le sélecteur <abbr>CSS</abbr> `#1:target` devient actif. Voici une
illustration :
```html
<p class="idee-dessin" id="1">Un renard qui fait du surf</p>
<p class="idee-dessin" id="2">Une tomate amoureuse</p>
<p class="idee-dessin" id="3">Une pendule en retard à un rendez-vous</p>
<div class="conteneur-boutons-nouvelle-idee">
<a class="bouton-nouvelle-idee" href="#1">Nouvelle idée ?</a>
<a class="bouton-nouvelle-idee" href="#2">Nouvelle idée ?</a>
<a class="bouton-nouvelle-idee" href="#3">Nouvelle idée ?</a>
</div>
```
Ainsi, le premier lien « Nouvelle idée ? » active le premier paragraphe, etc.
Il suffit alors de cacher en <abbr>CSS</abbr> tous les paragraphes, sauf celui
visé par le sélecteur `:target`.
```css
.idee-dessin {
display: none;
}
.idee-dessin:target {
display: block;
}
```
Il ne reste alors plus qu’à superposer les liens et animer leur `z-index` :
```css
.conteneur-boutons-nouvelle-idee {
position: relative;
}
@keyframes changeOrdre {
from { z-index: 3; }
to { z-index: 1; }
}
.bouton-nouvelle-idee {
animation: changeOrdre 3s infinite linear;
position: absolute;
}
.bouton-nouvelle-idee:nth-of-type(1) { animation-delay: -0.0s; }
.bouton-nouvelle-idee:nth-of-type(2) { animation-delay: -0.5s; }
.bouton-nouvelle-idee:nth-of-type(3) { animation-delay: -1.0s; }
.bouton-nouvelle-idee:active {
z-index: 4 !important;
}
```
La dernière règle est importante car les navigateurs génèrent un clic
uniquement si l’élément qui a reçu l’évènement `mousedown` est le même qui
reçoit l’évènement `mouseup`. Comme les `z-index` changent en permanence, ce
n’est souvent pas le cas. Il faut donc forcer un peu les choses en mettant
l’élément `:active` au premier plan. C’est expliqué dans l’article de
CSS-Tricks avec une solution plus compliquée, mais qui fait l’économie d’un
`!important`.
Une dernière chose me chagrinait avec cette méthode, c’est qu’il était
compliqué d’ajouter de nouvelles phrases à la main. J’ai donc écrit un script
Python pour générer les fichiers <abbr>HTML</abbr> et <abbr>CSS</abbr> à partir
d’un fichier contenant des phrases.
**Le code est [sur Framagit](https://framagit.org/marienfressinaud/dessine-moi),
et le résultat sur [frama.io](https://marienfressinaud.frama.io/dessine-moi/#1).**
Avec ça je me serai bien marré, mais la prochaine fois j’utiliserai quand même
JavaScript, ce sera plus simple 😅
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment