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
Sorry for the interrupt!
If you're interested in learning JavaScript in a comprehensive way, I highly recommend this course: JavaScript - The Complete Guide 2020 (Beginner + Advanced)
It's an affiliate link, so by purchasing, you support the blog at the same time.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