Chargeurs à élément unique : passez à la 3D ! Intelligence des données PlatoBlockchain. Recherche verticale. Aï.

Chargeurs à élément unique : en 3D !

Pour ce quatrième et dernier article de notre petite série sur les chargeurs monoélément, nous allons explorer des modèles 3D. Lors de la création d'un élément 3D, il est difficile d'imaginer qu'un seul élément HTML suffise pour simuler quelque chose comme les six faces d'un cube. Mais peut-être pourrions-nous nous en sortir avec quelque chose de plus cubique.comme au lieu de cela, en affichant uniquement les trois côtés avant de la forme – c’est tout à fait possible et c’est ce que nous allons faire ensemble.

Série d'articles

Le chargeur de cube divisé

Voici un chargeur 3D où un cube est divisé en deux parties, mais n'est réalisé qu'avec un seul élément :

CodePen Intégrer la solution de secours

Chaque moitié du cube est réalisée à l'aide d'un pseudo-élément :

Chargeurs à élément unique : passez à la 3D ! Intelligence des données PlatoBlockchain. Recherche verticale. Aï.
Chargeurs à élément unique : en 3D !

Cool, non ?! Nous pouvons utiliser un dégradé conique avec CSS clip-path sur l'élément ::before ainsi que ::after pseudos pour simuler les trois faces visibles d’un cube 3D. La marge négative est ce qui rassemble les deux pseudos pour se chevaucher et simuler un cube complet. Le reste de notre travail consiste principalement à animer ces deux moitiés pour obtenir des chargeurs soignés !

Voyons un visuel qui explique les calculs derrière les points de tracé utilisés pour créer cet élément en forme de cube :

Chargeurs à élément unique : passez à la 3D ! Intelligence des données PlatoBlockchain. Recherche verticale. Aï.
Chargeurs à élément unique : en 3D !

Nous avons nos variables et une équation, alors mettons-les en œuvre. Tout d’abord, nous allons établir nos variables et définir le dimensionnement du principal .loader élément:

.loader { --s: 150px; /* control the size */ --_d: calc(0.353 * var(--s)); /* 0.353 = sin(45deg)/2 */ width: calc(var(--s) + var(--_d)); aspect-ratio: 1; display: flex;
}

Rien de bien fou pour l'instant. Nous avons un 150px carré configuré comme un conteneur flexible. Maintenant, nous établissons nos pseudos :

.loader::before,
.loader::after { content: ""; flex: 1;
}

Ce sont deux moitiés dans le .loader récipient. Nous devons les peindre, c'est donc là que notre dégradé conique coups de pied dans:

.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}

Le dégradé est là, mais ça a l'air bizarre. Nous devons le faire attachez-le à l'élément:

.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0); clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}

Assurons-nous que les deux moitiés se chevauchent avec un marge négative:

.loader::before { margin-right: calc(var(--_d) / -2);
} .loader::after { margin-left: calc(var(--_d) / -2);
}

Maintenant, faisons-les bouger !

.loader::before,
.loader::after { /* same as before */ animation: load 1.5s infinite cubic-bezier(0, .5, .5, 1.8) alternate;
} .loader::after { /* same as before */ animation-delay: -.75s
} @keyframes load{ 0%, 40% { transform: translateY(calc(var(--s) / -4)) } 60%, 100% { transform: translateY(calc(var(--s) / 4)) }
}

Voici à nouveau la démo finale :

CodePen Intégrer la solution de secours

Le chargeur de cube de progression

Utilisons la même technique pour créer un chargeur de progression 3D. Oui, toujours un seul élément !

CodePen Intégrer la solution de secours

Nous ne changeons rien en ce qui concerne la simulation du cube de la même manière que nous le faisions auparavant, à part changer la hauteur et le rapport hauteur/largeur du chargeur. L'animation que nous réalisons repose sur une technique étonnamment simple où nous mettons à jour la largeur du côté gauche tandis que le côté droit remplit l'espace restant, grâce à flex-grow: 1.

