I'm trying to create a scrolling posts animation in React using TailwindCSS and Framer Motion similar to this example link?
I tried to implement it this way, but it doesn’t work and doesn’t look as expected.
import { BsTwitterX, BsInstagram, BsThreads } from "react-icons/bs";
import "./App.css";
import { motion } from "framer-motion";
const posts = [
{
title: "#ultra25",
username: "@user1",
text: "Great vibes at Ultra Music Festival!",
image: ".jpg",
source: "instagram",
},
{
title: "#ultra25",
username: "@user2",
text: "Epic night with amazing beats!",
image: "",
source: "twitter",
},
{
title: "#ultra25",
username: "@user3",
text: "The best party of the year!",
image: ".jpg",
source: "threads",
},
{
title: "#ultra25",
username: "@user4",
text: "Unfettable memories at Ultra!",
image: "",
source: "instagram",
},
{
title: "#ultra25",
username: "@user1",
text: "Great vibes at Ultra Music Festival!",
image: ".jpg",
source: "instagram",
},
{
title: "#ultra25",
username: "@user2",
text: "Epic night with amazing beats!",
image: "",
source: "twitter",
},
{
title: "#ultra25",
username: "@user3",
text: "The best party of the year!",
image:
";,
source: "threads",
},
{
title: "#ultra25",
username: "@user4",
text: "Unfettable memories at Ultra!",
image: "",
source: "instagram",
},
{
title: "#ultra25",
username: "@user1",
text: "Great vibes at Ultra Music Festival!",
image: ".jpg",
source: "instagram",
},
{
title: "#ultra25",
username: "@user2",
text: "Epic night with amazing beats!",
image: "",
source: "twitter",
},
{
title: "#ultra25",
username: "@user3",
text: "The best party of the year!",
image: ".jpg:large",
source: "threads",
},
{
title: "#ultra25",
username: "@user4",
text: "Unfettable memories at Ultra!",
image: "",
source: "instagram",
},
{
title: "#ultra25",
username: "@user1",
text: "Great vibes at Ultra Music Festival!",
image: ".jpg",
source: "instagram",
},
{
title: "#ultra25",
username: "@user2",
text: "Epic night with amazing beats!",
image: "",
source: "twitter",
},
{
title: "#ultra25",
username: "@user3",
text: "The best party of the year!",
image: ".jpg",
source: "threads",
},
{
title: "#ultra25",
username: "@user4",
text: "Unfettable memories at Ultra!",
image: "",
source: "instagram",
},
];
const renderSocialIcon = (source: string) => {
switch (source) {
case "instagram":
return <BsInstagram className="text-[#0077e7] w-[20px] h-[20px]" />;
case "twitter":
return <BsTwitterX className="text-[#0077e7] w-[20px] h-[20px]" />;
case "threads":
return <BsThreads className="text-[#0077e7] w-[20px] h-[20px]" />;
default:
return null;
}
};
const App = () => {
const createColumnAnimation = (colIndex) => ({
animate: {
y: ["0%", "-100%"],
transition: {
repeat: Infinity,
repeatType: "loop",
duration: 5,
ease: "linear",
delay: colIndex * 2,
},
},
});
return (
<div className="min-h-screen bg-gray-100 pt-[180px] px-6">
<div className="grid grid-cols-4 gap-6">
{Array.from({ length: 4 }).map((_, colIndex) => (
<motion.div
key={colIndex}
className="flex flex-col overflow-hidden relative"
variants={createColumnAnimation(colIndex)}
animate="animate"
>
<div className="flex flex-col">
{posts
.filter((_, index) => index % 4 === colIndex)
.map((post, postIndex) => (
<div
key={postIndex}
className="bg-white rounded-lg shadow-lg flex flex-col min-h-[250px]"
>
<div className="flex justify-between items-center p-4">
<h3 className="text-xl font-bold text-black uppercase">
#ultra25
</h3>
<div className="flex space-x-4">
{renderSocialIcon(post.source)}
</div>
</div>
{post.image ? (
<img
src={post.image}
alt="Post"
style={{
height: "auto",
objectFit: "cover",
width: "100%",
}}
/>
) : null}
<div className="p-4">
<footer className="text-[#0084ff]">
<span className="font-semibold uppercase">
{post.username}
</span>
<p className="text-black">{post.text}</p>
</footer>
</div>
</div>
))}
</div>
</motion.div>
))}
</div>
</div>
);
};
export default App;
What I’m trying to achieve:
- Each column scrolls upward by one post in 1 second.
- The next column starts scrolling 2 seconds after the previous one.
- The animation loops infinitely and smoothly.
- The effect should resemble continuous, seamless scrolling.
What’s not working:
- The animation doesn’t look smooth, and it feels jerky.
- It seems like the entire column scrolls rather than individual posts.
- It doesn’t create the smooth, infinite scrolling effect I’m aiming for.
Could the issue be related to using CSS Grid instead of Flexbox or maybe Is there a better way to handle this with Framer Motion?
Any help would be greatly appreciated!
Preview