How to Create a Card in CSS

Build a reusable card component that groups an image, heading, description, and action into one visually distinct block.

What makes a card a card

A card is a self-contained block of related content - typically an image, a title, some supporting text, and an optional action - set apart from the rest of the page with a border, shadow, or background color. Cards are the standard way to present a list of similar things (products, articles, team members) as a scannable grid.

Structurally, a card is just a container element with a few semantic children. The visual identity comes entirely from CSS: padding for breathing room, a border-radius for softened corners, and a box-shadow to lift it off the background.

Example: a single card

<!DOCTYPE html>
<html>
<head>
<style>
  .card {
    max-width: 320px;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    overflow: hidden; /* clips the image to the rounded corners */
    font-family: system-ui, sans-serif;
  }
  .card img {
    width: 100%;
    height: 160px;
    object-fit: cover; /* fills the box without distorting the image */
    display: block;
  }
  .card-body {
    padding: 16px 20px 20px;
  }
  .card-title {
    margin: 0 0 8px;
    font-size: 1.1rem;
  }
  .card-text {
    margin: 0 0 16px;
    color: #5b6472;
    font-size: 0.9rem;
    line-height: 1.5;
  }
  .card-action {
    display: inline-block;
    background: #2563eb;
    color: #fff;
    text-decoration: none;
    padding: 8px 16px;
    border-radius: 6px;
    font-size: 0.9rem;
  }
  .card-action:hover {
    background: #1d4ed8;
  }
</style>
</head>
<body>

<div class="card">
  <img src="https://picsum.photos/id/1025/320/160" alt="A dog sitting in snow">
  <div class="card-body">
    <h3 class="card-title">Winter Hikes</h3>
    <p class="card-text">A short guide to keeping your dog warm and safe on cold-weather trails.</p>
    <a class="card-action" href="#">Read more</a>
  </div>
</div>

</body>
</html>
Note: object-fit: cover on the image is what keeps every card the same height even when the source images have different aspect ratios - the image is cropped, not squashed, to fill its box.

Laying out a grid of cards

Cards are almost always shown in groups. `display: grid` with `grid-template-columns: repeat(auto-fit, minmax(240px, 1fr))` produces a responsive grid that fits as many cards per row as will comfortably fit, and reflows to fewer columns automatically as the viewport shrinks - no media queries required.

Example: responsive card grid

<!DOCTYPE html>
<html>
<head>
<style>
  .card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 20px;
  }
</style>
</head>
<body>

<div class="card-grid">
  <div class="card"><!-- card 1 content --></div>
  <div class="card"><!-- card 2 content --></div>
  <div class="card"><!-- card 3 content --></div>
</div>

</body>
</html>

`auto-fit` tells the grid to collapse empty tracks, so a row with only two cards stretches them to fill the space rather than leaving a gap; `minmax(240px, 1fr)` sets a floor of 240px per card while letting them grow evenly to fill any extra width.

  • Use semantic tags inside the card (h3 for the title, p for the description, a for the action) so the content makes sense even without the CSS.
  • Keep the whole card clickable by wrapping it in an <a> tag when the card links to one destination, rather than only making a small 'Read more' link clickable.
  • Cap image height with a fixed value plus object-fit: cover so mismatched image sizes don't break the grid's alignment.
Note: If the entire card is wrapped in an <a>, do not put another <a> or <button> inside it - nested interactive elements are invalid HTML and produce unpredictable click behavior.

Frequently Asked Questions

How do I create a card component in CSS?
Use a container with padding, a border or subtle shadow, and border-radius. Put the image first with width: 100%, then the text content. Flex column layout keeps the spacing even as content length varies.
How do I make cards the same height in a row?
Put them in a flex or grid container. Both stretch children to match the tallest by default. Inside each card, use margin-top: auto on the footer so buttons align across cards even when the text above differs in length.