La première étape consiste à ajouter un peu de transparence sur le côté droit en utilisant opacity:

CodePen Intégrer la solution de secours

Cela simule l'effet selon lequel un côté du cube est rempli tandis que l'autre est vide. Ensuite, nous mettons à jour la couleur du côté gauche. Pour ce faire, soit nous mettons à jour les trois couleurs à l'intérieur du dégradé conique, soit nous le faisons en ajoutant une couleur de fond avec un background-blend-mode:

.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply;
}

Cette astuce ne nous permet de mettre à jour la couleur qu'une seule fois. Le côté droit du chargeur se fond dans les trois nuances de blanc du dégradé conique pour créer trois nouvelles nuances de notre couleur, même si nous n'utilisons qu'une seule valeur de couleur. Supercherie des couleurs !

CodePen Intégrer la solution de secours

Animons la largeur du côté gauche du chargeur :

CodePen Intégrer la solution de secours

Oups, l'animation est un peu étrange au début ! Remarquez comment cela commence en quelque sorte en dehors du cube ? C'est parce que nous commençons l'animation au 0% largeur. Mais à cause du clip-path et la marge négative que nous utilisons, ce que nous devons faire à la place est de partir de notre --_d variable, que nous avons utilisée pour définir la clip-path points et la marge négative :

@keyframes load { 0%, 5% {width: var(--_d); } 95%, 100% {width: 100%; }
}

C'est un peu mieux :

CodePen Intégrer la solution de secours

Mais nous pouvons rendre cette animation encore plus fluide. Avez-vous remarqué qu'il nous manque un petit quelque chose ? Laissez-moi vous montrer une capture d'écran pour comparer à quoi devrait ressembler la démo finale avec cette dernière démo :

Chargeurs à élément unique : passez à la 3D ! Intelligence des données PlatoBlockchain. Recherche verticale. Aï.

C'est la face inférieure du cube ! Puisque le deuxième élément est transparent, nous devons voir la face inférieure de ce rectangle, comme vous pouvez le voir dans l'exemple de gauche. C'est subtil, mais ça devrait être là !

Nous pouvons ajouter un dégradé à l'élément principal et le découper comme nous l'avons fait avec les pseudos :

background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat;

Voici le code complet une fois que tout est rassemblé :

.loader { --s: 100px; /* control the size */ --_d: calc(0.353*var(--s)); /* 0.353 = sin(45deg) / 2 */ height: var(--s); aspect-ratio: 3; display: flex; background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat; clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}
.loader::before,
.loader::after { content: ""; clip-path: inherit; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}
.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply; margin-right: calc(var(--_d) / -2); animation: load 2.5s infinite linear;
}
.loader:after { flex: 1; margin-left: calc(var(--_d) / -2); opacity: 0.4;
} @keyframes load { 0%, 5% { width: var(--_d); } 95%, 100% { width: 100%; }
}
CodePen Intégrer la solution de secours

C'est ça! Nous venons d'utiliser une technique intelligente qui utilise des pseudo-éléments, des dégradés coniques, un découpage, une fusion d'arrière-plan et des marges négatives pour obtenir, non pas un, mais deux de jolis chargeurs 3D avec rien de plus qu'un seul élément dans le balisage.

Plus de 3D

On peut encore aller plus loin et simuler une infinité de cubes 3D à partir d’un seul élément — oui, c’est possible ! Voici une grille de cubes :

CodePen Intégrer la solution de secours

Cette démo et les démos suivantes ne sont pas prises en charge dans Safari au moment de la rédaction.

Fou, non ? Nous créons maintenant un motif répété de cubes réalisés à partir d’un seul élément… et sans pseudos non plus ! Je n’entrerai pas dans les détails des calculs que nous utilisons (il contient des nombres très spécifiques), mais voici une figure pour visualiser comment nous en sommes arrivés là :

