Infinite scrolling carousels are an excellent way to create a dynamic and engaging user experience.
In the world of web development, creating engaging and dynamic user interfaces is key to capturing and maintaining user attention. One popular technique is the infinite scrolling logo slider, often used to showcase partnerships, clients, or featured brands. In this post, we'll walk through how to create a responsive, infinite scrolling logo slider using React, Prismic CMS, and CSS, with a particular focus on ensuring it works well across all device sizes.
The main challenges in creating an infinite scrolling logo slider are:
Our solution involves a combination of React for component structure, Prismic for content management, and CSS for animation and responsive design. Here's a breakdown of the key elements:
We'll use Prismic to manage our logos. This allows for easy updates and management of the logos without changing the code. Here's how we set it up:
We'll create two main components: InfiniteScroller and LogoSlider. The InfiniteScroller component will fetch data from Prismic and pass it to LogoSlider.
Here's the basic structure of InfiniteScroller:
import dynamic from 'next/dynamic';
import { Content } from '@prismicio/client';
import { SliceComponentProps } from '@prismicio/react';
import { ImageField } from '@prismicio/types';
const LogoSlider = dynamic(() => import('./LogoSlider'), { ssr: false });
export type InfiniteScrollerProps = SliceComponentProps<Content.InfiniteScrollerSlice>;
const InfiniteScroller = ({ slice }: InfiniteScrollerProps): JSX.Element => {
const logos = slice.primary.logo_group.map((item) => item.logo as ImageField);
return (
<section className="relative w-full lg:mt-24 mt-2 bg-slate-50 py-12 md:py-16 lg:py-24">
<div className="w-full px-4 md:w-3/4 lg:w-1/2 mx-auto">
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold text-smiths text-center mb-4 md:mb-6">
Our Ice Cold Partnerships
</h2>
<p className="text-sm md:text-base lg:text-lg text-smiths-dark mb-8 md:mb-12 text-center">
We're proud to serve a diverse range of companies. These logos represent partnerships built on our commitment to excellence in ice supply.
</p>
</div>
<LogoSlider logos={logos} />
</section>
);
};
export default InfiniteScroller;
And here's the structure of LogoSlider:
"use client";
import React, { useEffect, useRef } from 'react';
import { ImageField } from '@prismicio/types';
interface LogoSliderProps {
logos: ImageField[];
}
const LogoSlider: React.FC<LogoSliderProps> = ({ logos }) => {
// Component logic here
}
export default LogoSlider;
In the LogoSlider component, we use CSS variables to adjust the slider's properties based on screen size:
useEffect(() => {
const slider = sliderRef.current;
if (!slider) return;
slider.style.setProperty('--n', logos.length.toString());
const handleResize = () => {
const viewportWidth = window.innerWidth;
if (viewportWidth < 640) {
slider.style.setProperty('--w', '100px');
slider.style.setProperty('--g', '0.5rem');
slider.style.setProperty('--d', '15s');
} else if (viewportWidth < 1024) {
slider.style.setProperty('--w', '140px');
slider.style.setProperty('--g', '1rem');
slider.style.setProperty('--d', '20s');
} else {
slider.style.setProperty('--w', '180px');
slider.style.setProperty('--g', '1.5rem');
slider.style.setProperty('--d', '25s');
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [logos]);
The key to making this slider work smoothly lies in the CSS. Here's the crucial part:
.logo-slider-container {
max-width: 100vw;
width: 100%;
overflow: hidden;
-webkit-mask: linear-gradient(90deg, #0000, #000 10% 90%, #0000);
mask: linear-gradient(90deg, #0000, #000 10% 90%, #0000);
}
.logo-slider {
--w: 180px; /* default logo width */
--g: 1.5rem; /* default gap between logos */
--d: 25s; /* default duration */
display: flex;
width: fit-content;
animation: scroll var(--d) linear infinite;
}
@keyframes scroll {
0% { transform: translateX(0); }
100% { transform: translateX(calc((var(--w) + var(--g)) * var(--n) * -1)); }
}
In the render method of our LogoSlider component, we triple the logos array to ensure smooth looping:
const tripleLogos = [...logos, ...logos, ...logos];
return (
<div className="logo-slider-container">
<div ref={sliderRef} className="logo-slider flex">
{tripleLogos.map((logo, index) => (
<div key={index} className="logo-item flex-shrink-0">
<img
src={logo.url}
alt={logo.alt || `Logo ${index + 1}`}
className="w-full h-full object-contain"
/>
</div>
))}
</div>
{/* CSS styles here */}
</div>
);
This implementation creates a smooth, infinite scrolling effect that works across all device sizes. The logos, managed through Prismic, scroll continuously from right to left, creating an engaging visual element on your webpage.
By combining these techniques with Prismic CMS, you can create a professional-looking, responsive infinite logo slider that enhances the visual appeal of your website while showcasing your partnerships or clients. Plus, the content management aspect allows for easy updates without touching the code.
Remember, the key to great web development is often finding simple, elegant solutions to complex problems, and integrating them with powerful content management systems like Prismic. Happy coding!