Open demo

CSS code

HTML
<div class="pr-grid">
  <article class="pr-card">
    <h2 class="pr-name">Starter</h2>
    <p class="pr-price">$0<span>/mo</span></p>
    <p class="pr-per">For side projects</p>
    <ul class="pr-list">
      <li>1 project</li>
      <li>Community support</li>
      <li class="pr-no"><span class="pr-sr">Not included: </span>Custom domain</li>
      <li class="pr-no"><span class="pr-sr">Not included: </span>Team seats</li>
    </ul>
    <button class="pr-go" type="button">Start free</button>
  </article>
  <article class="pr-card pr-hot">
    <p class="pr-flag">Most popular</p>
    <h2 class="pr-name">Pro</h2>
    <p class="pr-price">$19<span>/mo</span></p>
    <p class="pr-per">For growing products</p>
    <ul class="pr-list">
      <li>Unlimited projects</li>
      <li>Priority support</li>
      <li>Custom domain</li>
      <li class="pr-no"><span class="pr-sr">Not included: </span>Team seats</li>
    </ul>
    <button class="pr-go" type="button">Go Pro</button>
  </article>
  <article class="pr-card">
    <h2 class="pr-name">Team</h2>
    <p class="pr-price">$49<span>/mo</span></p>
    <p class="pr-per">For whole teams</p>
    <ul class="pr-list">
      <li>Unlimited projects</li>
      <li>Priority support</li>
      <li>Custom domain</li>
      <li>10 team seats</li>
    </ul>
    <button class="pr-go" type="button">Start trial</button>
  </article>
</div>
CSS
/* Three-tier pricing cards with a dark, slightly enlarged featured plan.
   Tick and dash markers are CSS ::before glyphs with empty alt text; excluded features carry a hidden "Not included" prefix. */
