Three-Tier Pricing
The canonical Starter / Pro / Enterprise grid, with the middle tier promoted.
6 frameworksBeginner
One plan in a split card: the pitch on one side, the price panel on the other.
<!--
One plan, so there is nothing to compare and no grid to build. The layout
splits instead: the pitch and the feature list get the wide side, the price and
the CTA get a tinted panel of their own. The panel is what a returning visitor
scans for, so it stays a fixed, self-contained block rather than sitting at the
bottom of a column whose height depends on how many features you listed.
Source order puts the pitch first - on a narrow screen the panel stacks under
it, which is also the order it should be read in.
-->
<article class="solo" aria-labelledby="solo-name">
<div class="solo__body">
<p class="solo__kicker">One plan</p>
<h3 class="solo__name" id="solo-name">Pro</h3>
<p class="solo__copy">
Everything you need to ship, at one price. No seat maths, no feature gates,
no sales call.
</p>
<p class="solo__included">What's included</p>
<ul class="solo__features">
<li class="solo__feature">
<svg class="solo__check" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.8 3.8 6.8-6.8a1 1 0 0 1 1.4 0Z" />
</svg>
Unlimited projects
</li>
<li class="solo__feature">
<svg class="solo__check" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.8 3.8 6.8-6.8a1 1 0 0 1 1.4 0Z" />
</svg>
Unlimited team members
</li>
<li class="solo__feature">
<svg class="solo__check" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.8 3.8 6.8-6.8a1 1 0 0 1 1.4 0Z" />
</svg>
100 GB storage
</li>
<li class="solo__feature">
<svg class="solo__check" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.8 3.8 6.8-6.8a1 1 0 0 1 1.4 0Z" />
</svg>
Priority support
</li>
<li class="solo__feature">
<svg class="solo__check" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.8 3.8 6.8-6.8a1 1 0 0 1 1.4 0Z" />
</svg>
SSO and audit log
</li>
<li class="solo__feature">
<svg class="solo__check" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.8 3.8 6.8-6.8a1 1 0 0 1 1.4 0Z" />
</svg>
99.9% uptime SLA
</li>
</ul>
</div>
<div class="solo__panel">
<p class="solo__panel-label">Flat monthly rate</p>
<p class="solo__price">
<span class="solo__amount">$19</span>
<span class="solo__period">/month</span>
</p>
<a class="solo__cta" href="#">Get access</a>
<p class="solo__note">Invoices and VAT receipts included. Cancel any time.</p>
</div>
</article>| Prop | Type | Default | Description |
|---|---|---|---|
namerequired | string | - | Plan name shown as the heading. |
pricerequired | string | - | Amount to display. |
period | string | '/month' | Billing period shown beside the price. |
copyrequired | string | - | Body text shown under the title. |
featuresrequired | string[] | - | List of feature strings. |
ctaLabel | string | 'Get access' | Call-to-action button text. |
ctaHref | string | '#' | Destination for the call-to-action link. |
className | string | - | Additional classes merged onto the root element. |
With one plan there is nothing to compare, so the usual vertical card wastes the width it has. This splits instead - pitch and features take the wide side, price and CTA get a tinted panel that stays a fixed, self-contained block a returning visitor can scan for, rather than drifting down the page as the feature list grows. The grid is `1.6fr 1fr` rather than `2fr 1fr` for one reason: the panel must stay wide enough that "$19" and "/month" share a line, because a wrapped period reads as a different price. Source order puts the pitch first, which is also the order it stacks and should be read in. `price` is a pre-formatted string, currency symbol and all - formatting belongs to the caller, the only layer that knows the visitor’s locale.