Subscribe to get the weekly post

Or

Follow me

Construire une barre de navigation collante avec React

Publié 2 months ago 7 min de lecture

Je suis à peu près sûr, que vous avez déjà vu l'effet que nous allons faire aujourd'hui. C'est une animation courante que nous voyons sur de nombreux sites Web. Lorsqu'un utilisateur fait défiler, la barre de navigation se déplace vers le bas avec un effet d'animation cool.

Vous avez de la chance car, dans ce article, nous ferons le même effet avec React en créant une barre de navigation collante à partir de zéro sans bibliothèques tierces.

Vous pouvez le voir ici

Mise en place du projet

Pour pouvoir suivre, vous devez créer un nouvelle application React avec:

npx create-react-app react-sticky-navbar

Ou, si vous le souhaitez, vous pouvez en configurer un nouvelle à partir de zéro avec Webpack. C'est vraiment comme vous le voulez.

Ensuite, nous devrons créer quelques fichiers.

Notez que je vais me concentrer principalement sur les fichiers navbar, pour rendre ce post court et utile, vous pouvez toujours trouver le code source à la fin de l'article.

  • Créez un dossier components et comme sous-dossier Header.

Ensuite, ajoutez Welcome.js, Welcome.css, Navbar.js et Navbar.css.

  • Dans Welcome.js
import React from "react"
import "./Welcome.css"
import Logo from "../../assets/images/logo.svg"
import About from "./About"

const Welcome = ({ stickyRef }) => (
  <main>
    <section className="welcome">
      <div ref={stickyRef}>
        <img src={Logo} alt="logo" className="welcome--logo" />
        <p>Even if you scroll, i will stick with you</p>
        <button className="welcome__cta-primary">Contact us</button>
      </div>
    </section>
    <About />
  </main>
)

export default Welcome

Comme vous pouvez le voir, nous avons ici un composant simple qui reçoit le props stickyRef. C'est juste la référence de l'élément qui déclenchera l'effet collant plus tard sur le défilement. En passant, j'utilise ici la déstructuration pour extraire l'élément. Si vous le souhaitez, vous pouvez utiliser props.stickyRef. C'est à vous de voir.

Passons maintenant au fichier suivant.

  • Dans Navbar.js
import React from "react"
import "./Navbar.css"
import Logo from "../../assets/images/logo.svg"

const Navbar = () => (
  <nav className="navbar">
    <div className="navbar--logo-holder">
      <img src={Logo} alt="logo" className="navbar--logo" />
      <h1> Stick'Me</h1>
    </div>
    <ul className="navbar--link">
      <li className="navbar--link-item">Home</li>
      <li className="navbar--link-item">About</li>
      <li className="navbar--link-item">Blog</li>
    </ul>
  </nav>
)
export default Navbar

Dans ce fichier, pour le moment, il est très simple. Plus tard, nous allons le mettre à jour, pour pouvoir afficher certains éléments conditionnellement et rendre la barre de navigation collante.

gif-1

L' effet collant

  • Dans App.js
import React, { Fragment, useEffect, useRef, useState } from "react"
import Welcome from "./components/Header/Welcome"
import Navbar from "./components/Header/Navbar"

function App() {
  useEffect(() => {
    return () => {
      window.removeEventListener("scroll", () => handleScroll)
    }
  }, [])

  const [isSticky, setSticky] = useState(false)

  const stickyRef = useRef(null)
  const handleScroll = () => {
    window.pageYOffset > stickyRef.current.getBoundingClientRect().bottom
      ? setSticky(true)
      : setSticky(false)
  }

  window.addEventListener("scroll", handleScroll)

  return (
    <Fragment>
      <Navbar sticky={isSticky} />
      <Welcome stickyRef={stickyRef} />
    </Fragment>
  )
}

export default App

Toute la magie se produira ici (je vous le promets). Nous devons d'abord importer quelques hooks et Fragment qui va envelopper nos éléments.

Ensuite, nous définissons notre état avec useState() et initialisons sa valeur à false. Cela signifie que nous allons maintenant pouvoir changer isSticky entre true et false en fonction du défilement.

gif-2

Lorsque l'utilisateur commence à faire défiler, la fonction handleScroll() sera déclenchée. Ensuite, il vérifiera si window.pageYOffset > stickyRef.current.getBoundingClientRect().bottom et mettra à jour isSticky. En d'autres termes, il vérifiera si le nombre de pixels de défilement de la page en rapport avec le long de l'axe vertical est supérieur ou non à la position de l'élément courant par rapport à son bas.