.pr-grid,.pr-grid *,.pr-grid *::before,.pr-grid *::after{box-sizing:border-box}
.pr-grid{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:22px}
.pr-card{position:relative;width:260px;background:#fff;border:1px solid #e5e9f0;border-radius:18px;padding:30px 26px;transition:transform .18s,box-shadow .18s}
.pr-card:hover{transform:translateY(-5px);box-shadow:0 22px 44px -18px rgba(15,23,42,.18)}
.pr-card.pr-hot{background:#0f172a;border-color:#0f172a;color:#e2e8f0;transform:scale(1.04)}
.pr-card.pr-hot:hover{transform:scale(1.04) translateY(-5px)}
.pr-flag{position:absolute;top:-12px;left:50%;transform:translateX(-50%);background:#22d3ee;color:#082f36;font-size:.68rem;font-weight:800;letter-spacing:.07em;text-transform:uppercase;white-space:nowrap;margin:0;padding:5px 13px;border-radius:999px}
.pr-name{font-size:.95rem;letter-spacing:.02em;color:#334155;margin:0}
.pr-hot .pr-name{color:#94a3b8}
.pr-price{margin:12px 0 4px;font-size:2.2rem;font-weight:800;letter-spacing:-.03em;color:#0f172a}
.pr-hot .pr-price{color:#fff}
.pr-price span{font-size:.85rem;font-weight:500;letter-spacing:0;color:#64748b}
.pr-per{font-size:.8rem;color:#64748b;margin:0 0 20px}
.pr-hot .pr-price span,.pr-hot .pr-per{color:#94a3b8}
.pr-list{list-style:none;margin:0 0 24px;padding:0}
.pr-list li{font-size:.86rem;padding:7px 0 7px 26px;position:relative;color:#475569}
.pr-hot .pr-list li{color:#cbd5e1}
.pr-list li::before{content:"✓";content:"✓"/"";position:absolute;left:0;top:7px;width:17px;height:17px;border-radius:50%;background:#dcfce7;color:#16a34a;font-size:.7rem;font-weight:800;display:flex;align-items:center;justify-content:center}
.pr-hot .pr-list li::before{background:#164e63;color:#22d3ee}
.pr-list li.pr-no{color:#64748b;text-decoration:line-through}
.pr-hot .pr-list li.pr-no{color:#b6bfcc}
.pr-list li.pr-no::before{content:"–";content:"–"/"";background:#f1f5f9;color:#64748b}
.pr-go{width:100%;padding:12px;border-radius:11px;font:inherit;font-size:.9rem;font-weight:700;cursor:pointer;border:1px solid #8391a5;background:#fff;color:#0f172a;transition:background .15s,filter .15s}
.pr-go:hover{background:#f1f5f9}
.pr-hot .pr-go{border:0;background:#22d3ee;color:#082f36}
.pr-hot .pr-go:hover{filter:brightness(1.1)}
.pr-go:focus-visible{outline:3px solid #0f172a;outline-offset:2px}
.pr-hot .pr-go:focus-visible{outline-color:#22d3ee}
.pr-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media (prefers-reduced-motion:reduce){.pr-card,.pr-go{transition:none}.pr-card:hover{transform:none}.pr-card.pr-hot:hover{transform:scale(1.04)}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div class="row row-cols-auto align-items-center justify-content-center g-4">
  <div class="col">
    <article class="card pr-card">
      <div class="card-body">
        <h2 class="pr-name">Starter</h2>
        <p class="pr-price">$0<span>/mo</span></p>
        <p class="pr-per">For side projects</p>
        <ul class="pr-list list-unstyled">
          <li>1 project</li>
          <li>Community support</li>
          <li class="pr-no"><span class="visually-hidden">Not included: </span>Custom domain</li>
          <li class="pr-no"><span class="visually-hidden">Not included: </span>Team seats</li>
        </ul>
        <button class="btn w-100 pr-go" type="button">Start free</button>
      </div>
    </article>
  </div>
  <div class="col">
    <article class="card pr-card pr-hot">
      <p class="badge rounded-pill position-absolute top-0 start-50 translate-middle m-0 pr-flag">Most popular</p>
      <div class="card-body">
        <h2 class="pr-name">Pro</h2>
        <p class="pr-price">$19<span>/mo</span></p>
        <p class="pr-per">For growing products</p>
        <ul class="pr-list list-unstyled">
          <li>Unlimited projects</li>
          <li>Priority support</li>
          <li>Custom domain</li>
          <li class="pr-no"><span class="visually-hidden">Not included: </span>Team seats</li>
        </ul>
        <button class="btn w-100 pr-go" type="button">Go Pro</button>
      </div>
    </article>
  </div>
  <div class="col">
    <article class="card pr-card">
      <div class="card-body">
        <h2 class="pr-name">Team</h2>
        <p class="pr-price">$49<span>/mo</span></p>
        <p class="pr-per">For whole teams</p>
        <ul class="pr-list list-unstyled">
          <li>Unlimited projects</li>
          <li>Priority support</li>
          <li>Custom domain</li>
          <li>10 team seats</li>
        </ul>
        <button class="btn w-100 pr-go" type="button">Start trial</button>
      </div>
    </article>
  </div>
</div>
CSS
/* Bootstrap .card + .badge + .btn in a .row-cols-auto grid, restyled through --bs-card-* and --bs-btn-* variables.
   The featured plan recolours the card through the same variables and is scaled up slightly. */
.pr-card{--bs-card-border-color:#e5e9f0;--bs-card-border-radius:18px;--bs-card-spacer-x:26px;--bs-card-spacer-y:30px;width:260px;transition:transform .18s,box-shadow .18s}
.pr-card:hover{transform:translateY(-5px);box-shadow:0 22px 44px -18px rgba(15,23,42,.18)}
.pr-card.pr-hot{--bs-card-bg:#0f172a;--bs-card-border-color:#0f172a;--bs-card-color:#e2e8f0;transform:scale(1.04)}
.pr-card.pr-hot:hover{transform:scale(1.04) translateY(-5px)}
.pr-flag{--bs-badge-font-size:.68rem;--bs-badge-font-weight:800;--bs-badge-padding-x:13px;--bs-badge-padding-y:5px;--bs-badge-color:#082f36;background:#22d3ee;letter-spacing:.07em;text-transform:uppercase}
.pr-name{font-size:.95rem;font-weight:700;line-height:normal;letter-spacing:.02em;color:#334155;margin:0}
.pr-hot .pr-name{color:#94a3b8}
.pr-price{margin:12px 0 4px;font-size:2.2rem;font-weight:800;letter-spacing:-.03em;color:#0f172a}
.pr-hot .pr-price{color:#fff}
.pr-price span{font-size:.85rem;font-weight:500;letter-spacing:0;color:#64748b}
.pr-per{font-size:.8rem;color:#64748b;margin:0 0 20px}
.pr-hot .pr-price span,.pr-hot .pr-per{color:#94a3b8}
.pr-list{margin:0 0 24px}
.pr-list li{font-size:.86rem;padding:7px 0 7px 26px;position:relative;color:#475569}
.pr-hot .pr-list li{color:#cbd5e1}
.pr-list li::before{content:"✓";content:"✓"/"";position:absolute;left:0;top:7px;width:17px;height:17px;border-radius:50%;background:#dcfce7;color:#16a34a;font-size:.7rem;font-weight:800;display:flex;align-items:center;justify-content:center}
.pr-hot .pr-list li::before{background:#164e63;color:#22d3ee}
.pr-list li.pr-no{color:#64748b;text-decoration:line-through}
.pr-hot .pr-list li.pr-no{color:#b6bfcc}
.pr-list li.pr-no::before{content:"–";content:"–"/"";background:#f1f5f9;color:#64748b}
.pr-go{--bs-btn-padding-y:12px;--bs-btn-font-size:.9rem;--bs-btn-font-weight:700;--bs-btn-border-radius:11px;
  --bs-btn-color:#0f172a;--bs-btn-bg:#fff;--bs-btn-border-color:#8391a5;--bs-btn-hover-color:#0f172a;--bs-btn-hover-bg:#f1f5f9;--bs-btn-hover-border-color:#8391a5;
  --bs-btn-active-color:#0f172a;--bs-btn-active-bg:#f1f5f9;--bs-btn-active-border-color:#8391a5;--bs-btn-focus-box-shadow:none;transition:background .15s,filter .15s}
.pr-hot .pr-go{--bs-btn-color:#082f36;--bs-btn-bg:#22d3ee;--bs-btn-border-color:#22d3ee;--bs-btn-hover-color:#082f36;--bs-btn-hover-bg:#22d3ee;--bs-btn-hover-border-color:#22d3ee;
  --bs-btn-active-color:#082f36;--bs-btn-active-bg:#22d3ee;--bs-btn-active-border-color:#22d3ee}
.pr-hot .pr-go:hover{filter:brightness(1.1)}
.pr-go:focus-visible{outline:3px solid #0f172a;outline-offset:2px}
.pr-hot .pr-go:focus-visible{outline-color:#22d3ee}
@media (prefers-reduced-motion:reduce){.pr-card,.pr-go{transition:none}.pr-card:hover{transform:none}.pr-card.pr-hot:hover{transform:scale(1.04)}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div class="flex flex-wrap items-center justify-center gap-[22px]">
  <article class="relative w-[260px] rounded-[18px] border border-[#e5e9f0] bg-white px-[26px] py-[30px] transition-[translate,box-shadow] duration-[180ms] hover:-translate-y-[5px] hover:shadow-[0_22px_44px_-18px_rgba(15,23,42,.18)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
    <h2 class="text-[.95rem] font-bold tracking-[.02em] text-[#334155]">Starter</h2>
    <p class="mt-3 mb-1 text-[2.2rem] font-extrabold tracking-[-.03em] text-[#0f172a]">$0<span class="text-[.85rem] font-medium tracking-normal text-[#64748b]">/mo</span></p>
    <p class="mb-5 text-[.8rem] text-[#64748b]">For side projects</p>
    <ul class="mb-6 text-[.86rem] text-[#475569] [&>li]:relative [&>li]:py-[7px] [&>li]:pl-[26px] [&>li]:before:absolute [&>li]:before:top-[7px] [&>li]:before:left-0 [&>li]:before:flex [&>li]:before:size-[17px] [&>li]:before:items-center [&>li]:before:justify-center [&>li]:before:rounded-full [&>li]:before:bg-[#dcfce7] [&>li]:before:text-[.7rem] [&>li]:before:font-extrabold [&>li]:before:text-[#16a34a] [&>li]:before:content-['✓'] [&>li]:before:[content:'✓'_/_'']">
      <li>1 project</li>
      <li>Community support</li>
      <li class="text-[#64748b] line-through before:bg-[#f1f5f9]! before:text-[#64748b]! before:content-['–']! before:[content:'–'_/_'']!"><span class="sr-only">Not included: </span>Custom domain</li>
      <li class="text-[#64748b] line-through before:bg-[#f1f5f9]! before:text-[#64748b]! before:content-['–']! before:[content:'–'_/_'']!"><span class="sr-only">Not included: </span>Team seats</li>
    </ul>
    <button type="button" class="w-full cursor-pointer rounded-[11px] border border-[#8391a5] bg-white p-3 text-[.9rem] font-bold text-[#0f172a] transition-[background-color] duration-150 hover:bg-[#f1f5f9] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a] motion-reduce:transition-none">Start free</button>
  </article>
  <article class="relative w-[260px] scale-[1.04] rounded-[18px] border border-[#0f172a] bg-[#0f172a] px-[26px] py-[30px] text-[#e2e8f0] transition-[translate,box-shadow] duration-[180ms] hover:-translate-y-[5px] hover:shadow-[0_22px_44px_-18px_rgba(15,23,42,.18)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
    <p class="absolute -top-3 left-1/2 -translate-x-1/2 rounded-full bg-[#22d3ee] px-[13px] py-[5px] text-[.68rem] font-extrabold tracking-[.07em] whitespace-nowrap text-[#082f36] uppercase">Most popular</p>
    <h2 class="text-[.95rem] font-bold tracking-[.02em] text-[#94a3b8]">Pro</h2>
    <p class="mt-3 mb-1 text-[2.2rem] font-extrabold tracking-[-.03em] text-white">$19<span class="text-[.85rem] font-medium tracking-normal text-[#94a3b8]">/mo</span></p>
    <p class="mb-5 text-[.8rem] text-[#94a3b8]">For growing products</p>
    <ul class="mb-6 text-[.86rem] text-[#cbd5e1] [&>li]:relative [&>li]:py-[7px] [&>li]:pl-[26px] [&>li]:before:absolute [&>li]:before:top-[7px] [&>li]:before:left-0 [&>li]:before:flex [&>li]:before:size-[17px] [&>li]:before:items-center [&>li]:before:justify-center [&>li]:before:rounded-full [&>li]:before:bg-[#164e63] [&>li]:before:text-[.7rem] [&>li]:before:font-extrabold [&>li]:before:text-[#22d3ee] [&>li]:before:content-['✓'] [&>li]:before:[content:'✓'_/_'']">
      <li>Unlimited projects</li>
      <li>Priority support</li>
      <li>Custom domain</li>
      <li class="text-[#b6bfcc] line-through before:bg-[#f1f5f9]! before:text-[#64748b]! before:content-['–']! before:[content:'–'_/_'']!"><span class="sr-only">Not included: </span>Team seats</li>
    </ul>
    <button type="button" class="w-full cursor-pointer rounded-[11px] bg-[#22d3ee] p-3 text-[.9rem] font-bold text-[#082f36] transition-[filter] duration-150 hover:brightness-110 focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#22d3ee] motion-reduce:transition-none">Go Pro</button>
  </article>
  <article class="relative w-[260px] rounded-[18px] border border-[#e5e9f0] bg-white px-[26px] py-[30px] transition-[translate,box-shadow] duration-[180ms] hover:-translate-y-[5px] hover:shadow-[0_22px_44px_-18px_rgba(15,23,42,.18)] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
    <h2 class="text-[.95rem] font-bold tracking-[.02em] text-[#334155]">Team</h2>
    <p class="mt-3 mb-1 text-[2.2rem] font-extrabold tracking-[-.03em] text-[#0f172a]">$49<span class="text-[.85rem] font-medium tracking-normal text-[#64748b]">/mo</span></p>
    <p class="mb-5 text-[.8rem] text-[#64748b]">For whole teams</p>
    <ul class="mb-6 text-[.86rem] text-[#475569] [&>li]:relative [&>li]:py-[7px] [&>li]:pl-[26px] [&>li]:before:absolute [&>li]:before:top-[7px] [&>li]:before:left-0 [&>li]:before:flex [&>li]:before:size-[17px] [&>li]:before:items-center [&>li]:before:justify-center [&>li]:before:rounded-full [&>li]:before:bg-[#dcfce7] [&>li]:before:text-[.7rem] [&>li]:before:font-extrabold [&>li]:before:text-[#16a34a] [&>li]:before:content-['✓'] [&>li]:before:[content:'✓'_/_'']">
      <li>Unlimited projects</li>
      <li>Priority support</li>
      <li>Custom domain</li>
      <li>10 team seats</li>
    </ul>
    <button type="button" class="w-full cursor-pointer rounded-[11px] border border-[#8391a5] bg-white p-3 text-[.9rem] font-bold text-[#0f172a] transition-[background-color] duration-150 hover:bg-[#f1f5f9] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a] motion-reduce:transition-none">Start trial</button>
  </article>
</div>

About this set

A three-plan pricing row with Starter, Pro and Team cards. Each card has the plan name, a large monthly price, a one-line audience note, a feature list and a full-width call-to-action button. The middle plan is the featured one: it has a dark background, is scaled up four percent and wears a cyan Most popular pill that overlaps its top edge. Included features get a green tick and excluded ones a grey dash with the text struck through. The tick and dash are CSS ::before glyphs with empty alternative text, so they are not read aloud, and each excluded feature starts with visually hidden Not included text so screen reader users hear the difference that sighted users see from the strike-through. Use it on SaaS pricing pages or plan comparison sections; add or remove li elements to change the features. Cards lift on hover. The buttons are plain buttons with no behaviour, so turn them into links or wire them to your checkout. The Bootstrap version uses .card, .badge, .btn and a .row-cols-auto grid; the Tailwind version styles the list markers with before: utilities.

What’s included

  • Three plans with a dark, enlarged featured plan and a Most popular pill
  • Tick and dash markers as CSS glyphs with empty alt text
  • Excluded features announced with hidden Not included text
  • Full-width call-to-action button per plan
  • Hover lift that is turned off under prefers-reduced-motion

Accessibility

Each plan is an article headed by its plan name, and features are real lists. Excluded features are struck through visually and prefixed with visually hidden Not included text, and the decorative tick and dash glyphs have empty alt text. Grey captions and the outlined button border were darkened to meet contrast, buttons show a 3px focus outline, and the hover lift is disabled under prefers-reduced-motion.

Customise it

Change the featured card colours in the .pr-hot rules and the accent #22d3ee used by its pill, markers and button. In Bootstrap the featured surface is --bs-card-bg on .pr-hot and the buttons use --bs-btn-* variables on .pr-go; in Tailwind edit the bg- and text- utilities on the middle card.