Vertical Blog Card
A cover image over a category, title, excerpt and author row - the default post card for a grid.
2 frameworksBeginner
An image and copy split side by side that stacks to image-over-text on small screens.
<!-- Below sm the image sits above the copy in reading order; the grid keeps
the two columns aligned without the copy ever wrapping under the image. -->
<a
href="#"
class="group grid w-full max-w-2xl grid-cols-1 overflow-hidden rounded-xl border border-gray-200 bg-white transition-shadow hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 sm:grid-cols-[40%_1fr] dark:border-gray-800 dark:bg-gray-900 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950"
>
<div class="aspect-video overflow-hidden bg-gray-100 sm:aspect-auto dark:bg-gray-800">
<img
src="/images/photo-2.jpg"
alt="Two designers reviewing a wireframe on a tablet"
loading="lazy"
class="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105 motion-reduce:transform-none"
/>
</div>
<div class="flex flex-col justify-center p-5">
<span class="text-xs font-semibold uppercase tracking-wide text-blue-600 dark:text-blue-400">Product</span>
<h3 class="mt-1.5 text-base font-semibold leading-snug text-gray-900 sm:text-lg dark:text-gray-100">
Shipping accessible components without slowing the team down
</h3>
<p class="mt-2 line-clamp-2 text-sm leading-relaxed text-gray-600 dark:text-gray-400">
A practical checklist we run before any component leaves review.
</p>
<span class="mt-3 text-xs text-gray-500 dark:text-gray-500">6 min read</span>
</div>
</a>| Prop | Type | Default | Description |
|---|---|---|---|
titlerequired | string | - | Heading text for the card. |
excerpt | string | - | Short summary shown under the title. |
category | string | - | Category label shown above the title. |
href | string | '#' | Destination the card links to. |
coverSrc | string | - | Image URL for the cover image. |
imageAlt | string | '' | Alternative text for the image. Empty when the title already names it. |
readTime | string | - | Read time |
className | string | - | Additional classes merged onto the root element. |
The grid is `grid-cols-1` then `sm:grid-cols-[40%_1fr]`, so below `sm` the image sits above the copy in reading order rather than squeezing into a thin column. Swap to the reverse variant by moving the media column with `sm:order-last`. The image box keeps `aspect-video` on mobile and stretches to the copy height on `sm` and up.