Skip to content

CSS Tutorial Practical Projects

Project: A Pricing Card

Lesson 175 of 182 2 min read By Deepak Paswan Updated Oct 4, 2026

Pricing cards combine a lot: grid, borders, badges, lists with custom markers and emphasis. This project builds three plans with a featured one in the middle.

The finished cards

index.html
HTML
<style>
  *, *::before, *::after { box-sizing: border-box; }
  body { margin: 0; padding: 20px 16px; font-family: system-ui, sans-serif; background: #f9f5f1; }

  .plans { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); align-items: start; max-width: 800px; margin: 0 auto; }

  .plan { position: relative; background: #fff; border: 2px solid #e6ddd7; border-radius: 14px; padding: 24px 20px; }
  .plan--featured { border-color: #d94a00; box-shadow: 0 10px 24px rgba(217,74,0,.18); }
  .plan__badge { position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: #d94a00; color: #fff; font-size: .75rem; font-weight: 700; padding: 3px 12px; border-radius: 999px; white-space: nowrap; }

  .plan__name { margin: 0; font-size: 1.125rem; }
  .plan__price { margin: 8px 0 16px; font-size: 2.25rem; font-weight: 800; line-height: 1; }
  .plan__price span { font-size: .9rem; font-weight: 400; color: #5c5750; }

  .plan__list { list-style: none; margin: 0 0 20px; padding: 0; }
  .plan__list li { position: relative; padding: 5px 0 5px 24px; font-size: .9375rem; }
  .plan__list li::before { content: "✓"; position: absolute; left: 0; color: #27ae60; font-weight: 700; }

  .plan__cta { display: block; text-align: center; padding: 11px; border-radius: 8px; border: 2px solid #d94a00; color: #d94a00; text-decoration: none; font-weight: 700; }
  .plan__cta:hover, .plan__cta:focus-visible { background: #d94a00; color: #fff; }
  .plan--featured .plan__cta { background: #d94a00; color: #fff; }
  .plan--featured .plan__cta:hover { background: #b84624; border-color: #b84624; }
</style>
<div class="plans">
  <section class="plan">
    <h2 class="plan__name">Starter</h2>
    <p class="plan__price">$9<span>/month</span></p>
    <ul class="plan__list"><li>1 shop</li><li>100 products</li><li>Email support</li></ul>
    <a class="plan__cta" href="#">Choose Starter</a>
  </section>
  <section class="plan plan--featured">
    <span class="plan__badge">Most popular</span>
    <h2 class="plan__name">Standard</h2>
    <p class="plan__price">$19<span>/month</span></p>
    <ul class="plan__list"><li>3 shops</li><li>Unlimited products</li><li>Priority support</li><li>Sales reports</li></ul>
    <a class="plan__cta" href="#">Choose Standard</a>
  </section>
  <section class="plan">
    <h2 class="plan__name">Studio</h2>
    <p class="plan__price">$39<span>/month</span></p>
    <ul class="plan__list"><li>10 shops</li><li>Unlimited products</li><li>Phone support</li></ul>
    <a class="plan__cta" href="#">Choose Studio</a>
  </section>
</div>

The plan names and prices are made-up sample content for the exercise.

Notes

  • Grid with auto-fit lets the cards sit in a row or stack by themselves. See auto-fit and auto-fill.
  • align-items: start stops shorter cards stretching to the height of the tallest.
  • The badge uses position: absolute against a position: relative card, and translateX(-50%) to center itself.
  • Checkmarks come from ::before, so the HTML stays a plain list.
  • The featured card is emphasised with a color, a border and a shadow, not by size alone, so it also works for people who cannot tell colors apart.

Make it yours

  1. Make the featured card slightly taller on wide screens with transform: scale(1.03).
  2. Add a “yearly / monthly” switch (needs JavaScript) that changes the price using a variable.

Exercise: a disabled plan

Add a .plan--soon modifier that dims a card to 60% opacity and makes its button look disabled and non-clickable.

Show a possible solution
style.css
CSS
.plan--soon { opacity: .6; }
.plan--soon .plan__cta { border-color: #999; color: #666; pointer-events: none; }

For real accessibility also add aria-disabled="true" to the link.