Techniques CSS pour effet d'entraînement matériel

Un guide sur différentes techniques pour l'effet d'entraînement à l'aide de CSS et JavaScript

J'ai récemment dû implémenter l'effet d'entraînement de la conception de matériaux dans une application Web. Et puis j'ai réalisé que je n'avais aucune idée de la façon dont cela avait été mis en œuvre. Cela m'a amené à étudier les implémentations existantes et même à proposer une nouvelle technique qui pourrait vous être utile.

Quel est cet effet d'entraînement?

Attendez, vous ne connaissez pas l’effet d'entraînement de Material Design de Google? Avez-vous vécu dans une grotte pendant combien d'années?

L'effet d'entraînement est utilisé lorsque vous appuyez sur un bouton. Cela fonctionne de la même manière pour les interactions avec la souris ou le toucher.

La position sur laquelle vous cliquez ou touchez le bouton s'appelle le point de contact. À partir de là, une ondulation se déplace vers l’extérieur, perdant son opacité à mesure qu’elle grossit jusqu’à remplir tout le bouton. Ensuite, il disparaît complètement.

La dynamique de cet effet d'entraînement est similaire à celle que vous obtenez lorsque vous touchez une surface liquide ou lorsque vous laissez tomber une pierre dans un lac.

Les ondulations que vous trouverez sur le web

Après des recherches, je pourrais trouver deux techniques principales utilisées pour implémenter l’effet d’ondulation sur les applications Web.

Utiliser le pseudo-élément :: after

En utilisant cette technique, le pseudo-élément :: after du bouton est présenté sous forme de cercle semi-transparent et animé pour se développer et se fondre. Le bouton conteneur doit avoir un débordement: caché pour que le cercle ne déborde jamais en dehors de la surface du bouton, et position: relative pour faciliter le positionnement du cercle dans le bouton. Vous pouvez lire plus de détails sur cette technique dans cet article de Ionuț Colceriu.

L’un des avantages de cette technique est qu’il s’agit d’une solution purement CSS pour l’effet d’ondulation. Cependant, l'effet d'entraînement commence toujours par le centre du bouton, au lieu du point de contact. Ce n’est pas la réaction la plus naturelle.

Il pourrait être amélioré en utilisant JavaScript pour stocker le point de contact et l’utiliser pour positionner l’ondulation. C’est exactement ce que material.io a fait pour son composant d’ondulation Web. Il utilise des variables CSS pour stocker le point de contact et le pseudo-élément :: after utilise ces variables pour le positionnement.

Utiliser des éléments enfants

En substance, cette technique utilise la même stratégie que précédemment. Mais au lieu d'un pseudo-élément, il ajoute un élément span à l'intérieur du bouton, qui peut ensuite être positionné via JavaScript. Cette technique est décrite dans cet article par Jhey Tompkins.

La mise en œuvre la plus simple crée une étendue pour chaque clic sur le bouton et utilise la position de la souris sur l'événement de clic pour modifier la position de l'étendue. Une animation CSS agrandit et diminue progressivement la durée jusqu'à ce qu'elle devienne totalement transparente. Nous pouvons choisir de supprimer la plage du DOM une fois l'animation terminée ou simplement de la laisser sous le tapis - personne ne remarquera vraiment la durée d'une transparence.

J'ai trouvé une autre variante de ceci, sur laquelle l'élément enfant est un svg au lieu d'un span, et le svg est animé via JavaScript. Dennis Gaebel explique cette variation, mais en substance, elle semble être la même et permet peut-être d’utiliser des formes et des effets SVG complexes.

Un problème avec les entrées de soumission

Les deux techniques décrites ci-dessus semblent bonnes. Mais c’est ce qui se passe lorsque j’ai essayé de les appliquer à des éléments d’entrée de type = submit:

Pourquoi ne travaillent-ils pas?

L'élément d'entrée est un élément remplacé. En bref, cela signifie que vous ne pouvez pratiquement rien faire avec ces éléments, en ce qui concerne DOM et CSS. En particulier, ils ne peuvent pas avoir d’éléments enfants ni de pseudo-éléments. On comprend maintenant pourquoi ces techniques échouent.

Par conséquent, si vous utilisez Material Design, il est préférable de rester à l’écart de la saisie [type = submit] et de vous en tenir aux éléments de bouton. Ou continuez simplement à lire.

Ajouter des ondulations pour soumettre des entrées

