Aller au contenu
Patrick Junod Patrick Junod

Comment styliser n'importe quel élément au scroll grâce à Tailwind CSS et Alpine.js

Découvrez comment créer un variant Tailwind CSS personnalisé qui s'active au scroll de la page grâce à Alpine.js. Idéal pour animer vos headers, navbar et éléments au défilement.

AlpineJS CSS Tailwindcss

Lorsqu'on développe un site, il est très courant de vouloir modifier l'apparence de certains éléments en fonction du scroll. Un header qui se réduit, une navbar qui change de couleur, un bouton qui apparaît... Les cas d'usage sont nombreux.

Avec Tailwind CSS v4 et Alpine.js, on peut mettre en place un système élégant et réutilisable en quelques minutes : un custom variant scrolled: qui s'utilise directement dans vos classes Tailwind, exactement comme hover: ou focus:.

1. Déclarer le custom variant dans votre CSS

Tailwind CSS v4 introduit la directive @custom-variant qui permet de créer vos propres variants. Ajoutez la ligne suivante dans votre fichier CSS principal (généralement resources/css/app.css) :

@custom-variant scrolled (&:where(.scrolled, .scrolled *));

Cette ligne indique à Tailwind que le variant scrolled: doit s'appliquer lorsqu'un élément possède la classe .scrolled, ou lorsqu'il est un enfant d'un élément ayant cette classe.

Concrètement, cela signifie que lorsque la classe scrolled est présente sur le <body>, tous les éléments enfants pourront réagir via le préfixe scrolled: dans leurs classes Tailwind.

2. Ajouter la logique de scroll avec Alpine.js

Il nous faut maintenant un mécanisme pour ajouter dynamiquement la classe scrolled sur le <body> lorsque l'utilisateur scrolle. C'est ici qu'Alpine.js entre en jeu.

Modifiez votre balise <body> comme suit :

<body :class="{ 'scrolled': hasScrolled }"
      x-data="{
          hasScrolled: false,
          reactOnScroll() {
              this.hasScrolled = window.scrollY > 10;
          }
      }"
      x-init="reactOnScroll()"
      @scroll.window="reactOnScroll()"
>

Voici ce qui se passe :

  • x-data déclare une variable réactive hasScrolled, initialisée à false, ainsi qu'une méthode reactOnScroll() qui met à jour cette variable.

  • x-init appelle reactOnScroll() dès le chargement de la page, afin de gérer le cas où l'utilisateur arrive sur une page déjà scrollée (après un refresh par exemple).

  • @scroll.window écoute l'événement de scroll sur la fenêtre et appelle notre méthode à chaque défilement.

  • :class ajoute conditionnellement la classe scrolled sur le <body> lorsque hasScrolled est true.

3. Utiliser le variant dans vos composants

C'est là que la magie opère. Vous pouvez maintenant utiliser le préfixe scrolled: sur n'importe quel élément enfant du <body> :

<!-- Header qui change de background au scroll -->
<header class="bg-transparent scrolled:bg-white scrolled:shadow-lg transition-all duration-300">
    <nav class="py-6 scrolled:py-3 transition-all duration-300">
        <!-- ... -->
    </nav>
</header>

<!-- Logo qui se réduit au scroll -->
<img src="/logo.svg"
     class="h-12 scrolled:h-8 transition-all duration-300"
     alt="Logo">

<!-- Bouton "retour en haut" qui apparaît au scroll -->
<button class="opacity-0 scrolled:opacity-100 transition-opacity duration-300">
    ↑ Haut de page
</button>

Comme vous pouvez le constater, le variant scrolled: s'utilise exactement comme les variants natifs de Tailwind. Combiné avec les classes transition, vous obtenez des animations fluides sans effort.

4. Pourquoi cette approche ?

Vous pourriez vous demander pourquoi ne pas simplement utiliser du JavaScript classique pour toggler des classes. Voici quelques avantages de cette solution :

  • Lisibilité : Tout est déclaratif et visible directement dans le HTML. Pas besoin d'aller chercher dans un fichier JS quel élément est modifié au scroll.

  • Réutilisabilité : Le variant scrolled: est disponible partout dans votre projet. Ajoutez-le à n'importe quel élément sans écrire une ligne de logique supplémentaire.

  • Cohérence : Vous restez dans l'écosystème Tailwind. Vos classes responsive, hover, focus et maintenant scroll cohabitent au même endroit.

  • Performance : Alpine.js est extrêmement léger et la détection du scroll via window.scrollY est très performante.

Conclusion

En combinant la puissance des custom variants de Tailwind CSS v4 avec la réactivité d'Alpine.js, vous obtenez un système de détection de scroll propre, maintenable et réutilisable à travers tout votre projet. Plus besoin de scripts custom ou de librairies supplémentaires pour animer votre interface au scroll.

N'hésitez pas à adapter le seuil de détection (ici 10 pixels) selon vos besoins, et à combiner ce variant avec d'autres pour des comportements encore plus poussés.