Ensuite, nous passons au composant Navbar l'état isSticky et à Welcome la référence de l'élément géré par useRef. Maintenant, nous devons mettre à jour Navbar.js pour le rendre collant sur le défilement.

  • Dans Navbar.js
import React from "react"
import "./Navbar.css"
import Logo from "../../assets/images/logo.svg"

const Navbar = ({ sticky }) => (
  <nav className={sticky ? "navbar navbar-sticky" : "navbar"}>
    <div className="navbar--logo-holder">
      {sticky ? <img src={Logo} alt="logo" className="navbar--logo" /> : null}
      <h1> Stick'Me</h1>
    </div>
    <ul className="navbar--link">
      <li className="navbar--link-item">Home</li>
      <li className="navbar--link-item">About</li>
      <li className="navbar--link-item">Blog</li>
    </ul>
  </nav>
)
export default Navbar

Nous avons maintenant accès à sticky, et nous pouvons vérifier s'il est true or false et afficher les classes ou les éléments conditionnellement avec l'aide de l'opérateur ternaire.

Nous avons beaucoup avancé, mais nous n'avons pas encore finit. Il reste une partie importante: le style et les animations.

Faisons le!

gif-3

Style de la barre de navigation

  • Dans Navbar.css
.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 2.5rem;
  position: absolute;
  z-index: 1;
  width: 100%;
}

.navbar-sticky {
  background: #333;
  position: fixed;
  top: 0;
  left: 0;
  box-shadow: 1px 1px 1px #222;
  animation: moveDown 0.5s ease-in-out;
}

.navbar--logo {
  width: 2rem;
  height: 2rem;
  margin-right: 0.5rem;
  animation: rotate 0.7s ease-in-out 0.5s;
}

@keyframes moveDown {
  from {
    transform: translateY(-5rem);
  }
  to {
    transform: translateY(0rem);
  }
}

@keyframes rotate {
  0% {
    transform: rotateY(360deg);
  }
  100% {
    transform: rotateY(0rem);
  }
}

Ici, en plus de fixer la barre de navigation sur le défilement avec la classe .navbar-sticky, nous faisons aussi un bel effet moveDown avec @keyframes. Ensuite, nous allons également faire pivoter un peu le logo pour que tout soit beau et accordé sur le défilement.

Nous obtenons enfin notre barre de navigation collante. Cependant, ajouter des écouteurs de défilement comme celui-ci peut entraîner des problèmes de performances sur votre application. Vous pouvez le vérifier en affichant l'événement de défilement sur votre console.

Cependant, nous pouvons encore faire quelque chose pour résoudre le problème. Nous pouvons utiliser une fonction anti-rebond.

Nous devons à présent mettre à jour App.js pour gérer ce problème.

L' Anti-rebond

  • Dans App.js
import React, { Fragment, useEffect, useRef, useState } from "react"
import Welcome from "./components/Header/Welcome"
import Navbar from "./components/Header/Navbar"

function App() {
  useEffect(() => {
    return () => {
      window.removeEventListener("scroll", () => handleScroll)
    }
  }, [])

  const [isSticky, setSticky] = useState(false)

  const stickyRef = useRef(null)
  const handleScroll = () => {
    window.pageYOffset > stickyRef.current.getBoundingClientRect().bottom
      ? setSticky(true)
      : setSticky(false)
  }

  const debounce = (func, wait = 20, immediate = true) => {
    let timeOut
    return () => {
      let context = this,
        args = arguments
      const later = () => {
        timeOut = null
        if (!immediate) func.apply(context, args)
      }
      const callNow = immediate && !timeOut
      clearTimeout(timeOut)
      timeOut = setTimeout(later, wait)
      if (callNow) func.apply(context, args)
    }
  }

  window.addEventListener("scroll", debounce(handleScroll))

  return (
    <Fragment>
      <Navbar sticky={isSticky} />
      <Welcome stickyRef={stickyRef} />
    </Fragment>
  )
}

export default App

Vous pouvez trouver une méthode anti-rebond partout, ou vous pouvez même utiliser lodash. Mais, la chose la plus importante à retenir est ce que fait cette fonction. Au lieu d'exécuter handleScroll tout le temps, il l'exécutera toutes les 20 millisecondes pour vous donner plus de contrôle.

Sur ce, nous avons terminé la construction de notre barre de navigation collante.

Code source

applause

C'est tout!

Merci de l'avoir lu.

#react

Posted by Ibrahima Ndaw

Full-stack developer and blogger
Follow me

Get the next in your inbox