Sur l'application Web sur laquelle je travaillais, nous avions déjà beaucoup de boutons de soumission. Changer chacun d'eux pour en faire un élément différent demanderait beaucoup de travail et un risque élevé de rupture des feuilles de style et de la logique JavaScript. Il fallait donc que je trouve comment ajouter des ondulations aux boutons de soumission existants.

Utiliser un conteneur d'emballage

Je me suis vite rendu compte que je pouvais envelopper le bouton d'envoi à l'intérieur d'un élément inline-block et utiliser l'élément inline-block comme surface d'ondulation. Voici une démonstration rapide:

Bien que cette solution me plaise pour sa simplicité, elle nécessitait encore que je modifie le balisage trop souvent. Et je savais que ce serait une solution fragile: de nouveaux développeurs entreraient dans le projet et créeraient des boutons de soumission sans les emballer correctement dans une surface ondulée. J'ai donc continué à chercher d'autres solutions qui ne nécessitaient pas de changer de DOM.

Gradients radiaux

La syntaxe du dégradé radial me permet de contrôler à la fois le centre et la taille du dégradé. Bien entendu, cela me permet également de contrôler la couleur du dégradé, y compris les couleurs semi-transparentes. Et il ne déborde jamais l’élément auquel il est appliqué. Donc, il semble que cela fait déjà tout ce dont j'ai besoin!

Pas si vite… il manque une chose: la propriété background-image n'est pas animable. Je ne pouvais pas faire que le dégradé grandisse et devienne transparent en utilisant des animations CSS. J'ai réussi à le faire grandir en animant la propriété d’arrière-plan, mais c’était tout ce que je pouvais faire.

J'ai essayé quelques autres choses, comme avoir un cercle fondu en tant qu'image animée (en utilisant le format apng) et je l'ai appliqué en tant qu'image d'arrière-plan. Mais alors je ne pouvais pas contrôler quand la boucle de l'image a commencé et s'est terminée.

Enfin, une solution avec JavaScript

Ce que vous ne pouvez pas faire en CSS, vous pouvez le faire en JavaScript. Après avoir passé plus de temps que ce que je suis prêt à admettre pour essayer de faire fonctionner cet effet à l’aide d’animations CSS, j’ai abandonné et décidé d’écrire l’animation en JavaScript.

J'ai commencé avec la solution de dégradé radial ci-dessus et ai utilisé window.requestAnimationFrame pour créer une animation fluide du dégradé radial, en croissance et en atténuation progressive. Voici ma solution finale:

Conclusion

Il est donc possible d'avoir des effets d'entraînement sur les boutons de soumission, mais pas uniquement avec CSS.

Je ne pouvais pas trouver cette technique documentée nulle part sur le Web, alors je l’appelle moi-même. La technique d’ondulation de Leonardo ne nécessite aucune modification du DOM et s’applique à tous les éléments car elle ne repose pas sur des pseudo-éléments ou des éléments enfants. Cependant, ce n’est pas une solution parfaite.

Premièrement, il y a la performance. En animant le dégradé avec JavaScript, vous perdez beaucoup d'optimisations du navigateur. Mais comme la seule propriété modifiée est l’image d’arrière-plan, je suppose que les navigateurs n’auraient pas besoin de redistribuer et exigeraient simplement une nouvelle application des styles et une nouvelle peinture de l’élément. En pratique, c'est exactement ce qui se passe et la performance est vraiment bonne. L'exception à cette déclaration est Firefox Mobile, qui, pour une raison quelconque, ne suit pas l'animation. (edit: l'animation est fluide sur les versions modernes de Firefox Mobile)

Deuxièmement, la technique utilise la propriété background-image du bouton. Si votre conception nécessite que vos boutons aient une image appliquée à son arrière-plan, l'effet d'entraînement la remplacerait. Si vous avez vraiment besoin de cette image sur votre conception, vous pouvez modifier le code JavaScript pour tracer le dégradé radial au-dessus de l'image d'arrière-plan existante.

Troisièmement, cela ne semble pas fonctionner dans Internet Explorer. Cependant, je ne vois aucune raison pour laquelle cela ne fonctionnerait pas avec IE10 ou une version ultérieure. Peut-être est-ce dû au fait que IE utilise une syntaxe différente pour le gradient radial. Mais, qui se soucie de IE aujourd'hui? (edit: cette méthode fonctionne sans aucun problème sur Internet Explorer 11)