Chargeurs à élément unique : passez à la 3D ! Intelligence des données PlatoBlockchain. Recherche verticale. Aï.
Chargeurs à élément unique : en 3D !

Nous utilisons d'abord un conic-gradient pour créer le motif de cube répétitif. La répétition du motif est contrôlée par trois variables :

  • --size: Fidèle à son nom, cela contrôle la taille de chaque cube.
  • --m: Cela représente le nombre de colonnes.
  • --n: C'est le nombre de lignes.
  • --gap: c'est l'écart ou la distance entre les cubes
.cube { --size: 40px; --m: 4; --n: 5; --gap :10px; aspect-ratio: var(--m) / var(--n); width: calc(var(--m) * (1.353 * var(--size) + var(--gap))); background: conic-gradient(from -90deg at var(--size) calc(0.353 * var(--size)), #249FAB 135deg, #81C5A3 0 270deg, #26609D 0) /* update the colors here */ 0 0 / calc(100% / var(--m)) calc(100% / var(--n));
}

Ensuite, nous appliquons un calque de masque en utilisant un autre motif ayant la même taille. C'est la partie la plus délicate de cette idée. En utilisant une combinaison d'un linear-gradient et conic-gradient nous allons couper quelques parties de notre élément pour ne garder visibles que les formes de cube.

.cube { /* etc. */ mask: linear-gradient(to bottom right, #0000 calc(0.25 * var(--size)), #000 0 calc(100% - calc(0.25 * var(--size)) - 1.414 * var(--gap)), #0000 0), conic-gradient(from -90deg at right var(--gap) bottom var(--gap), #000 90deg, #0000 0); mask-size: calc(100% / var(--m)) calc(100% / var(--n)); mask-composite: intersect;
}

Le code peut paraître un peu complexe mais grâce aux variables CSS, il suffit de mettre à jour quelques valeurs pour contrôler notre matrice de cubes. Besoin d'une grille 10⨉10 ? Mettre à jour le --m ainsi que --n variables à 10. Besoin d'un espace plus large entre les cubes ? Mettre à jour le --gap valeur. Les valeurs de couleur ne sont utilisées qu'une seule fois, alors mettez-les à jour pour une nouvelle palette de couleurs !

Maintenant que nous disposons d’une autre technique 3D, utilisons-la pour créer des variantes du chargeur en jouant avec différentes animations. Par exemple, que diriez-vous d’un motif répétitif de cubes glissant à l’infini de gauche à droite ?

CodePen Intégrer la solution de secours

Ce chargeur définit quatre cubes sur une seule ligne. Cela signifie que notre --n valeur est 4 ainsi que --m est égal à 1 . En d’autres termes, nous n’en avons plus besoin !

Au lieu de cela, nous pouvons travailler avec le --size ainsi que --gap variables dans un conteneur de grille :

.loader { --size: 70px; --gap: 15px; width: calc(3 * (1.353 * var(--size) + var(--gap))); display: grid; aspect-ratio: 3;
}

C'est notre conteneur. Nous avons quatre cubes, mais nous souhaitons n'en afficher que trois dans le conteneur à la fois afin qu'il y en ait toujours un qui glisse à l'intérieur et un qui sort. C'est pourquoi nous prenons en compte la largeur par 3 et réglez le rapport hauteur/largeur sur 3 également.

Assurons-nous que notre motif de cube est configuré pour une largeur de quatre cubes. Nous allons faire cela sur le conteneur ::before pseudo-élément:

.loader::before { content: ""; width: calc(4 * 100% / 3); /* Code to create four cubes */
}

Maintenant que nous avons quatre cubes dans un conteneur de trois cubes, nous pouvons justifier le motif de cube jusqu'à la fin du conteneur de grille pour le déborder, affichant les trois derniers cubes :

.loader { /* same as before */ justify-content: end;
}

Voici ce que nous avons jusqu’à présent, avec un contour rouge pour montrer les limites du conteneur de grille :

CodePen Intégrer la solution de secours

Il ne nous reste plus qu'à déplacer le pseudo-élément vers la droite en ajoutant notre animation :

@keyframes load { to { transform: translate(calc(100% / 4)); }
}
CodePen Intégrer la solution de secours

Avez-vous compris l'astuce de l'animation ? Terminons en masquant le motif du cube débordant et en ajoutant une touche de masquage pour créer cet effet de fondu qui marque le début et la fin :

.loader { --size: 70px; --gap: 15px; width: calc(3*(1.353*var(--s) + var(--g))); display: grid; justify-items: end; aspect-ratio: 3; overflow: hidden; mask: linear-gradient(90deg, #0000, #000 30px calc(100% - 30px), #0000);
}
CodePen Intégrer la solution de secours

Nous pouvons rendre cela beaucoup plus flexible en introduisant une variable, --n, pour définir le nombre de cubes affichés simultanément dans le conteneur. Et comme le nombre total de cubes dans le motif doit être supérieur à un --n, nous pouvons exprimer cela comme calc(var(--n) + 1).

Voici l’intégralité :

CodePen Intégrer la solution de secours

OK, un autre chargeur 3D similaire mais dont les cubes changent de couleur successivement au lieu de glisser :

CodePen Intégrer la solution de secours

Nous allons nous appuyer sur un fond animé avec background-blend-mode pour celui-ci :

.loader { /* ... */ background: linear-gradient(#ff1818 0 0) 0% / calc(100% / 3) 100% no-repeat, /* ... */; background-blend-mode: multiply; /* ... */ animation: load steps(3) 1.5s infinite;
}
@keyframes load { to { background-position: 150%; }
}

J'ai supprimé le code superflu utilisé pour créer la même mise en page que le dernier exemple, mais avec trois cubes au lieu de quatre. Ce que j'ajoute ici est un dégradé défini avec une couleur spécifique qui se mélange au dégradé conique, comme nous l'avons fait précédemment pour le chargeur 3D de la barre de progression.

À partir de là, il anime le dégradé d’arrière-plan background-position sous la forme d'une animation en trois étapes pour faire clignoter les couleurs des cubes une à la fois.

Si vous n'êtes pas familier avec les valeurs que j'utilise pour background-position et la syntaxe d'arrière-plan, je recommande vivement un de mes articles précédents et l'un des mes réponses Stack Overflow. Vous y trouverez une explication très détaillée.

Pouvons-nous mettre à jour le nombre de cubes pour en faire des variables ?

Oui, j'ai un solution pour ça, mais j'aimerais que vous y essayiez plutôt que de l'intégrer ici. Prenez ce que nous avons appris de l’exemple précédent et essayez de faire de même avec celui-ci – puis partagez votre travail dans les commentaires !

Des variantes à gogo !

Comme les trois autres articles de cette série, j'aimerais vous laisser un peu d'inspiration pour aller de l'avant et créer vos propres chargeurs. Voici une collection qui comprend les chargeurs 3D que nous avons réalisés ensemble, ainsi que quelques autres pour laisser libre cours à votre imagination :

CodePen Intégrer la solution de secours

C'est une enveloppe

J'espère que vous avez apprécié passer du temps à créer des chargeurs à élément unique avec moi ces dernières semaines. C'est fou que nous ayons commencé avec un spinner apparemment simple, puis ajouté progressivement de nouvelles pièces pour travailler nous-mêmes jusqu'à des techniques 3D qui n'utilisent encore qu'un seul élément dans le balisage. C’est exactement à quoi ressemble CSS lorsque nous exploitons ses pouvoirs : évolutif, flexible et réutilisable.

Merci encore d'avoir lu cette petite série ! Je termine en vous rappelant que j'ai un collection de plus de 500 chargeurs si vous cherchez plus d’idées et d’inspiration.

Série d'articles


Chargeurs à élément unique : en 3D ! publié à l'origine le Astuces CSS. Vous devriez recevoir le bulletin.

Horodatage:

Plus de Astuces CSS