Build a mobile-friendly testimonials slideshow
Last updated: October 29, 2021.
Testimonials are a common way to put a spotlight on positive customer feedback. In this tutorial, we will cover how you can create a user-controlled testimonials slideshow using HTML, CSS and JavaScript.
What we will build
Below is a live preview of the project. If you toggle your screen size, you will notice that the slideshow has two fixed views: one for desktop and another for mobile. We will cover how to achieve these using a media query when we add CSS to the project.
See the Pen Untitled by James (@openjavascriptadmin) on CodePen.
Step 1: Create (or get) testimonials data
In a live project, it is likely that testimonial data is fetched from a backend server.
In this tutorial we will create the data ourselves within JavaScript.
To do so, we create an array of JavaScript objects. Each JavaScript object contains the following information: an id (id
), the name of the testimonial giver (name
) and their testimonial (text
) as well as a URL to an image of the testimonial giver (image
). User images are randomly generated by the free and open-source Random User Generator API.
Having the data in JavaScript allows us to easily inject it into a web page dynamically.
Step 2: HTML template
We keep this HTML minimal as the testimonial content will be injected using JavaScript.
To wrap the entire content, we create a container div (testimonials-wrapper
). This has three children.
The first div contains two Font Awesome quotation marks elements and these will be made the background of the container using CSS. Add the following link to the Font Awesome CDN to make these visible:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"/>
The second child is a testimonial-content
div. This is empty. We will inject it with content using JavaScript.
Finally, since they are fixed elements, we place a scroll left (<) and scroll right (>) icon each in their own span elements and place both inside a user-controls-container
div.
<div id="testimonials-wrapper"> <!-- Background quotation begin --> <div> <i id="quote-left" class="fas fa-quote-left"></i> <i id="quote-right"class="fas fa-quote-right"></i> </div> <!-- Background quotation end --> <!-- Content begins --> <div id="testimonial-content"></div> <div id="user-controls-container"> <span id="scroll-left"><</span> <span id="scroll-right">></span> </div> <!-- Content ends --> </div>
Step 3: Programming slideshow controls with JavaScript
Since our main content is to be injected with JavaScript, we program this first before turning to CSS when we have a full page of content.
We begin by selecting the testimonial-content
element, into which we will inject content, and the two user controls arrows.
We then create a global index variable (testimonialIndex
) and set its starting value to 0.
We then call the setTestimonial
function to inject content onto the page.
The setTestimonial
function sets the innerHTML of the empty testimonial-content
div to the value of a template string that includes a dynamically injected image, name and testimonial text as follows. The syntax ${testimonials[testimonialIndex].propertyName}
gets the property of the object corresponding to the value of testimonialIndex
in the earlier defined testimonials
data.
So the below code will display the img
, name
and text
property values of the first testimonial inside the empty
content-container div as HTML.
testimonial = document.getElementById('testimonial-content'); left = document.getElementById('scroll-left'); right = document.getElementById('scroll-right'); // Index for setting testimonial let testimonialIndex = 0; // Load first testimonial (array element "0" of testimonials data) setTestimonial(); function setTestimonial() { // Set innerHTML of testimonial content to new template string // with content dynamically injected from testimonials data testimonial.innerHTML = ` <img class="thumbnail" src="${testimonials[testimonialIndex].img}"> <span class="name">${testimonials[testimonialIndex].name}</span> <div class="testimonial-text">${testimonials[testimonialIndex].text}</div> ` }
Next, we add user controls so the user can browse through the testimonials.
We do this by adding event listeners to each of the arrows inside the user-controls-container
.
If it is right, we add 1 to the global testimonialIndex
variables and if left, subtract one.
We then check to see if this makes the value of testimonialIndex
out of bounds (i.e. not corresponding to a stored testimonial). If the value of testimonialIndex
is now greater than the number of testimonials or less than the index of the first testimonial (-1), the value of testimonialIndex
is updated to cycle to the other end of the testimonial list.
Finally, the setTestimonial
function is rerun (to update the testimonial content):
left.addEventListener('click', () => { // 1. Subtract 1 from global index variable testimonialIndex--; // 2. Check if index is -1 (out of bounds). If so, set to // length of testimonals data -1 (final testimonial) if (testimonialIndex == -1) {testimonialIndex = testimonials.length-1} // 3. Set testimonial with updated index variable setTestimonial(); }) right.addEventListener('click', () => { // 1. Add 1 to global index variable testimonialIndex++; // 2. Check if index is the length of testimonials data (out of bounds). // If so, set to 0 (first testimonial) if (testimonialIndex == testimonials.length) {testimonialIndex = 0} // 3. Set testimonial with updated index variable setTestimonial(); })
Step 4: Add responsive CSS
Apply the following CSS for the same appearance as the live preview.
The main features of the CSS:
- Vertical alignment of the contents by applying a vertical flexbox to
testimonials-wrapper
- Quotation elements have
display: absolute
applied to they are ‘under’ the content - User controls arrows centered by applying a horizontal flexbox to
user-controls-container
- A fixed mobile-view of 280px width and 370px height
- A fixed large-screen-view (>650px) of 550px width and 370px height
/*** Mobile layout ***/ body { background-color: whitesmoke; font-family: Arial; } #testimonials-wrapper { display: flex; flex-direction: column; /* format content vertically */ justify-content: space-between; background-color: white; border: 0.1rem lightgray solid; border-radius: 0.3rem; box-shadow: 10px 5px 5px lightgray; padding: 0.5rem; width: 280px; /* fixed width */ height: 370px; /* fixed height */ margin: auto; margin-top: 4rem; } #testimonial-content { /* div into which content is injected by JS */ font-size: 1rem; padding: 1rem; padding-bottom: 0.2rem; text-align: center; } .thumbnail { display: block; margin: auto; width: 100px; border-radius: 10rem; padding: 0.1rem; } .testimonial-text { padding: 0.5rem; padding-left: 0.1rem; padding-right: 0.1rem; font-size: 0.9rem; text-align: center; } .name { font-weight: 900; } #user-controls-container { /* centers contained arrows */ display: flex; flex-direction: row; justify-content: center; } #scroll-left, #scroll-right { text-align: center; font-size: 1.2rem; padding: 0rem; margin: 0rem; color: steelblue; font-weight: 900; margin-left: 1rem; /* margin-left and margin-right create arrow spacing */ margin-right: 1rem; } #quote-left { display: block; position: absolute; color:rgb(176, 196, 222, 0.2); font-size: 100px; } #quote-right { display: block; position: absolute; color:rgb(176, 196, 222, 0.2); font-size: 100px; margin-left: 180px; margin-top: 220px; } /*** Adjustment for desktop ***/ @media screen and (min-width: 650px) { #testimonials-wrapper { width: 550px; } .thumbnail { width: 120px; } #testimonial-content { font-size: 1.2rem; } .testimonial-text { font-size: 1rem; } #quote-right { margin-left: 440px; margin-top: 170px; } }
Summary
In this tutorial, we have seen how to create a testimonials slideshow with user controls using HTML, CSS and plain JavaScript.
If you enjoyed this tutorial, good news. We have more free projects on our projects page!