Un retournement de cartes avec vent arrière

Apprenez à créer une animation de flip de carte 3D à l’aide de Tailwind CSS.
CSS a parcouru un long chemin au cours des 10 dernières années. Il est maintenant plus facile que jamais de créer des animations 3D. Le vent de queue facilite encore cela en incluant votre CSS directement dans vos attributs de classe.
Tl;
Cela nécessite un JavaScript minimal pour créer des animations. Tailwind 4 ajoutera des fonctions d’espace 3D, mais vous pouvez y parvenir aujourd’hui avec des valeurs arbitraires dans Tailwind 3 ou en utilisant des plugins de vent arrière externes. La création d’une carte rotative n’a jamais été plus simple.
Configuration du vent arrière et du framework
Cette démo peut fonctionner dans n’importe quel cadre, bien que j’utilise Sveltekit pour la simplicité. Après avoir installé Tailwind, nous utiliserons des classes d’assistance.
npm i -D tailwind-merge clsx
- Fusion de vent arrière Vous permet de compiler les classes que vous utilisez et d’éliminer celles que vous n’avez pas lorsque vous passez des classes entre les composants.
- clsx est un petit utilitaire vous permettant de construire des conditions de classe HTML.
Ensemble, ces deux éléments ont été normalisés pour créer le cn
fonction dans de grands cadres d’interface utilisateur comme shadcn.
// lib/utils.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Composants
Nous avons besoin d’un dos et d’un composant avant à afficher.
Devant
<div
class="flex h-full w-full flex-col items-center justify-center rounded-xl border bg-blue-700 text-white"
>
Front
</div>
Dos
<div
class="flex h-full w-full flex-col items-center justify-center rounded-xl bg-emerald-700 text-white"
>
Back
</div>
Vous pouvez utiliser les classes que vous souhaitez formater la carte, mais vous aurez besoin du size-full
ou les deux w-full
et h-full
Pour s’assurer que la carte est complètement couverte.
Conteneur de bouton de base
Parce que nous retournerons la carte en cliquant, la meilleure pratique pour l’accessibilité est d’utiliser un button
élément pour éviter la confusion avec les lecteurs d’écran.
<button type="button" onclick={() => {}} class="size-96 outline-none">
<div class="relative size-full">
<div class="absolute inset-0 size-full">
<Front />
</div>
<div class="absolute inset-0 size-full">
<Back />
</div>
</div>
</button>
- Nous voulons
type="button"
Pour assurer une action de clic et non une rafraîchissement de page. - Nous ajouterons un
onclick
action plus tard. - Chrome ajoute une bordure supplémentaire pour les boutons standard sur des événements sélectionnés, nous supprimons donc cela avec
outline-none
. - Nous avons un récipient extérieur avec un
relative
Position d’affichage, avec deuxabsolute
etinset-0
Conteneurs enfants, pour le dimensionnement exact lorsque nous utilisons nos transitions 3D. - Nous voulons
size-full
sur les troisdiv
Éléments pour correspondre à nos tailles de cartes maximales.
Ajouter l’effet 3D
<button type="button" onclick={() => {}} class="size-96 outline-none [perspective:100rem]">
<div class={cn('relative size-full transition duration-500 [transform-style:preserve-3d]')}>
<div class="absolute inset-0 size-full [backface-visibility:hidden]">
<Front />
</div>
<div
class="absolute inset-0 size-full [backface-visibility:hidden] [transform:rotateY(180deg)]"
>
<Back />
</div>
</div>
</button>
- Nous ajoutons
[perspective:50rem]
pour définir la perspective de l’espace 3D Root. L’équivalent du vent arrière estperspective-midrange
. - Nous ajoutons
[transform-style:preserve-3d]
Pour confirmer que les éléments enfants seront toujours dans l’espace 3D. L’équivalent du vent arrière esttransform-3d
. - Nous ajoutons
[backface-visibility:hidden]
aux deux côtés de la carte pour cacher l’autre côté de l’élément lorsque chaque côté est visible. L’équivalent du vent arrière estbackface-hidden
. - Nous ajoutons
[transform:rotateY(180deg)]
à l’arrière de la carte pour régler l’arrière comme arrière. L’équivalent du vent arrière estrotate-y-180
.
Si vous utilisez une ancienne version du vent arrière, vous préférez peut-être le Tailwind-3Dtransform-Pluginentre autres. Cependant, je préfère mettre le CSS directement dans la classe avec []
Jusqu’à ce que le vent arrière 4 soit stable et largement utilisé.
Le flip
Pour retourner la carte, nous avons besoin d’un état avant et arrière. La meilleure façon de représenter cela est avec un booléen qui peut être réactif.
const card = $state({
showBack: false,
flip() {
this.showBack = !this.showBack;
}
});
J’utilise un $state()
variable dans svelte, mais cela pourrait facilement être traduit par useState
ou d’autres types de signal()
fonctions, selon votre cadre.
- Nous retournons la carte avec
card.flip()
. - Nous devons ajouter dynamiquement
[transform:rotateY(180deg)]
à notre élément racine lorsque nous voulons retourner. Rappelez-vous que c’estrotate-y-180
dans le vent arrière 4. - Nous pouvons ajouter
transition duration-1000
pour avoir un deuxième effet d’animation.
<button type="button" onclick={() => card.flip()} class="size-96 outline-none [perspective:50rem]">
<div
class={cn(
'relative size-full transition duration-1000 [transform-style:preserve-3d]',
card.showBack && '[transform:rotateY(180deg)]'
)}
>
<div class="absolute inset-0 size-full [backface-visibility:hidden]">
<Front />
</div>
<div
class="absolute inset-0 size-full [backface-visibility:hidden] [transform:rotateY(180deg)]"
>
<Back />
</div>
</div>
</button>
Remarquez que nous ajoutons programmatiquement la rotation grâce à notre nifty cn()
fonction utilitaire.
card.showBack && '[transform:rotateY(180deg)]'
Bonus: retourner avec la barre d’espace
Si nous essayons de montrer le dos de la carte pour étudier une carte flash, et que nous voulons retourner la carte avec une touche, nous devons appeler le flip()
fonction de cette touche.
useKey
Nous pouvons écouter manuellement une touche avec l’écouteur de l’événement JS, mais nous pouvons également faciliter cela.
import { onMount } from 'svelte';
export function useKey(
key: string | string[],
callback: (event: KeyboardEvent) => void,
options: {
event?: 'keydown' | 'keyup' | 'keypress',
preventDefault?: boolean,
} = {}
) {
const {
event="keydown",
preventDefault = false,
} = options;
function handler(e: KeyboardEvent) {
const keys = Array.isArray(key) ? key : [key];
if (keys.includes(e.key)) {
if (preventDefault) {
e.preventDefault();
}
callback(e);
}
}
onMount(() => {
addEventListener(event, handler);
return () => {
removeEventListener(event, handler);
};
});
}
J’ai modifié useKey
Pour travailler avec Svelte, mais il existe des packages et des modèles pré-écrits pour la plupart des frameworks:
Retourner avec de l’espace
useKey(' ', () => card.flip());
C’est ça!
Beau, non?
Source link