Construire une carte de témoignage avec HTML, CSS et JavaScript

cover
Nov 28, 2019☕ ☕ 8 min Follow me on Twitter

Subscribe to receive the free weekly article

Dans cet article, nous allons passer du bon temps avec les animations CSS et la manipulation DOM en construisant une carte de témoignage animée en utilisant HTML, CSS et JavaScript.

You can check it live here

HTML

Nous commençons par envelopper nos éléments dans la balise main.

<main>
  <!--This is the current testimonial-->
  <div class="testimonial-container testimonial-active">
    <div class="testimonial-header"></div>
    <div class="testimonial-body">
      <img alt="Avatar" src="" class="testimonial-avatar" />
      <h1></h1>
      <p></p>
    </div>
    <div class="testimonial-footer">
      <div>
        <span><i class="fab fa-google"></i></span>
        <span><i class="fab fa-linkedin"></i></span>
        <span><i class="fab fa-twitter"></i></span>
      </div>
      <div>
        <button id="next">
          <i class="fa fa-3x fa-chevron-circle-right"></i>
        </button>
      </div>
    </div>
  </div>
</main>

Nous allons avoir deux div principaux, le premier sera utilisé pour la carte de témoignage actuelle et le second dans le bloc de code ci-dessous nous aidera à montrer la prochaine carte de témoignage.

Notez que le contenu HTML sera ajouté via javaScript.

      <!--This is the next testimonial-->
      <div class="testimonial-ghost-container">
        <div class="testimonial-ghost-header"></div>
        <div class="testimonial-ghost-body">
          <img alt="Avatar" src="" />
          <h1></h1>
          <p></p>
        </div>
        <div class="testimonial-ghost-footer">
          <div>
            <span><i class="fab fa-google"></i></span>
            <span><i class="fab fa-linkedin"></i></span>
            <span><i class="fab fa-twitter"></i></span>
          </div>
          <div>
            <button id="ghost-next">
              <i class="fa fa-3x fa-chevron-circle-right"></i>
            </button>
          </div>
        </div>
      </div>
    </main>

Comme je l'ai dit plus tôt, ce div sera caché au début. Mais lorsque nous passerons au prochain témoignage, il sera utilisé pour montrer les deux cartes de témoignage en même temps.

CSS

Comme d'habitude, nous commençons la partie CSS avec quelques réinitialisations.

@import url("https://fonts.googleapis.com/css?family=Roboto:400,400i,700&display=swap");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background: #f5f6f7;
  line-height: 1.6;
  font-family: "Roboto", sans-serif;
}

main {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  width: 100%;
  max-width: 100%;
  position: relative;
}

Ensuite, on change la police, et on définit l'arrière-plan du corps sur une couleur gris clair. Ensuite, la balise main prend toute la largeur et la hauteur, et nous utilisons display: flex pour amener littéralement la carte de témoignage au centre de la fenêtre (écran).

.testimonial-container,
.testimonial-ghost-container {
  width: 22rem;
  height: 28rem;
  background: #fff;
  border-radius: 1.2rem;
  overflow: hidden;
  position: absolute;
}
.testimonial-active {
  z-index: 1;
  box-shadow: 0.5rem 0.5rem 1rem rgba(51, 51, 51, 0.2), 0.5rem 0.5rem 1rem rgba(51, 51, 51, 0.2);
}

.testimonial-header,
.testimonial-ghost-header {
  height: 10rem;
  background-image: linear-gradient(
      to right,
      rgba(239, 124, 0, 0.8),
      rgba(255, 181, 102, 0.8)
    ), url("https://shorturl.at/grwP6");
  background-size: cover;
  background-position: cover;
}

Nous continuons en stylisant nos deux éléments de carte. Dans les classes .testimonial-container et .testimonial-ghost-container, nous utilisons position: absolue; pour placer ces deux éléments l'un sur l'autre en suivant la position de la balise main. Ensuite, la classe .testimonial-active nous aidera à mettre la carte de témoignage active au premier plan.
Les deux classes suivantes sont utilisées pour styliser l'en-tête de la carte. Il aura une image doublée d'une couleur dégradée comme arrière-plan.

