← Back to Cards

Cards pattern

Pricing card group

Three comparable plans with semantic lists, a clearly named recommendation, and responsive columns.

Live example

See the pattern in isolation

The preview uses the same locked-down composition policy as the Agate IDE.

PreviewSandboxed

Canonical source

Copy it, change it, keep it plain

These exact files power the preview and the IDE handoff.

Source

HTML

<section class="pricing" aria-labelledby="pricing-title">
  <header class="pricing__header">
    <p>Simple monthly plans</p>
    <h1 id="pricing-title">Choose the support you need.</h1>
    <p>Every plan includes accessible templates and plain-language documentation. Change or cancel at any time.</p>
  </header>

  <ul class="plan-list">
    <li>
      <article class="plan" aria-labelledby="starter-title">
        <h2 id="starter-title">Starter</h2>
        <p class="plan__price"><span>$</span>12 <span>/ month</span></p>
        <p>For one small site taking shape.</p>
        <ul>
          <li>One published project</li>
          <li>Community guidance</li>
          <li>Monthly office hours</li>
        </ul>
        <a href="mailto:hello@example.com?subject=Starter%20plan">Ask about Starter</a>
      </article>
    </li>
    <li>
      <article class="plan plan--recommended" aria-labelledby="studio-title">
        <p class="plan__flag">Recommended</p>
        <h2 id="studio-title">Studio</h2>
        <p class="plan__price"><span>$</span>29 <span>/ month</span></p>
        <p>For an active portfolio of client work.</p>
        <ul>
          <li>Ten published projects</li>
          <li>Email guidance</li>
          <li>Weekly office hours</li>
        </ul>
        <a href="mailto:hello@example.com?subject=Studio%20plan">Ask about Studio</a>
      </article>
    </li>
    <li>
      <article class="plan" aria-labelledby="team-title">
        <h2 id="team-title">Team</h2>
        <p class="plan__price"><span>$</span>64 <span>/ month</span></p>
        <p>For a small group sharing a design system.</p>
        <ul>
          <li>Unlimited projects</li>
          <li>Priority guidance</li>
          <li>Shared review sessions</li>
        </ul>
        <a href="mailto:hello@example.com?subject=Team%20plan">Ask about Team</a>
      </article>
    </li>
  </ul>
</section>
Source

CSS

* {
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  margin: 0;
  padding: clamp(1.5rem, 6vw, 5rem);
  background: #f2e3de;
  color: #2b151d;
  font-family: system-ui, sans-serif;
}

.pricing {
  width: min(100%, 70rem);
  margin-inline: auto;
}

.pricing__header {
  max-width: 48rem;
  margin-bottom: 2rem;
}

.pricing__header > p:first-child,
.plan__flag {
  margin: 0 0 0.75rem;
  color: #8e2f50;
  font-size: 0.78rem;
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.pricing h1 {
  max-width: 13ch;
  margin: 0;
  font-size: clamp(2.25rem, 7vw, 4.5rem);
  line-height: 1;
}

.pricing__header > p:last-child {
  max-width: 58ch;
  color: #5c3b45;
  line-height: 1.6;
}

.plan-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.plan-list > li {
  display: flex;
}

.plan {
  display: flex;
  width: 100%;
  min-height: 30rem;
  flex-direction: column;
  padding: 1.5rem;
  border: 4px solid #2b151d;
  background: #fffaf5;
}

.plan--recommended {
  background: #d94f9d;
}

.plan--recommended .plan__flag {
  color: #2b151d;
}

.plan h2 {
  margin: 0;
  font-size: 1.6rem;
}

.plan__price {
  margin: 1.25rem 0;
  font-size: 3rem;
  font-weight: 900;
  line-height: 1;
}

.plan__price > span:last-child {
  font-size: 0.9rem;
  font-weight: 700;
}

.plan > p:not(.plan__price, .plan__flag) {
  min-height: 3.2em;
  line-height: 1.6;
}

.plan ul {
  display: grid;
  gap: 0.75rem;
  margin: 1rem 0 2rem;
  padding-inline-start: 1.25rem;
  line-height: 1.45;
}

.plan > a {
  display: inline-flex;
  min-height: 3rem;
  align-items: center;
  justify-content: center;
  margin-top: auto;
  padding: 0.75rem 1rem;
  border: 2px solid #2b151d;
  background: #b0436a;
  color: #ffffff;
  font-weight: 850;
  text-align: center;
  text-decoration: none;
}

.plan--recommended > a,
.plan > a:hover {
  background: #2b151d;
}

.plan > a:focus-visible {
  outline: 4px solid #2b151d;
  outline-offset: 4px;
}

@media (max-width: 50rem) {
  .plan-list {
    grid-template-columns: 1fr;
  }

  .plan {
    min-height: auto;
  }

  .plan > p:not(.plan__price, .plan__flag) {
    min-height: auto;
  }
}

How it works

A small pattern with visible decisions

The plans form one semantic list, and each card is an article with its own heading. Features are lists too, which makes the comparison understandable before CSS creates columns.

The recommended plan is identified with text rather than color alone. Flexbox keeps each action at the bottom of equal-height cards, while the narrow layout returns the plans to a straightforward vertical sequence.

Make it yours

Open both files in the workspace.

Agate will protect different saved work before loading this example.