Edge-to-edge hotel room tiles with name, location, nightly price and guests, beds and size over a dark gradient. React and Tailwind CSS.
HotelRoomCards.tsx
// Hotel room cards: edge-to-edge photo tiles with name, location, nightly
// price and specs over a dark gradient; photos zoom gently on hover.
// Pure Tailwind, no dependencies. Works with Tailwind v3 and v4.
type Room = {
name: string;
location: string;
price: string;
guests: number;
beds: number;
size: string;
image: string;
href?: string;
};
type Props = {
heading?: string;
rooms?: Room[];
};
const img = (id: string) => `https://images.unsplash.com/photo-${id}?w=1200&q=80&auto=format&fit=crop`;
const DEFAULT_ROOMS: Room[] = [
{ name: "Garden Suite", location: "Ground floor · Garden view", price: "$420", guests: 2, beds: 1, size: "48 m²", image: img("1582719478250-c89cae4dc85b") },
{ name: "Sea View Room", location: "Upper floor · Sea view", price: "$360", guests: 2, beds: 1, size: "36 m²", image: img("1493809842364-78817add7ffb") },
{ name: "Family Loft", location: "Top floor · Terrace", price: "$540", guests: 4, beds: 2, size: "64 m²", image: img("1505691938895-1758d7feb511") },
];
export default function RoomCards({ heading = "Rooms & suites", rooms = DEFAULT_ROOMS }: Props) {
return (
<section className="bg-white py-24 font-sans antialiased">
{heading && <h2 className="mx-auto mb-12 max-w-7xl px-5 text-center font-['Cardo',Georgia,'Times_New_Roman',serif] text-4xl text-black md:text-6xl">{heading}</h2>}
<ul className="grid gap-1.5 px-2.5 sm:grid-cols-2 lg:grid-cols-3">
{rooms.map((room) => (
<li key={room.name}>
<a href={room.href ?? "#"} className="group relative block aspect-[13/10] overflow-hidden bg-black text-white">
<img src={room.image} alt={room.name} loading="lazy" className="absolute inset-0 h-full w-full object-cover transition duration-1000 ease-out group-hover:scale-105" />
<div className="absolute inset-0 bg-gradient-to-t from-black/75 via-black/15 to-transparent" />
<div className="absolute inset-x-0 bottom-0 p-5 md:p-6">
<h3 className="font-['Cardo',Georgia,'Times_New_Roman',serif] text-2xl">{room.name}</h3>
<p className="mt-1 flex items-center gap-1.5 text-sm text-white/85">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" aria-hidden className="h-3.5 w-3.5">
<path d="M12 21s-7-6.2-7-11.5A7 7 0 0 1 19 9.5C19 14.8 12 21 12 21zM12 12a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z" />
</svg>
{room.location}
</p>
<p className="mt-3 font-['Cardo',Georgia,'Times_New_Roman',serif] text-2xl">
{room.price}
<span className="ml-1 font-sans text-sm text-white/80">/ night</span>
</p>
<p className="mt-2 flex flex-wrap gap-x-4 gap-y-1 text-sm text-white/85">
<span>
{room.guests} {room.guests === 1 ? "guest" : "guests"}
</span>
<span>
{room.beds} {room.beds === 1 ? "bed" : "beds"}
</span>
<span>{room.size}</span>
</p>
</div>
</a>
</li>
))}
</ul>
</section>
);
}
How to use it
- Make sure your Next.js or React project has Tailwind CSS set up (v3 or v4 both work).
- Create
components/HotelRoomCards.tsxand paste the code. - Import it into a page and replace the sample text and images with your own.