.testimonial-avatar,
.testimonial-ghost-body img {
  border-radius: 100%;
  display: block;
  margin: auto;
  margin-top: -4rem;
  border: 0.5rem solid #fff;
  z-index: 100;
}

.testimonial-body,
.testimonial-ghost-body {
  padding: 0 1rem;
  text-align: center;
  margin-bottom: 1rem;
}

Cette partie stylise l'avatar de notre carte. Nous utilisons une valeur négative -4rem dans la propriété margin-top pour amener l'avatar au milieu de l'en-tête de la carte et la propriété z-index garantit que l'élément sera toujours en haut de l'en-tête.

.testimonial-ghost-header {
  background-image: linear-gradient(
      to right,
      rgba(119, 119, 119, 0.8),
      rgba(119, 119, 119, 0.8)
    ), url("https://shorturl.at/grwP6");
}

.testimonial-ghost-body img {
  filter: blur(2px);
}

.testimonial-ghost-body h1,
.testimonial-ghost-body p i,
.testimonial-ghost-footer button i,
.testimonial-ghost-footer span i {
  color: #777;
}

.testimonial-footer,
.testimonial-ghost-footer {
  display: flex;
  justify-content: space-between;
  padding: 1rem;
}

Lorsqu'un changement se produit, le style de la carte de témoignage précédente change. l'avatar sera flou avec filter: blur (2px);. L'en-tête de la carte et la couleur des éléments deviendront sombres, juste pour avoir un joli style.

.testimonial-active-animated {
  animation: moveRight 1.5s ease-in-out;
}

.testimonial-inactive-animated {
  animation: moveLeft 1.5s ease-in-out;
}

@keyframes moveRight {
  0% {
    transform: translateX(0);
    box-shadow: none;
  }
  50% {
    transform: translateX(-10rem);
    box-shadow: none;
  }
  100% {
    transform: translateX(0);
  }
}

@keyframes moveLeft {
  0% {
    transform: translateX(0);
    opacity: 1;
    z-index: 2;
  }
  50% {
    transform: translateX(18rem) scale(0.96);
    opacity: 0.7;
  }
  100% {
    transform: translateX(0) scale(0.98);
    opacity: 0.2;
  }
}

Ce bloc de code sera indispensable pour passer au prochain témoignage. Nous avons deux animations: le premier moveRight déplacera l'élément de gauche à droite avec la propriététransform et le box-shadow sera caché pour avoir juste un effet plus naturel.

La deuxième animation moveLeft se déplacera de gauche à droite et se réduira un peu avec transform: translateX (18rem) scale (0.96). Il aura également un effet de fondu avec la propriété opacity. Et la propriété z-index placera l'élément en haut au début de l'animation.

Le .testimonial-active-animated et .testimonial-active-animated seront attachés aux cartes de témoignage appropriées.

JavaScript

Comme vous pouvez le voir ici, nous commençons par sélectionner les deux conteneurs de témoignages.

const testimonialContainer = document.querySelector(".testimonial-container")
const testimonialGhost = document.querySelector(".testimonial-ghost-container")
const nextBtn = document.querySelector("#next")
const testimonials = [
  {
    name: "Sarah Drucker",
    text:
      "Working with John Doe was a real pleasure, he helps me extending my business online.",
    avatar: "https://shorturl.at/eqyGW",
  },
  {
    name: "Nicolas Jaylen",
    text:
      "My business was broken, then i start working with John Doe, and now everything works fine.",
    avatar: "https://shorturl.at/ptC58",
  },
  {
    name: "Awa Fall",
    text:
      "John Doe helps me a lot from designing my website to make it live in just 5 weeks.",
    avatar: "https://shorturl.at/lwBY1",
  },
]
let counter = 0

Ensuite, nous avons un bouton pour écouter l'événement click et un tableau de témoignages qui seront affichés dynamiquement en suivant la variable counter.

