Back to Shopify Liquid
Reviews Slider v3
Shopify Liquid

Reviews Slider v3

Drop this Shopify Liquid snippet into your theme to add the reviews slider v3 block. Copy the code below, paste it into your theme files, save and you're done.

399 lines · 15.9 KB
Shopify Liquid
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Responsive Slider</title>
7 <style>
8 .user-info {
9 display: flex;
10 align-items: center;
11 gap: 10px;
12 }
13
14 .user-avatar {
15 width: 40px;
16 height: 40px;
17 background-color: #f05454;
18 color: white;
19 border-radius: 50%;
20 display: flex;
21 align-items: center;
22 justify-content: center;
23 font-weight: bold;
24 font-size: 18px;
25 }
26
27 .user-details {
28 display: flex;
29 flex-direction: column;
30 }
31
32.user-name {
33 font-weight: bold;
34 color: #13152f;
35 font-size: 15px;
36 display: flex;
37 align-items: center;
38 gap: 5px;
39 line-height: 22px;
40}
41.reviewing {
42 font-size: 13px;
43 line-height: 20px;
44}
45
46 .rating-inline {
47 font-size: 16px;
48 color: #f7d131;
49 }
50
51.verified-badge {
52 color: #42a5f5;
53 font-size: 10px;
54 display: flex;
55 align-items: center;
56 gap: 4px;
57 font-weight: 600;
58 line-height: 14px;
59}
60
61 .verified-badge img {
62 width: 13px;
63 height: 13px;
64 }
65
66 .product-review {
67 display: flex;
68 gap: 10px;
69 align-items: center;
70 }
71
72 .product-image {
73 width: 40px;
74 height: 40px;
75 object-fit: cover;
76 border: 2px dashed #e0e0e0;
77 border-radius: 5px;
78 }
79
80 .rating {
81 font-size: 24px;
82 color: #f7d131;
83 margin-top: 10px;
84 }
85
86 .description {
87 font-size: 13px;
88 color: #555;
89 text-align: left;
90 line-height: 22px;
91 }
92 #v2-slider-container {
93 overflow: hidden;
94 position: relative;
95padding: 20px 5px;
96max-width: 1500px;
97margin-right: auto;
98margin-left: auto;
99 }
100
101 #v2-slider {
102 display: flex;
103 transition: transform 0.5s ease-in-out;
104 }
105
106 .v2-slider-card {
107 flex: 0 0 80%;
108 max-width: 300px;
109 height: 180px;
110 box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
111 display: flex;
112 flex-direction: column;
113 background-color: #fff;
114 border: 1px solid #e0e0e0;
115 border-radius: 10px;
116 padding: 10px;
117 box-sizing: border-box;
118 gap: 10px;
119 transition: transform 0.3s ease;
120justify-content: space-around;
121margin-right: 10px;
122 }
123
124 .v2-slider-card:hover{
125 transform: translateY(-5px);
126 }
127
128 #v2-pagination {
129 display: flex;
130 justify-content: center;
131 margin-top: 10px;
132 }
133
134.v2-pagination-dot {
135 width: 18px;
136 height: 6px;
137 background-color: #0d437d29;
138 cursor: pointer;
139 }
140
141 .v2-pagination-dot.active {
142 background-color: #f05454;
143width: 22px;
144border-radius: 5px;
145
146 }
147 </style>
148</head>
149<body>
150 <div id="v2-slider-container">
151 <div id="v2-slider">
152 <div class="v2-slider-card">
153 <div class="user-info">
154 <div class="user-avatar">JH</div>
155 <div class="user-details">
156 <div class="user-name">Name here <span class="rating-inline">★★★★★</span></div>
157 <div class="verified-badge">
158 Verified Buyer <img src="https://cdn3.emoji.gg/emojis/9796-verified.png" alt="Verified">
159 </div>
160 </div>
161 </div>
162 <div class="product-review">
163 <img class="product-image" src="https://via.placeholder.com/50" alt="Product">
164 <div class="reviewing">Reviewing <br> <strong>Product name goes here</strong></div>
165 </div>
166 <div class="description">Review goes here for product name goes here</div>
167 </div>
168 <div class="v2-slider-card">
169 <div class="user-info">
170 <div class="user-avatar">JH</div>
171 <div class="user-details">
172 <div class="user-name">Name here <span class="rating-inline">★★★★★</span></div>
173 <div class="verified-badge">
174 Verified Buyer <img src="https://cdn3.emoji.gg/emojis/9796-verified.png" alt="Verified">
175 </div>
176 </div>
177 </div>
178 <div class="product-review">
179 <img class="product-image" src="https://via.placeholder.com/50" alt="Product">
180 <div class="reviewing">Reviewing <br> <strong>Product name goes here</strong></div>
181 </div>
182 <div class="description">Review goes here for product name goes here</div>
183 </div>
184 <div class="v2-slider-card">
185 <div class="user-info">
186 <div class="user-avatar">JH</div>
187 <div class="user-details">
188 <div class="user-name">Name here <span class="rating-inline">★★★★★</span></div>
189 <div class="verified-badge">
190 Verified Buyer <img src="https://cdn3.emoji.gg/emojis/9796-verified.png" alt="Verified">
191 </div>
192 </div>
193 </div>
194 <div class="product-review">
195 <img class="product-image" src="https://via.placeholder.com/50" alt="Product">
196 <div class="reviewing">Reviewing <br> <strong>Product name goes here</strong></div>
197 </div>
198 <div class="description">Review goes here for product name goes here</div>
199 </div>
200 <div class="v2-slider-card">
201 <div class="user-info">
202 <div class="user-avatar">JH</div>
203 <div class="user-details">
204 <div class="user-name">Name here <span class="rating-inline">★★★★★</span></div>
205 <div class="verified-badge">
206 Verified Buyer <img src="https://cdn3.emoji.gg/emojis/9796-verified.png" alt="Verified">
207 </div>
208 </div>
209 </div>
210 <div class="product-review">
211 <img class="product-image" src="https://via.placeholder.com/50" alt="Product">
212 <div class="reviewing">Reviewing <br> <strong>Product name goes here</strong></div>
213 </div>
214 <div class="description">Review goes here for product name goes here</div>
215 </div>
216 <div class="v2-slider-card">
217 <div class="user-info">
218 <div class="user-avatar">JH</div>
219 <div class="user-details">
220 <div class="user-name">Name here <span class="rating-inline">★★★★★</span></div>
221 <div class="verified-badge">
222 Verified Buyer <img src="https://cdn3.emoji.gg/emojis/9796-verified.png" alt="Verified">
223 </div>
224 </div>
225 </div>
226 <div class="product-review">
227 <img class="product-image" src="https://via.placeholder.com/50" alt="Product">
228 <div class="reviewing">Reviewing <br> <strong>Product name goes here</strong></div>
229 </div>
230 <div class="description">Review goes here for product name goes here</div>
231 </div>
232 <div class="v2-slider-card">
233 <div class="user-info">
234 <div class="user-avatar">JH</div>
235 <div class="user-details">
236 <div class="user-name">Name here <span class="rating-inline">★★★★★</span></div>
237 <div class="verified-badge">
238 Verified Buyer <img src="https://cdn3.emoji.gg/emojis/9796-verified.png" alt="Verified">
239 </div>
240 </div>
241 </div>
242 <div class="product-review">
243 <img class="product-image" src="https://via.placeholder.com/50" alt="Product">
244 <div class="reviewing">Reviewing <br> <strong>Product name goes here</strong></div>
245 </div>
246 <div class="description">Review goes here for product name goes here</div>
247 </div>
248 <div class="v2-slider-card">
249 <div class="user-info">
250 <div class="user-avatar">JH</div>
251 <div class="user-details">
252 <div class="user-name">Name here <span class="rating-inline">★★★★★</span></div>
253 <div class="verified-badge">
254 Verified Buyer <img src="https://cdn3.emoji.gg/emojis/9796-verified.png" alt="Verified">
255 </div>
256 </div>
257 </div>
258 <div class="product-review">
259 <img class="product-image" src="https://via.placeholder.com/50" alt="Product">
260 <div class="reviewing">Reviewing <br> <strong>Product name goes here</strong></div>
261 </div>
262 <div class="description">Review goes here for product name goes here</div>
263 </div>
264 <div class="v2-slider-card">
265 <div class="user-info">
266 <div class="user-avatar">JH</div>
267 <div class="user-details">
268 <div class="user-name">Name here <span class="rating-inline">★★★★★</span></div>
269 <div class="verified-badge">
270 Verified Buyer <img src="https://cdn3.emoji.gg/emojis/9796-verified.png" alt="Verified">
271 </div>
272 </div>
273 </div>
274 <div class="product-review">
275 <img class="product-image" src="https://via.placeholder.com/50" alt="Product">
276 <div class="reviewing">Reviewing <br> <strong>Product name goes here</strong></div>
277 </div>
278 <div class="description">Review goes here for product name goes here</div>
279 </div>
280 </div>
281 <div id="v2-pagination"></div>
282 </div>
283
284 <script>
285 class ResponsiveSlider {
286 constructor(containerId, sliderId, paginationId) {
287 this.container = document.getElementById(containerId);
288 this.slider = document.getElementById(sliderId);
289 this.pagination = document.getElementById(paginationId);
290 this.cards = Array.from(this.slider.children);
291 this.cardWidth = this.cards[0].offsetWidth + 10; // Includes margin
292 this.totalWidth = this.cardWidth * this.cards.length - 10; // Adjust total width
293 this.containerWidth = this.slider.parentElement.offsetWidth;
294 this.currentIndex = 0;
295 this.isDragging = false;
296 this.startX = 0;
297 this.currentTranslate = 0;
298 this.prevTranslate = 0;
299 this.animationID = null;
300
301 this.init();
302 }
303
304 init() {
305 this.createPagination();
306 this.addEventListeners();
307 this.startAutoplay();
308 }
309
310 updatePagination() {
311 this.pagination.querySelectorAll('.v2-pagination-dot').forEach((dot, index) => {
312 dot.classList.toggle('active', index === this.currentIndex);
313 });
314 }
315
316 goToSlide(index) {
317 this.currentIndex = index;
318 const maxOffset = Math.max(this.totalWidth - this.containerWidth, 0); // Prevent gaps
319 const offset = Math.min(this.currentIndex * this.cardWidth, maxOffset);
320 this.slider.style.transition = 'transform 0.5s ease';
321 this.slider.style.transform = `translateX(-${offset}px)`;
322 this.currentTranslate = -offset;
323 this.prevTranslate = this.currentTranslate;
324 this.updatePagination();
325 }
326
327 createPagination() {
328 const totalSlides = this.cards.length;
329 this.pagination.innerHTML = '';
330 for (let i = 0; i < totalSlides; i++) {
331 const dot = document.createElement('div');
332 dot.classList.add('v2-pagination-dot');
333 dot.innerHTML = '&#8203;'; // Add zero-width space to prevent being treated as empty
334 if (i === 0) dot.classList.add('active');
335 dot.addEventListener('click', () => this.goToSlide(i));
336 this.pagination.appendChild(dot);
337 }
338 }
339
340 autoplay() {
341 this.currentIndex = (this.currentIndex + 1) % this.cards.length;
342 this.goToSlide(this.currentIndex);
343 }
344
345 startAutoplay() {
346 setInterval(() => this.autoplay(), 3000);
347 }
348
349 startDrag(event) {
350 this.isDragging = true;
351 this.startX = this.getPositionX(event);
352 this.slider.style.transition = 'none';
353 cancelAnimationFrame(this.animationID);
354 }
355
356 endDrag() {
357 this.isDragging = false;
358 const movedBy = this.currentTranslate - this.prevTranslate;
359 if (movedBy < -50 && this.currentIndex < this.cards.length - 1) {
360 this.currentIndex++;
361 }
362 if (movedBy > 50 && this.currentIndex > 0) {
363 this.currentIndex--;
364 }
365 this.goToSlide(this.currentIndex);
366 }
367
368 drag(event) {
369 if (this.isDragging) {
370 const currentPosition = this.getPositionX(event);
371 this.currentTranslate = this.prevTranslate + currentPosition - this.startX;
372 this.slider.style.transform = `translateX(${this.currentTranslate}px)`;
373 }
374 }
375
376 getPositionX(event) {
377 return event.type.includes('mouse') ? event.pageX : event.touches[0].clientX;
378 }
379
380 addEventListeners() {
381 this.slider.addEventListener('mousedown', (e) => this.startDrag(e));
382 this.slider.addEventListener('touchstart', (e) => this.startDrag(e));
383 this.slider.addEventListener('mouseup', () => this.endDrag());
384 this.slider.addEventListener('touchend', () => this.endDrag());
385 this.slider.addEventListener('mousemove', (e) => this.drag(e));
386 this.slider.addEventListener('touchmove', (e) => this.drag(e));
387 window.addEventListener('resize', () => {
388 this.slider.style.transform = 'translateX(0)';
389 this.currentIndex = 0;
390 this.updatePagination();
391 });
392 }
393 }
394
395 // Initialize slider
396 new ResponsiveSlider('v2-slider-container', 'v2-slider', 'v2-pagination');
397 </script>
398</body>
399</html>

Related snippets