Hello folks, today we will discuss Building Testimonial Slider in LWC. Testimonials are a powerful way to showcase the positive experiences of your customers or users. Implementing a testimonial slider in Lightning Web Components (LWC) can elevate the user experience and add credibility to your website or application.
Also, check this: Efficient Server-Side Pagination in LWC: No Offset Approach
Key Highlights :
- Pure HTML CSS and Javascript slider. not use any third-party library.
- The collection of images can be automatically changed using a timer or manually when the user clicks the displayed buttons.
- Create Nav buttons to slide the testimonial.
Code :
LwcTestimonialSlider.HTML:
<template>
<div class="body">
<div class="wrapper">
<i id="left" class="fa-solid" data-id="arrow">
<lightning-icon icon-name="utility:back"></lightning-icon>
</i>
<ul class="carousel" lwc:dom="manual"></ul>
<i id="right" class="fa-solid"><lightning-icon icon-name="utility:forward"></lightning-icon></i>
</div>
</div>
</template>
<template>
<div class="body">
<div class="wrapper">
<i id="left" class="fa-solid" data-id="arrow">
<lightning-icon icon-name="utility:back"></lightning-icon>
</i>
<ul class="carousel" lwc:dom="manual"></ul>
<i id="right" class="fa-solid"><lightning-icon icon-name="utility:forward"></lightning-icon></i>
</div>
</div>
</template>
<template> <div class="body"> <div class="wrapper"> <i id="left" class="fa-solid" data-id="arrow"> <lightning-icon icon-name="utility:back"></lightning-icon> </i> <ul class="carousel" lwc:dom="manual"></ul> <i id="right" class="fa-solid"><lightning-icon icon-name="utility:forward"></lightning-icon></i> </div> </div> </template>
LwcTestimonialSlider.JS:
import { LightningElement } from 'lwc';
export default class LwcTestimonialSlider extends LightningElement {
data = [
{ Name: 'Blanche Pearson', img: 'https://t4.ftcdn.net/jpg/03/50/40/93/240_F_350409330_2bqhjowfBmrqEia5U8lBsGrvD7h8EIo6.jpg', 'profession': 'Web Developer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'Joenas Brauers', img: 'https://t3.ftcdn.net/jpg/06/15/91/36/240_F_615913669_1GvdMMT0H44Z4owh9SCYsml6mCcy8g3G.jpg', 'profession': 'Sales Manager', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'Lariach French', img: 'https://t4.ftcdn.net/jpg/06/81/01/43/240_F_681014359_dyMjwn4JYLtY985umiBOeytmLmVxEjC0.jpg', 'profession': 'App Designer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'James Khosravi', img: 'https://t4.ftcdn.net/jpg/03/50/40/93/240_F_350409330_2bqhjowfBmrqEia5U8lBsGrvD7h8EIo6.jpg', 'profession': 'Freelancer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'Rijwan', img: 'https://t3.ftcdn.net/jpg/03/99/91/62/240_F_399916297_1JwXdmC6ViCG4YhZuhLVz7xfuZhfHCY9.jpg', 'profession': 'Salesforce Expert', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'Sachin', img: 'https://t3.ftcdn.net/jpg/02/60/67/80/240_F_260678009_gV1PBTotxDIwTngnmn3nYqWshbznYf24.jpg', 'profession': 'Salesforce Consultant', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
]
renderedCallback() {
this.data.forEach(ele => {
this.template.querySelector('.carousel').innerHTML += '<li class="card"> <div class="img"> <img src="' + ele.img + '" alt="img" draggable="false"></div> <h2>' + ele.Name + '</h2> <span>' + ele.profession + '</span> <p class="testim"> ' + ele.review + ' </p></li>';
})
const wrapper = this.template.querySelector(".wrapper");
const carousel = this.template.querySelector(".carousel");
const firstCardWidth = carousel.querySelector(".card").offsetWidth;
const arrowBtns = this.template.querySelectorAll(".wrapper i");
const carouselChildrens = [...carousel.children];
let isDragging = false;
let isAutoPlay = true;
let startX;
let startScrollLeft;
let timeoutId;
// Get the number of cards that can fit in the carousel at once
let cardPerView = Math.round(carousel.offsetWidth / firstCardWidth);
// Insert copies of the last few cards to beginning of carousel for infinite scrolling
carouselChildrens
.slice(-cardPerView)
.reverse()
.forEach((card) => {
carousel.insertAdjacentHTML("afterbegin", card.outerHTML);
});
carouselChildrens.slice(0, cardPerView).forEach((card) => {
carousel.insertAdjacentHTML("beforeend", card.outerHTML);
});
// Scroll the carousel at appropriate postition to hide first few duplicate cards on Firefox
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");
// Add event listeners for the arrow buttons to scroll the carousel left and right
arrowBtns.forEach((btn) => {
console.log(btn);
console.log(btn.id);
btn.addEventListener("click", () => {
carousel.scrollLeft += btn.id.includes("left") ? -firstCardWidth : firstCardWidth;
});
});
const dragStart = (e) => {
isDragging = true;
carousel.classList.add("dragging");
// Records the initial cursor and scroll position of the carousel
startX = e.pageX;
startScrollLeft = carousel.scrollLeft;
};
const dragging = (e) => {
if (!isDragging) return; // if isDragging is false return from here
// Updates the scroll position of the carousel based on the cursor movement
carousel.scrollLeft = startScrollLeft - (e.pageX - startX);
};
const dragStop = () => {
isDragging = false;
carousel.classList.remove("dragging");
};
const infiniteScroll = () => {
// If the carousel is at the beginning, scroll to the end
if (carousel.scrollLeft === 0) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.scrollWidth - 2 * carousel.offsetWidth;
carousel.classList.remove("no-transition");
}
// If the carousel is at the end, scroll to the beginning
else if (
Math.ceil(carousel.scrollLeft) ===
carousel.scrollWidth - carousel.offsetWidth
) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");
}
// Clear existing timeout & start autoplay if mouse is not hovering over carousel
clearTimeout(timeoutId);
if (!wrapper.matches(":hover")) autoPlay();
};
const autoPlay = () => {
if (window.innerWidth < 800 || !isAutoPlay) return; // Return if window is smaller than 800 or isAutoPlay is false
// Autoplay the carousel after every 2500 ms
timeoutId = setTimeout(() => (carousel.scrollLeft += firstCardWidth), 2500);
};
autoPlay();
carousel.addEventListener("mousedown", dragStart);
carousel.addEventListener("mousemove", dragging);
document.addEventListener("mouseup", dragStop);
carousel.addEventListener("scroll", infiniteScroll);
wrapper.addEventListener("mouseenter", () => clearTimeout(timeoutId));
wrapper.addEventListener("mouseleave", autoPlay);
}
}
import { LightningElement } from 'lwc';
export default class LwcTestimonialSlider extends LightningElement {
data = [
{ Name: 'Blanche Pearson', img: 'https://t4.ftcdn.net/jpg/03/50/40/93/240_F_350409330_2bqhjowfBmrqEia5U8lBsGrvD7h8EIo6.jpg', 'profession': 'Web Developer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'Joenas Brauers', img: 'https://t3.ftcdn.net/jpg/06/15/91/36/240_F_615913669_1GvdMMT0H44Z4owh9SCYsml6mCcy8g3G.jpg', 'profession': 'Sales Manager', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'Lariach French', img: 'https://t4.ftcdn.net/jpg/06/81/01/43/240_F_681014359_dyMjwn4JYLtY985umiBOeytmLmVxEjC0.jpg', 'profession': 'App Designer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'James Khosravi', img: 'https://t4.ftcdn.net/jpg/03/50/40/93/240_F_350409330_2bqhjowfBmrqEia5U8lBsGrvD7h8EIo6.jpg', 'profession': 'Freelancer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'Rijwan', img: 'https://t3.ftcdn.net/jpg/03/99/91/62/240_F_399916297_1JwXdmC6ViCG4YhZuhLVz7xfuZhfHCY9.jpg', 'profession': 'Salesforce Expert', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
{ Name: 'Sachin', img: 'https://t3.ftcdn.net/jpg/02/60/67/80/240_F_260678009_gV1PBTotxDIwTngnmn3nYqWshbznYf24.jpg', 'profession': 'Salesforce Consultant', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' },
]
renderedCallback() {
this.data.forEach(ele => {
this.template.querySelector('.carousel').innerHTML += '<li class="card"> <div class="img"> <img src="' + ele.img + '" alt="img" draggable="false"></div> <h2>' + ele.Name + '</h2> <span>' + ele.profession + '</span> <p class="testim"> ' + ele.review + ' </p></li>';
})
const wrapper = this.template.querySelector(".wrapper");
const carousel = this.template.querySelector(".carousel");
const firstCardWidth = carousel.querySelector(".card").offsetWidth;
const arrowBtns = this.template.querySelectorAll(".wrapper i");
const carouselChildrens = [...carousel.children];
let isDragging = false;
let isAutoPlay = true;
let startX;
let startScrollLeft;
let timeoutId;
// Get the number of cards that can fit in the carousel at once
let cardPerView = Math.round(carousel.offsetWidth / firstCardWidth);
// Insert copies of the last few cards to beginning of carousel for infinite scrolling
carouselChildrens
.slice(-cardPerView)
.reverse()
.forEach((card) => {
carousel.insertAdjacentHTML("afterbegin", card.outerHTML);
});
carouselChildrens.slice(0, cardPerView).forEach((card) => {
carousel.insertAdjacentHTML("beforeend", card.outerHTML);
});
// Scroll the carousel at appropriate postition to hide first few duplicate cards on Firefox
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");
// Add event listeners for the arrow buttons to scroll the carousel left and right
arrowBtns.forEach((btn) => {
console.log(btn);
console.log(btn.id);
btn.addEventListener("click", () => {
carousel.scrollLeft += btn.id.includes("left") ? -firstCardWidth : firstCardWidth;
});
});
const dragStart = (e) => {
isDragging = true;
carousel.classList.add("dragging");
// Records the initial cursor and scroll position of the carousel
startX = e.pageX;
startScrollLeft = carousel.scrollLeft;
};
const dragging = (e) => {
if (!isDragging) return; // if isDragging is false return from here
// Updates the scroll position of the carousel based on the cursor movement
carousel.scrollLeft = startScrollLeft - (e.pageX - startX);
};
const dragStop = () => {
isDragging = false;
carousel.classList.remove("dragging");
};
const infiniteScroll = () => {
// If the carousel is at the beginning, scroll to the end
if (carousel.scrollLeft === 0) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.scrollWidth - 2 * carousel.offsetWidth;
carousel.classList.remove("no-transition");
}
// If the carousel is at the end, scroll to the beginning
else if (
Math.ceil(carousel.scrollLeft) ===
carousel.scrollWidth - carousel.offsetWidth
) {
carousel.classList.add("no-transition");
carousel.scrollLeft = carousel.offsetWidth;
carousel.classList.remove("no-transition");
}
// Clear existing timeout & start autoplay if mouse is not hovering over carousel
clearTimeout(timeoutId);
if (!wrapper.matches(":hover")) autoPlay();
};
const autoPlay = () => {
if (window.innerWidth < 800 || !isAutoPlay) return; // Return if window is smaller than 800 or isAutoPlay is false
// Autoplay the carousel after every 2500 ms
timeoutId = setTimeout(() => (carousel.scrollLeft += firstCardWidth), 2500);
};
autoPlay();
carousel.addEventListener("mousedown", dragStart);
carousel.addEventListener("mousemove", dragging);
document.addEventListener("mouseup", dragStop);
carousel.addEventListener("scroll", infiniteScroll);
wrapper.addEventListener("mouseenter", () => clearTimeout(timeoutId));
wrapper.addEventListener("mouseleave", autoPlay);
}
}
import { LightningElement } from 'lwc'; export default class LwcTestimonialSlider extends LightningElement { data = [ { Name: 'Blanche Pearson', img: 'https://t4.ftcdn.net/jpg/03/50/40/93/240_F_350409330_2bqhjowfBmrqEia5U8lBsGrvD7h8EIo6.jpg', 'profession': 'Web Developer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' }, { Name: 'Joenas Brauers', img: 'https://t3.ftcdn.net/jpg/06/15/91/36/240_F_615913669_1GvdMMT0H44Z4owh9SCYsml6mCcy8g3G.jpg', 'profession': 'Sales Manager', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' }, { Name: 'Lariach French', img: 'https://t4.ftcdn.net/jpg/06/81/01/43/240_F_681014359_dyMjwn4JYLtY985umiBOeytmLmVxEjC0.jpg', 'profession': 'App Designer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' }, { Name: 'James Khosravi', img: 'https://t4.ftcdn.net/jpg/03/50/40/93/240_F_350409330_2bqhjowfBmrqEia5U8lBsGrvD7h8EIo6.jpg', 'profession': 'Freelancer', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' }, { Name: 'Rijwan', img: 'https://t3.ftcdn.net/jpg/03/99/91/62/240_F_399916297_1JwXdmC6ViCG4YhZuhLVz7xfuZhfHCY9.jpg', 'profession': 'Salesforce Expert', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' }, { Name: 'Sachin', img: 'https://t3.ftcdn.net/jpg/02/60/67/80/240_F_260678009_gV1PBTotxDIwTngnmn3nYqWshbznYf24.jpg', 'profession': 'Salesforce Consultant', review: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' }, ] renderedCallback() { this.data.forEach(ele => { this.template.querySelector('.carousel').innerHTML += '<li class="card"> <div class="img"> <img src="' + ele.img + '" alt="img" draggable="false"></div> <h2>' + ele.Name + '</h2> <span>' + ele.profession + '</span> <p class="testim"> ' + ele.review + ' </p></li>'; }) const wrapper = this.template.querySelector(".wrapper"); const carousel = this.template.querySelector(".carousel"); const firstCardWidth = carousel.querySelector(".card").offsetWidth; const arrowBtns = this.template.querySelectorAll(".wrapper i"); const carouselChildrens = [...carousel.children]; let isDragging = false; let isAutoPlay = true; let startX; let startScrollLeft; let timeoutId; // Get the number of cards that can fit in the carousel at once let cardPerView = Math.round(carousel.offsetWidth / firstCardWidth); // Insert copies of the last few cards to beginning of carousel for infinite scrolling carouselChildrens .slice(-cardPerView) .reverse() .forEach((card) => { carousel.insertAdjacentHTML("afterbegin", card.outerHTML); }); carouselChildrens.slice(0, cardPerView).forEach((card) => { carousel.insertAdjacentHTML("beforeend", card.outerHTML); }); // Scroll the carousel at appropriate postition to hide first few duplicate cards on Firefox carousel.classList.add("no-transition"); carousel.scrollLeft = carousel.offsetWidth; carousel.classList.remove("no-transition"); // Add event listeners for the arrow buttons to scroll the carousel left and right arrowBtns.forEach((btn) => { console.log(btn); console.log(btn.id); btn.addEventListener("click", () => { carousel.scrollLeft += btn.id.includes("left") ? -firstCardWidth : firstCardWidth; }); }); const dragStart = (e) => { isDragging = true; carousel.classList.add("dragging"); // Records the initial cursor and scroll position of the carousel startX = e.pageX; startScrollLeft = carousel.scrollLeft; }; const dragging = (e) => { if (!isDragging) return; // if isDragging is false return from here // Updates the scroll position of the carousel based on the cursor movement carousel.scrollLeft = startScrollLeft - (e.pageX - startX); }; const dragStop = () => { isDragging = false; carousel.classList.remove("dragging"); }; const infiniteScroll = () => { // If the carousel is at the beginning, scroll to the end if (carousel.scrollLeft === 0) { carousel.classList.add("no-transition"); carousel.scrollLeft = carousel.scrollWidth - 2 * carousel.offsetWidth; carousel.classList.remove("no-transition"); } // If the carousel is at the end, scroll to the beginning else if ( Math.ceil(carousel.scrollLeft) === carousel.scrollWidth - carousel.offsetWidth ) { carousel.classList.add("no-transition"); carousel.scrollLeft = carousel.offsetWidth; carousel.classList.remove("no-transition"); } // Clear existing timeout & start autoplay if mouse is not hovering over carousel clearTimeout(timeoutId); if (!wrapper.matches(":hover")) autoPlay(); }; const autoPlay = () => { if (window.innerWidth < 800 || !isAutoPlay) return; // Return if window is smaller than 800 or isAutoPlay is false // Autoplay the carousel after every 2500 ms timeoutId = setTimeout(() => (carousel.scrollLeft += firstCardWidth), 2500); }; autoPlay(); carousel.addEventListener("mousedown", dragStart); carousel.addEventListener("mousemove", dragging); document.addEventListener("mouseup", dragStop); carousel.addEventListener("scroll", infiniteScroll); wrapper.addEventListener("mouseenter", () => clearTimeout(timeoutId)); wrapper.addEventListener("mouseleave", autoPlay); } }
LwcTestimonialSlider.CSS :
.body {
display: flex;
padding: 0 35px;
align-items: center;
justify-content: center;
min-height: 100vh;
background: linear-gradient(to left top, #031a9a, #8b53ff);
}
.wrapper {
max-width: 1100px;
width: 100%;
position: relative;
}
.wrapper i {
top: 50%;
height: 50px;
width: 50px;
cursor: pointer;
font-size: 1.25rem;
position: absolute;
text-align: center;
line-height: 50px;
background: #fff;
border-radius: 50%;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.23);
transform: translateY(-50%);
transition: transform 0.1s linear;
}
.wrapper i:active {
transform: translateY(-50%) scale(0.85);
}
.wrapper i:first-child {
left: -22px;
}
.wrapper i:last-child {
right: -22px;
}
.wrapper .carousel {
display: grid;
grid-auto-flow: column;
grid-auto-columns: calc((100% / 3) - 12px);
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 16px;
border-radius: 8px;
scroll-behavior: smooth;
scrollbar-width: none;
}
.carousel::-webkit-scrollbar {
display: none;
}
.carousel.no-transition {
scroll-behavior: auto;
}
.carousel.dragging {
scroll-snap-type: none;
scroll-behavior: auto;
}
.carousel.dragging .card {
cursor: grab;
user-select: none;
}
.carousel :where(.card, .img) {
display: flex;
justify-content: center;
align-items: center;
}
.carousel .card {
scroll-snap-align: start;
height: 370px;
list-style: none;
background: #fff;
cursor: pointer;
padding-bottom: 15px;
flex-direction: column;
border-radius: 8px;
padding-top: 15px;
}
.carousel .card .img {
background: #8b53ff;
height: 148px;
width: 148px;
border-radius: 50%;
}
.card .img img {
width: 140px;
height: 140px;
border-radius: 50%;
object-fit: cover;
border: 4px solid #fff;
}
.carousel .card h2 {
font-weight: 500;
font-size: 1.4rem;
margin: 30px 0 5px;
}
.carousel .card span {
color: #6a6d78;
font-size: 1rem;
}
@media screen and (max-width: 900px) {
.wrapper .carousel {
grid-auto-columns: calc((100% / 2) - 9px);
}
}
@media screen and (max-width: 600px) {
.wrapper .carousel {
grid-auto-columns: 100%;
}
}
.testim {
font-size: 1.15em;
color: #333;
padding:4%;
margin: auto;
text-align: center;
}
.body {
display: flex;
padding: 0 35px;
align-items: center;
justify-content: center;
min-height: 100vh;
background: linear-gradient(to left top, #031a9a, #8b53ff);
}
.wrapper {
max-width: 1100px;
width: 100%;
position: relative;
}
.wrapper i {
top: 50%;
height: 50px;
width: 50px;
cursor: pointer;
font-size: 1.25rem;
position: absolute;
text-align: center;
line-height: 50px;
background: #fff;
border-radius: 50%;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.23);
transform: translateY(-50%);
transition: transform 0.1s linear;
}
.wrapper i:active {
transform: translateY(-50%) scale(0.85);
}
.wrapper i:first-child {
left: -22px;
}
.wrapper i:last-child {
right: -22px;
}
.wrapper .carousel {
display: grid;
grid-auto-flow: column;
grid-auto-columns: calc((100% / 3) - 12px);
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 16px;
border-radius: 8px;
scroll-behavior: smooth;
scrollbar-width: none;
}
.carousel::-webkit-scrollbar {
display: none;
}
.carousel.no-transition {
scroll-behavior: auto;
}
.carousel.dragging {
scroll-snap-type: none;
scroll-behavior: auto;
}
.carousel.dragging .card {
cursor: grab;
user-select: none;
}
.carousel :where(.card, .img) {
display: flex;
justify-content: center;
align-items: center;
}
.carousel .card {
scroll-snap-align: start;
height: 370px;
list-style: none;
background: #fff;
cursor: pointer;
padding-bottom: 15px;
flex-direction: column;
border-radius: 8px;
padding-top: 15px;
}
.carousel .card .img {
background: #8b53ff;
height: 148px;
width: 148px;
border-radius: 50%;
}
.card .img img {
width: 140px;
height: 140px;
border-radius: 50%;
object-fit: cover;
border: 4px solid #fff;
}
.carousel .card h2 {
font-weight: 500;
font-size: 1.4rem;
margin: 30px 0 5px;
}
.carousel .card span {
color: #6a6d78;
font-size: 1rem;
}
@media screen and (max-width: 900px) {
.wrapper .carousel {
grid-auto-columns: calc((100% / 2) - 9px);
}
}
@media screen and (max-width: 600px) {
.wrapper .carousel {
grid-auto-columns: 100%;
}
}
.testim {
font-size: 1.15em;
color: #333;
padding:4%;
margin: auto;
text-align: center;
}
.body { display: flex; padding: 0 35px; align-items: center; justify-content: center; min-height: 100vh; background: linear-gradient(to left top, #031a9a, #8b53ff); } .wrapper { max-width: 1100px; width: 100%; position: relative; } .wrapper i { top: 50%; height: 50px; width: 50px; cursor: pointer; font-size: 1.25rem; position: absolute; text-align: center; line-height: 50px; background: #fff; border-radius: 50%; box-shadow: 0 3px 6px rgba(0, 0, 0, 0.23); transform: translateY(-50%); transition: transform 0.1s linear; } .wrapper i:active { transform: translateY(-50%) scale(0.85); } .wrapper i:first-child { left: -22px; } .wrapper i:last-child { right: -22px; } .wrapper .carousel { display: grid; grid-auto-flow: column; grid-auto-columns: calc((100% / 3) - 12px); overflow-x: auto; scroll-snap-type: x mandatory; gap: 16px; border-radius: 8px; scroll-behavior: smooth; scrollbar-width: none; } .carousel::-webkit-scrollbar { display: none; } .carousel.no-transition { scroll-behavior: auto; } .carousel.dragging { scroll-snap-type: none; scroll-behavior: auto; } .carousel.dragging .card { cursor: grab; user-select: none; } .carousel :where(.card, .img) { display: flex; justify-content: center; align-items: center; } .carousel .card { scroll-snap-align: start; height: 370px; list-style: none; background: #fff; cursor: pointer; padding-bottom: 15px; flex-direction: column; border-radius: 8px; padding-top: 15px; } .carousel .card .img { background: #8b53ff; height: 148px; width: 148px; border-radius: 50%; } .card .img img { width: 140px; height: 140px; border-radius: 50%; object-fit: cover; border: 4px solid #fff; } .carousel .card h2 { font-weight: 500; font-size: 1.4rem; margin: 30px 0 5px; } .carousel .card span { color: #6a6d78; font-size: 1rem; } @media screen and (max-width: 900px) { .wrapper .carousel { grid-auto-columns: calc((100% / 2) - 9px); } } @media screen and (max-width: 600px) { .wrapper .carousel { grid-auto-columns: 100%; } } .testim { font-size: 1.15em; color: #333; padding:4%; margin: auto; text-align: center; }
LwcTestimonialSlider.JS-meta.xml:
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>57.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>57.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
<?xml version="1.0"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>57.0</apiVersion> <isExposed>true</isExposed> <targets> <target>lightning__HomePage</target> </targets> </LightningComponentBundle>
Output :
Reference :
What’s your Reaction?
+1
4
+1
1
+1
+1
+1
1
+1
1
2 comments
its not working
Can you please tell me error