const handleFirstTestimonial = () => {
  // Author avatar selection
  testimonialContainer.children[1].children[0].src = testimonials[0].avatar
  // Testimonial Author selection
  testimonialContainer.children[1].children[1].innerHTML = testimonials[0].name
  // Testimonial text selection
  testimonialContainer.children[1].children[2].innerHTML = `
  <i class="fas fa-quote-left"></i>
  ${testimonials[0].text}
  <i class="fas fa-quote-right"></i>
  `
}

La fonction handleFirstTestimonial () nous aide à montrer le premier témoignage du tableau. Ici, nous parcourons le DOM à travers l'élément testimonialContainer pour sélectionner les éléments enfants. Nous plaçons l'avatar, l'auteur du témoignage, et le texte avec le premier témoignage sur le tableau des testimonials.

const activeTestimonial = () => {
  testimonialContainer.classList.add("testimonial-active-animated")
  // Author avatar selection
  testimonialContainer.children[1].children[0].src =
    testimonials[counter].avatar
  // Testimonial Author selection
  testimonialContainer.children[1].children[1].innerHTML =
    testimonials[counter].name
  // Testimonial text selection
  testimonialContainer.children[1].children[2].innerHTML = `<i class="fas fa-quote-left"></i>
  ${testimonials[counter].text}
  <i class="fas fa-quote-right"></i>`

  setTimeout(() => {
    // Remove the active animated class
    testimonialContainer.classList.remove("testimonial-active-animated")
  }, 1400)
}

Ensuite, lorsque l'utilisateur passe au témoignage suivant, nous appelons la fonction activeTestimonial () pour le gérer. Et, utilisez le testimonialContainer pour parcourir le DOM et définir les données appropriées pour les éléments de la carte. Et faites en sorte que l'animation se produise avec testimonialContainer.classList.add (" testimonial-active-animated ");, et on supprime finalement l'animation après 1,4 seconde pour pouvoir l'animer à nouveau.

const inactiveTestimonial = () => {
  testimonialGhost.classList.add("testimonial-inactive-animated")
  let newCounter = counter
  if (newCounter === 0) {
    newCounter = testimonials.length
  }
  // image selection
  testimonialGhost.children[1].children[0].src =
    testimonials[newCounter - 1].avatar
  // title selection
  testimonialGhost.children[1].children[1].innerHTML =
    testimonials[newCounter - 1].name
  // text selection
  testimonialGhost.children[1].children[2].innerHTML = `<i class="fas fa-quote-left"></i>
  ${testimonials[newCounter - 1].text}
  <i class="fas fa-quote-right"></i>`
  setTimeout(() => {
    // Remove the active animated class
    testimonialGhost.classList.remove("testimonial-inactive-animated")
  }, 1400)
}

Comme la fonction activeTestimonial (), la fonction inactiveTestimonial gérera la carte de témoignage inactive. Nous parcourons le DOM avec testimonialGhost pour sélectionner les éléments et définir les données sur la carte de témoignage précédente.

Ici, nous utilisons un newCounter pour gérer simplement le tableau testimonials si le counter est égal à 0, nous réaffectons le newCounter avec la dernière carte de témoignage du tableau.

nextBtn.addEventListener("click", () => {
  if (counter === testimonials.length - 1) {
    counter = 0
    inactiveTestimonial()
    activeTestimonial()
  } else {
    counter++
    inactiveTestimonial()
    activeTestimonial()
  }
})

handleFirstTestimonial()

Pour que toute la magie se produise, nous devons écouter l'événement Click. Et vérifiez si le compteur est égal au dernier élément du tableau. Si c'est le cas, on réinitialise le compteur à 0 et on appele les fonctions nécessaires. Sinon, on incrémente la variable counter et on appele inactiveTestimonial() et activeTestimonial().

Ensuite, pour tout démarrer lorsque la page se charge, nous appelons la fonction handleFirstTestimonial ().

Vous pouvez le voir en direct ici
fullscreen-slider

#html#css#javascript

Support my work

Get articles in your inbox