Updated
—
3 min read
I've been building Featurable, a review & testimonial management SaaS.
So I've been working with reviews and star rating systems a lot. So here's a brief tutorial on a pure CSS (Tailwind CSS only) five-star rating component.
Here is a preview what we'll be creating:
We want to animate this component to "slide down" like a toast notification.
Let's add this animation to our tailwind.config.js
:
javascriptconst config = {
theme: {
extend: {
keyframes: {
"slide-down": {
from: {
transform: "translateY(-100%)",
},
to: {
transform: "translateY(0)",
},
},
},
animation: {
"slide-down": "slide-down 0.3s ease-out",
},
},
},
};
Great! Now we can set up our component.
I'll call this component ReviewPopup.tsx
:
jsx"use client";
const ReviewPopup: React.FC<{
isOpen?: boolean,
}> = ({ isOpen }) => {
return (
<div
className={"z-[60] fixed top-6 left-1/2 -translate-x-1/2"}
>
<div
className={clsx(
" bg-white p-3 shadow border border-solid border-gray-200 rounded-md",
isOpen ? "animate-slide-down" : "opacity-0"
)}
>
<p className="font-bold text-base">
How are you enjoying our product?
</p>
<p className="mt-1 text-xs text-center text-gray-500">
Use the stars below to rate your experience.
</p>
<div className="mt-2 flex items-center justify-center">
{/*
Stars will go here
*/}
</div>
<div className="mt-2 flex items-center justify-center">
<button
onClick={() => setIsOpen(false)}
className="text-sm mx-auto text-gray-500 "
>
Maybe later
</button>
</div>
</div>
</div>
);
};
I want it the popup to be centered horizontally (using translateX
), but our animation also uses translateY
.
Since we don't want animate-slide-down
to overwrite our horizontal translate, I'm using two outer div
containers.
Now let's add the stars.
Our goal is when a star is hovered, all stars to the left are also highlighted.
To do this, we'll create a CSS class like so:
css.star:hover .star,
.star:hover ~ .star .star-icon {
@apply fill-gray-400;
}
The element1~element2
operator selects every element2
that is preceded by element1
.
Now let's use this class in our component like so:
jsx{
Array.from(Array(5)).map((_, i) => {
return (
<button className="star">
<StarIcon
className={"star-icon h-6 w-6 fill-amber-500"}
/>
</button>
);
});
}
And that's it!
Now we have a fancy pure CSS star rating component:
Enjoy, and be sure to check out Featurable if you're looking to improve your social proof, boost conversion rates, and save time + money managing customer feedback.
Meet the Author
Ryan Chiang
Hello, I'm Ryan. I build things and write about them. This is my blog of my learnings, tutorials, and whatever else I feel like writing about.
See what I'm building →.
If you want an alert when I write a new blog post (not often), you can subscribe below:
0
Comments
Leave a Comment
Your email will not be published. Required fields are marked *