J'adore faire que CSS fait des choses que cela ne devrait pas. C'est le type d'entraînement cérébral de résolution de problèmes que vous obtiendriez en train de construire une calculatrice à Minecraft, sauf que vous n'obtiendrez probablement un emploi avec Minecraft Redstone, peu importe à quel point vous obtenez de bien, tandis que les compétences CSS valent de l'argent, et de nombreux programmeurs généralistes ont peur de CSS, donc l'étudier peut être un moyen de se démarquer du pack. De plus, lorsque vous avez fait l'impossible avec CSS, toutes les tâches CSS normales semblent faciles.
J'ai lu des discussions intéressantes sur le Web pour savoir si CSS est un langage complet Turing et si CSS et HTML sont qualifiés de langages de programmation. Je n'ai pas décidé, mais je peux dire que dans la quête pour soutenir les modèles d'interface utilisateur communs de manière standard, certaines des nouvelles fonctionnalités CSS brouillent la ligne entre le style et les fonctionnalités.
Nous défier à résoudre des problèmes logiques avec uniquement CSS et HTML peut nous forcer à passer du temps de qualité avec certaines des fonctionnalités nouvelles de programmes de CSS, telles que les propriétés personnalisées et les fonctions logiques. Il n'était toujours pas clair comment ceux-ci pouvaient être utilisés pour construire un solveur Sudoku en utilisant uniquement CSS, mais aussi fou que l'idée sonnait, la logique basée sur les contraintes de Sudoku semblait être compatible avec la nature déclarative de CSS, donc je n'ai pas été choqué de trouver quelqu'un d'autre prétendu avoir construit un «solveur de solution CSS3 Sudoku». Il s'est avéré que cela ressemblait plus à un validateur Sudoku dans CSS qu'à un solveur. Il a également utilisé un tout petit peu de javascript pour travailler avec des zones de texte.
Après des jours d'essayer vaillamment de construire un solveur et une application de générateur de Sudoku complet en CSS pur, j'ai appris trois choses.
Cependant, nous pouvons réaliser un solveur Sudoku et une application de générateur pour le Sudoku de 16 carrés avec lequel vous pouvez jouer ci-dessous, puis nous décomposons le fonctionnement de ses fonctionnalités. Où est votre dieu maintenant, simple puzzle destiné aux jeunes enfants?
Étant donné que nous expérimentons CSS, nous sommes contractuellement obligés d'inclure quelque chose de visuellement intéressant, bien que rien de trop exagéré, car les joueurs de Sudoku semblent apprécier une interface utilisateur qui reste à l'écart. À mon avis, la façon dont vous sélectionnez des numéros sur certaines des applications Sudoku pourrait être plus intuitive, j'ai donc décidé d'appliquer le modèle d'interface utilisateur du menu radial, qui remonte à des jours de Macintosh noir et blanc et est toujours populaire dans les jeux vidéo modernes. Quelqu'un a réellement construit une belle bibliothèque CSS pure pour les menus radiaux, mais j'ai eu le béguin pour React Planet car j'aime la façon dont il capture à la fois un élément avec le cercle autour de lui, et comment il affiche de manière attrayante les actions disponibles. Je voulais voir si je pouvais construire un effet similaire avec Just CSS.
J'ai pris une partie du code du cercle en pointillé de ce stylo, puis j'ai fait les chiffres à partir d'étiquettes en utilisant l'ancien tour de la frontière: 50%, puis j'ai utilisé le positionnement absolu pour faire en sorte que les chiffres «collent» au point correct sur le cercle en pointillé même lorsque l'animation le fait changer la taille.
.Context .number.top { Contexte: vert; marge-gauche: auto; marge droite: auto; à gauche: 0; à droite: 0; En haut: -12.5px; } .Context .number.left { Contexte: Orange; marge: auto; marge-fond: Auto; en haut: 0; en bas: 0; Gauche: -12.5px; }
L'animation atténue le sélecteur de numéros tout en faisant plus haut de son indice Z pour qu'il devienne cliquable. Nous animons également la marge supérieure et gauche de 50% à zéro afin que le cercle se développe du centre pour remplir l'espace disponible.
@keyframes rebond-out { 0% { Z-Index: -1; Largeur: 35%; hauteur: 35%; marge-gauche: 50%; marge: 50%; Opacité: 0; } 100% { Z-Index: 2; Opacité: 1; Largeur: var (- Circle-Radius); hauteur: var (- cercle-radius); } }
Ensuite, pour simuler la physique gonflable similaire à React Planet, j'utilise une fonction cubic-bezier () sur l'animation. Le site Web Easings.net a été d'une grande aide pour faciliter les fonctions d'assouplissement.
.contexte { Animation: rebond-out cubic-bezier (.68, -0,6, .32, 2.5) .5s Forward; }
La sélection des valeurs et le comportement de l'ouverture du sélecteur de valeur pour le carré sélectionné fonctionnent à l'aide de hacks de bouton radio, pour se rappeler quelles valeurs ont été sélectionnées et atteindre l'exclusivité mutuelle. CSS-Tricks a un excellent article sur la case à cocher et les hacks de boutons radio, donc je ne répéterai pas ces informations ici, mais je montrerai comment nous définissons les variables CSS au niveau de la grille CSS Sudoku en fonction des cases à cocher, car elle est au cœur du fonctionnement de cette expérience.
Comme nous utilisons des variables, nous pouvons obtenir le même comportement lorsqu'une valeur est définie, que ce soit l'utilisateur qui vérifie une zone pour spécifier une valeur, ou le générateur de puzzle définit la même valeur pour le carré. Il existe de nombreuses combinaisons de carrés et de valeurs, nous utilisons donc Sass plutôt que d'écrire toutes les combinaisons à la main. Nous créons également des valeurs de bit distinctes pour chaque combinaison de valeur carrée et une autre propriété personnalisée pour nous dire si le carré n'est pas résolu. En effet, CSS nous donne une capacité limitée à comparer une valeur à une autre (c'est possible mais peut être délicat). Nous définissons ces valeurs d'une manière qui pourrait sembler un peu étrange au début, mais nous faciliterons la vie lorsqu'il s'agit de valider si un ensemble de valeurs carrées de Sudoku est résoluble ou non.
@for $ i de 1 à 16 { @for $ j de 1 à 4 { #Select - # {$ j} -value-square - # {$ i}: vérifié ~ .sudoku { - square - # {$ i} -unsolved: 0; - square - # {$ i} -equals - # {$ j}: 1; } } }
Le docteur Google nous dit que même avec seulement 16 carrés, il y a quatre milliards de combinaisons possibles de quatre nombres. Mais un programme qui force brute toutes ces combinaisons et sort ceux qui sont valides en fonction des règles de Sudoku montrent qu'il n'y a que 288 solutions valides dans 4 × 4 Sudoku, ce qui fait une grande différence par rapport au nombre de solutions valides possibles dans une grille 9 × 9. Avec seulement 288 solutions possibles, c'est là que Sass peut vraiment prendre son propre temps. Je ne sais toujours pas si CSS est un langage complet Turing, mais Sass l'est, et il nous donne quelques structures de données appropriées, telles que les listes. Avec un peu de magie regex, nous pouvons transformer la liste des puzzles 4 × 4 valides liés ci-dessus en une liste bidimensionnelle propulsée par Sass!
$ Solutions: ((1,2,3,4,3,4,1,2,2,1,4,3,4,3,2,1), (3,1,2,4,2,4,1,3,1,3,4,2,4,2,3,1), (1,2,3,4,3,4,1,2,3,4,1,4,1,2,3), / ... Plus tard ... * / (2,4,3,1,3,1,4,2,4,2,1,3,1,3,2,4), (4,3,2,1,2,1,4,3,3,4,1,2,1,2,3,4));
Doux! Si notre piratage CSS était une application à plusieurs niveaux, ce serait notre base de données. La validation aurait pu utiliser la même approche pour vérifier les valeurs de lignes et de colonnes comme le validateur 9 × 9 que nous avons vu dans l'introduction, mais comme nous connaissons la réponse, il semble que nous ne devrions pas avoir besoin de prendre la peine de vérifier les blocs et les colonnes et les lignes. Au lieu de cela, nous pouvons vérifier si les numéros entrés pourraient toujours être un puzzle valide ou non. Dans Pseudocode, cela pourrait ressembler à quelque chose:
foreach (s en carrés) { if (SolutionsContains (S.Value, S.Index) ou S.isunsolved ()) { showValidationError (); } }
Rappelez-vous que nous avons créé ces variables étranges chaque fois qu'une valeur carrée est sélectionnée?
- square - # {$ i} -unsolved: 0; - square - # {$ i} -equals - # {$ j}: 1;
Alors maintenant, nous avons des réponses aux deux questions dans la condition à la ligne 3 du pseudocode ci-dessus, mais comment pouvons-nous faire un logique ou un opérateur dans CSS? Il y a un excellent article sur CSS-Tricks sur l'utilisation de Calc () pour simuler les opérateurs logiques dans CSS, et je ne suis pas sûr que j'aurais même pensé à une partie du code de mon solveur Sudoku sans lui, mais certaines des formules expliquées dans cet article deviennent un peu difficiles à manivelle, surtout si vous voulez faire des Ands et des OR avec plus de deux opérands. Par exemple, nous avons besoin de l'équivalent CSS de ce pseudocode:
if ((carréoneequalsone et squaretwoequalstwo /*...*/ et squaresixteenequalsone) ou (carréoneequalsone et squaretwoequalster /*...*/ et squaresixteenequalsone))) { sudokuisvalid (); } }
Eh bien, cet article montrant comment faire la logique à l'aide de calc () a été écrit en 2019. De nos jours, en plus de calc (), nous avons les fonctions mathématiques MIN () et Max () bien soutenues qui répondent encore mieux à nos besoins. Si vous Google «CSS MIN, MAX et CLAMP» (dont le dernier est juste un sucre pratique pour une combinaison de min () et max ()), vous trouverez de nombreux exemples qui montrent comment ils peuvent être utilisés pour simplifier la typographie des fluides. C'est un cas d'utilisation convaincant, mais vous pouvez utiliser ces fonctions mathématiques partout où vous utilisez un nombre, ce qui ajoute beaucoup de puissance à CSS. Par exemple, si vous passez des variables de drapeau de bits à CSS min (), cela équivaut à et. Si vous passez les mêmes drapeaux à CSS Max (), cela équivaut à Or. Nous pouvons prouver cela en utilisant les tables de vérité suivantes.
Nous pouvons devenir assez sophistiqués avec cela, surtout lorsque vous ajoutez le fait utile que nous sommes autorisés à faire tout ce que Calc () peut faire dans Min () et Max (). CSS a juste pris un pas de plus en étant sa propre langue de script étrange. Nous pouvons maintenant implémenter la condition dans notre pseudocode de validation ci-dessus dans CSS. (En pratique, nous générons cela à partir de SASS car c'est très répétitif.)
.sudoku { - carré-1-matches-puzzle-1: max (var (- carré-1-unsolved), var (- carré-1-equals-1, 0)); - Square-2-Matches-Puzzle-1: Max (var (- carré-2-unsolved), var (- carré-2-equals-2, 0)); /*...*/ - Square-16-Matches-Puzzle-1: Max (var (- carré-16-unsolved), var (- carré-16-equals-1, 0)); --puzzle-1-fond: min (var (- carré-1-matches-puzzle-1), /*...*/ var (- carré-16-matchs-puzzle-1)); --solution-fond: max (var (- puzzle-1-fond), /*...*/ var (- puzzle-288-fond)); }
En vérifiant si chaque carré n'est pas résolu ou a une valeur qui existe dans la même position dans l'une de nos solutions pré-calculées de la liste 2D SASS, nous pouvons produire une variable qui nous indique si les carrés actuellement définis existent dans un puzzle 4 × 4 Sudoku valide. Maintenant, tant que nous pouvons trouver quelque chose de numérique qui entraînera un comportement dans CSS, nous pouvons baser ce comportement CSS sur --solution. Par exemple, pour rendre notre grille en rouge lorsqu'elle est invalide, nous pouvons le mettre dans chaque carré:
.carré { Couleur: RGB (calc (255 * (1 - var (- solution-fond))), 0, 0); }
Toutes les propriétés CSS ne peuvent pas être motivées par un nombre, mais beaucoup le peuvent, et l'index z et l'opacité sont des propriétés CSS particulièrement polyvalentes pour cette utilisation. D'autres comportements peuvent être plus délicats mais souvent réalisables. Par exemple, j'étais un peu coincé en réfléchissant à la façon de déclencher l'animation Shake pour une grille non valide avec une propriété de drapeau de bits numériques afin que la grille secoue chaque fois qu'elle devenait invalide, mais c'est un excellent exemple de la façon dont le piratage CSS vous oblige à lire les spécifications et à comprendre les cas Edge pour chaque propriété. J'ai trouvé ma solution sur cette page sur la durée de l'animation.
Une valeur de 0, qui est la valeur par défaut, indique qu'aucune animation ne devrait se produire.
Nous pouvons donc baser la durée de l'animation de l'animation à shake sur --solution-solution et supprimer l'animation chaque fois qu'un nombre est cliqué en utilisant la pseudo-classe active pour faire la rediffusion de l'animation à chaque fois que la solution devient invalide et ne faites rien autrement.
#Select - # {$ j} -value-square - # {$ i}: actif { Animation: aucun; } #Select - # {$ j} -value-square - # {$ i}: vérifié ~ .sudoku { Animation: Shake cubic-bezier (.36, .07, .19, .97) calc ((clamp (0, 1 - var (- solution-fond), 1)) * 1s) Forward; }
Une application CSS Sudoku pure serait probablement impossible si nous n'avions pas de propriétés personnalisées CSS, et elles sont plus puissantes qu'elles ne semblent à première vue. La façon dont ils sont réévalués et mettent à jour l'interface utilisateur chaque fois qu'une propriété, ils dépendent des modifications, c'est comme une version plus simple de la réactivité que vous obtenez d'un framework JavaScript fantaisie comme Vue. Il est juste de dire que la réactivité est construite directement dans le navigateur sous la forme de variables CSS!
Maintenant que nous avons cette approche pour la validation et que notre feuille de style connaît la solution dans son subconscient chaque fois que nous définissons des valeurs valides dans notre Sudoku, nous sommes sur le point d'implémenter le solveur!
Rappelez-vous lorsque nous avons introduit ces variables intermédiaires?
.sudoku { --puzzle-1-fond: min (var (- carré-1-matches-puzzle-1), /*...*/ var (- carré-16-matchs-puzzle-1)); }
Ce n'était pas seulement pour rendre le code de validation plus facile à écrire et à comprendre. Savoir lequel des 288 puzzles possibles est apparié nous permet d'écrire le solveur!
# Non-solution { Z-Index: 1; Couleur: rouge; } @for $ Solution-Index de 1 à 288 { étiqueter [pour = solution - # {$ solution-index}] { curseur: pointeur; z-index: calc (var (- puzzle - # {$ solution-index} -found) * # {$ solution-index}); } #solution - # {$ solution-index}: vérifié ~ .sudoku { @for $ carré de 1 à 16 { - square - # {$ carré} -solution: "# {nth (nth ($ solutions, $ solution-index), $ carré)}"; - carré - # {$ carré} -Color: gris; --auto - # {$ carré}: 1; }
J'ai mis le pluriel facultatif dans le mot «puzzle (s)» ci-dessus car, si l'utilisateur n'a pas rempli de nombreux carrés, il est possible qu'il existe plusieurs solutions valides. Je creuse des résolveurs comme ce javascript qui peut produire rapidement une solution même si vous n'avez pas spécifié suffisamment de valeurs pour qu'un humain puisse le résoudre sans deviner.
L'astuce de mon solveur CSS est que si le bouton «Solve» ressemble à un seul bouton, il s'agit en fait de 288 étiquettes de bouton radio empilées l'une sur l'autre - mais toutes se ressemblent. Imaginez une pile de cartes: ils ont tous le même design à l'arrière, mais des valeurs différentes à l'avant. La logique du solveur met la carte avec la solution sur le dessus de la pile avec l'index z, donc si vous le ramassez et lisez l'autre côté, vous aurez toujours la bonne solution. Cela fonctionne toujours s'il existe plusieurs solutions correctes, car la solution qui vient plus tard dans notre liste de réponses valides sera placée en haut, car nous calculons l'index Z en multipliant l'indicateur par $ index. Si aucune solution n'est adaptée, l'index z de tous les boutons de résolution sera nul et, puisque la version désactivée du bouton avec le message "Puzzle non valide" en a une index z, elle apparaîtra en haut. Si le puzzle numéro un est la solution, nous verrons toujours le bouton Puzzle One, car le bouton non valide arrive plus tôt dans le HTML.
Le contexte d'empilement peut se comporter de façon inattendue si vous ne l'avez pas lu, donc c'est une belle illustration de l'un des comportements d'empilement non évidents.
Nous pouvons considérer les puzzles de génération comme une autre version du solveur avec des exigences supplémentaires.
CSS n'a pas de fonction aléatoire () (bien que Sass le fait), il peut donc ne pas être évident comment nous pouvons obtenir un comportement différent chaque fois que nous appuyons sur le même bouton. Mais l'explication du solveur ci-dessus était un peu un spoiler car il fait déjà quelque chose de similaire avec un bouton qui ressemble à un seul élément mais qui est en fait différent en fonction de la solution valide actuelle.
La question avec le bouton «Générer» est de savoir comment obtenir un résultat imprévisible à chaque fois que nous cliquez. Crédit complet à Alvaro Montoro pour son article sur CSS-Tricks sur la façon de générer des valeurs apparemment aléatoires avec seulement CSS. La combinaison des hacks de boutons radio et de l'animation de l'ordre d'empilement semble bien fonctionner. J'ai essayé de voir si je pouvais le faire sans marquage supplémentaire, mais j'ai conclu que cette approche est la meilleure et la plus simple. Pour réutiliser l'analogie du jeu de cartes de l'explication du solveur, c'est comme si le jeu de cartes de puzzle se mélange invisiblement tout le temps afin que chaque fois que vous prenez une carte, vous découvrez qu'il a un visage différent.
Nous pouvons combiner ce pseudo aléatoire avec l'aléatoire réel offert par la fonction sass random () pour donner à notre valeur de relecture de jeu sudoku.
@for $ j de 0 à 287 { étiqueter [pour = générer # {$ j}] { Animation-deLay: # {$ j * .35s}; } étiqueter [pour = générer # {$ j}]: actif: après { Z-Index: 300; Largeur: 100%; } #GENERETER # {$ j}: vérifié ~ .sudoku { $ BlockCounts: (1: 2, 2: 2, 3: 3, 4: 2); $ shufflesquares: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); @for $ carré de 1 à 16 { $ index1: aléatoire (16); $ index2: aléatoire (16); $ temp: nième ($ shufflesquares, $ index1); $ shufflesquares: set-nth ($ shufflesquares, $ index1, nth ($ shufflesquares, $ index2)); $ shufflesquares: set-nth ($ shufflesquares, $ index2, $ temp); } @Each $ carré dans $ shufflesquares { $ Row: Ceil ($ carré / 4); $ colonne: 1 ($ carré - 1)% 4; $ block: if ($ row & lt; 3, 1, 3) if ($ colonne 0) { $ BlockCounts: Map-Merge ($ BlockCounts, ($ Block: $ Count - 1)); - square - # {$ carré} -unsolved: 0; - square - # {$ carré} -equals - # {$ Val}: 1; @for $ autre valeur de 1 à 4 { @if ($ autre valeur! = $ val) { - square - # {$ carré} -equals - # {$ autre valeur}: 0; } } - carré - # {$ carré} -Color: gris; --auto - # {$ carré}: 1; } } } }
Pour chaque «bloc» (c'est Sudoku-Speak pour ces sections 4 × 4 de la grille Sudoku avec la bordure épaisse autour d'eux), nous utilisons Sass pour choisir au hasard deux sur quatre carrés pour résoudre, à l'exception d'un carré «gimme» qui n'a qu'un seul carré non résolu. Étant donné que la logique de validation et la logique du solveur utilisent les variables plutôt que d'être directement en fonction des valeurs qui ont été vérifiées à l'aide du sélecteur de valeur, la logique de validation et de résolution se comportent toutes deux de la même manière. Cela signifie que les valeurs générées sont traitées de la même manière que si l'utilisateur avait sélectionné individuellement chaque valeur.
Voici la minuterie qui tourne dans les onze premières secondes.
Nous plongerons dans le CSS pour la minuterie de résolution dans un instant, mais montrons d'abord à quoi ressemble l'un des chiffres sans que le débordement CSS ne se soit caché, et avec une bordure verte autour de l'élément pour montrer la pièce qui serait visible pour l'utilisateur à chaque étape de l'animation.
Nous utilisons une animation infiniment répétée pour les images clés pour déplacer la liste des chiffres possibles un caractère à gauche à un intervalle souhaité (nous utilisons une police monospacée afin que nous puissions être sûrs que chaque personnage occupera la même largeur exacte). Le chiffre des secondes passera de zéro à neuf, et le chiffre suivant ne devrait atteindre que cinq, augmentant une fois par dix secondes avant que les deux chiffres des secondes ne doivent se réinitialiser à zéro.
Chaque chiffre est l'animation en utilisant la même technique que vous pouvez utiliser pour animer une feuille de sprite en CSS, sauf au lieu de déplacer un arrière-plan d'image pour réaliser un effet d'animation, nous déplacons un pseudo élément contenant les chiffres possibles.
Comme pour de nombreuses tâches dans CSS, il y a plus d'une façon de faire un compteur animé dans CSS. Mais certains ne fonctionnent pas de croisement et exigent vraiment un préprocesseur pour maintenir le code succinct. J'aime mon approche car c'est assez court. CSS fait le levage lourd pour comprendre quand et comment passer au chiffre suivant. Tout ce que le balisage doit faire est de créer un espace réservé où va chaque chiffre, nous donnant une certaine liberté pour la façon dont nous présentons notre minuterie.
Voici le balisage:
<div> <div> </div> <div>: </div> <div> </div> <div> </div> </div>
… Et le CSS:
.stopwatch { Texte-aligne: Centre; Font-Family: Monospace; marge-fond: 10px; } .symbole { Largeur: 1ch; débordement: caché; Affichage: en ligne-flex; taille de police: 5ch; } .Symbol: Nth-Child (1) :: After { Animation: étapes de TEN 3600 (6, fin) infinie; Contenu: '012345'; } .Symbol: Nth-Child (2) :: After { Animation: étapes des unités 600 (10, fin) Infinite; Contenu: '0123456789'; } .Symbol: Nth-Child (4) :: After { Animation: étapes des dizaines des années 60 (6, fin) infinies; Contenu: '012345'; } .Symbol: Nth-Child (5) :: After { Animation: unités 10 étapes (10, fin) infinies; Contenu: '0123456789'; } @KeyFrames Unités { à { Transform: Translatex (-10ch); } } @KeyFrames Tens { à { Transform: Translatex (-6ch); } }
Vous remarquerez peut-être que le comptoir recommence depuis le début après une heure. C'est parce que tous les dénombrements d'itération sont définis sur Infinite. Nous pourrions le réparer, mais je pense que si quelqu'un passe une heure à en résoudre un, ils ont de plus gros problèmes qu'un puzzle de Sudoku pour enfants. ?
Ce qui serait injuste, cependant, c'est si nous permettons au même minuteur de continuer à cocher même lorsque l'utilisateur génère un nouveau puzzle. Pouvons-nous le faire réinitialiser? Il s'avère que nous avons déjà résolu ce problème dans la première étape de cet article, où nous avons supprimé et réévalué conditionnellement l'animation pour notre sélecteur de nombres en utilisant la pseudo-classe active. Cette fois, c'est en fait plus simple car chaque fois que nous appuyons sur le bouton «Générer», nous voulons supprimer l'animation sur tous les chiffres pour les ramener à zéro. Ensuite, l'animation recommencera lorsque le bouton radio n'est plus actif. Donc, ce n'est qu'une seule ligne de CSS, nous devons faire réinitialiser la minuterie à chaque fois que nous générons!
entrée [name = générer]: actif ~ .stopwatch .Symbol :: après { Animation: aucun; }
Même lorsque le puzzle est résolu, je veux offrir une valeur de relecture en donnant au joueur des commentaires visuels sur leurs performances temporelles et en les mettant au défi de résoudre des énigmes plus rapidement. Je veux également vous récompenser pour avoir été si loin dans l'article en vous donnant une jauge circulaire minimaliste que vous pourriez réutiliser dans vos propres projets. Voici un stylo autonome avec la jauge circulaire pour que vous puissiez expérimenter:
Nous appliquons les mêmes principes utilisés dans l'écran de victoire du jeu, sauf, dans ce stylo, la note affichée est contrôlée avec des hacks de bouton radio, tandis que dans le jeu, il est contrôlé par l'animation qui passe lentement à une note inférieure au fil du temps. La jauge du jeu est cachée en utilisant une opacité zéro et ne s'affiche (et interrompue) que lorsque nous détectons que le puzzle a été résolu manuellement.
Expliquons comment nous créons l'illusion d'un demi-cercle divisé en deux côtés par couleur. C'est en fait un cercle CSS complet avec sa moitié inférieure cachée en utilisant le débordement: caché.
Nous appliquons les deux couleurs en utilisant un pseudo-élément qui remplit la moitié du
Ensuite, nous avons coupé un trou au milieu pour faire un beignet, en utilisant un autre cercle rempli de couleur d'arrière-plan du jeu, et au centre à l'intérieur du cercle plus grand à l'aide de Flexbox.
Ensuite, cachez la moitié de celui-ci en faisant la taille du conteneur à moitié aussi haut que le cercle complet et, encore une fois, en utilisant un débordement: caché.
Maintenant, si nous tournons notre beignet, il semble que la jauge se remplit de vert ou de perdre du vert, selon que nous tournons notre beignet par des degrés négatifs ou positifs!
Nous aimerions mettre des étiquettes aux deux extrémités de la jauge et une description entre eux, et il s'avère que Flexbox est une solution élégante:
#notation { taille de police: 30px; Affichage: flex; Largeur: 300px; justifier-contenu: espace-intermédiaire; }
Voici le balisage:
<div> <div>? </div> <div> </div> <div>? </div> </div>
C'est tout ce dont nous avons besoin pour positionner nos étiquettes. Si la notation
Quant au contrôle de ce que dit la description, il est similaire à l'astuce que nous avons utilisée pour notre minuterie, sauf que cette fois, nous le faisons verticalement plutôt que horizontalement car les descriptions de rétroaction sont de longueur variable. Mais ils ont toujours la même hauteur.
J'ai ouvert cet article avec des questions sur la question de savoir si CSS est un langage de programmation. Il est difficile de faire valoir la logique que nous avons pu implémenter en utilisant uniquement CSS ne programmer pas, mais une partie de celle-ci est le moins inhabituelle de CSS. Comme pour beaucoup de choses dans le monde de la technologie, la réponse semble être «cela dépend» et autant que nous avons appris sur CSS à travers cette expérience, nous avons également illustré que la programmation concerne autant la mentalité que la technologie.
Aucun article de piratage de CSS n'est complet sans l'avertissement que, bien que nous ayons montré, nous pouvons implémenter une logique sophistiquée dans CSS et en apprendre beaucoup dans le processus, la plupart du temps, nous ne devrions probablement pas le faire en production, en raison de la maintenabilité, de l'accessibilité et de quelques autres mots se terminant par «itilité».
Mais nous avons également vu que certaines choses - comme ce que je considère comme la réactivité intégrée que vous obtenez avec les variables CSS - sont assez pratiques dans CSS mais pourraient nous obliger à passer par des cerceaux en JavaScript, et probablement à utiliser un cadre. En repoussant les limites de CSS, nous avons fini par créer une jauge circulaire qui, je crois, pourrait raisonnablement être utilisée dans une application de production, et pourrait même être la bonne chose par rapport à la recherche d'un widget JavaScript qui pourrait être lourd et faire plus que nous avons vraiment besoin.
Sur ma liste de souhaits pour l'application CSS Sudoku se trouve un bouton de réinitialisation. Actuellement, si vous souhaitez démarrer un nouveau jeu Sudoku, vous devez actualiser la page. C'est une limitation inhérente des hacks de boutons radio qui rend CSS pirater différent de la programmation conventionnelle. À un moment donné, j'ai cru avoir trouvé une solution lorsque je pensais que les animations pouvaient être utilisées pour définir des variables CSS - mais il s'avère que fait partie de CSS Houdini et que cela ne soutient que dans des navigateurs à base de chrome. Si et quand cela est pris en charge partout, il ouvrira une boîte de piratage de Pandora et sera très amusant. Dans un prochain article, je peux même explorer pourquoi cette fonctionnalité inoffensive que nous avons dans Chrome change la donne pour le piratage CSS.
Le jury est toujours là pour savoir si un solveur de Sudoku complet de 81 carrés est possible dans CSS, mais si vous êtes curieux de le savoir, laissez vos commentaires dans les commentaires. Si suffisamment de personnes le veulent, nous pouvons descendre ce terrier de lapin et voir quels coins sombres de CSS nous pouvons éclairer dans le processus.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!