@use 'sprucecss/scss/spruce' as *;
.pricing-block {
padding-block: spacer-clamp('xl', 'xxl');
&__inner {
display: flex;
flex-direction: column;
gap: spacer('l');
}
&__toggle {
display: flex;
margin-inline: auto;
max-inline-size: max-content;
}
&__note {
color: color('muted');
font-size: config('font-size-sm', $typography);
margin-block: 0;
text-align: center;
}
}
<section class="pricing-block" aria-labelledby="pricing-title" data-pricing-block>
<div class="container">
<div class="pricing-block__inner">
<header class="block-heading">
<p class="block-heading__eyebrow">Pricing</p>
<h2 class="block-heading__title" id="pricing-title">Simple pricing that grows with you</h2>
<p class="block-heading__text">Start for free. Upgrade when your team is ready.</p>
</header>
<fieldset class="segmented-control pricing-block__toggle">
<legend class="sr-only">Billing period</legend>
<label class="segmented-control__option">
<input class="segmented-control__input" type="radio" name="pricing-billing" value="monthly" checked>
<span>Monthly</span>
</label>
<label class="segmented-control__option">
<input class="segmented-control__input" type="radio" name="pricing-billing" value="yearly">
<span>Yearly <small class="segmented-control__hint">−20%</small></span>
</label>
</fieldset>
<div class="pricing-cards">
<article class="pricing-card" aria-labelledby="plan-starter">
<header class="pricing-card__header">
<h3 class="pricing-card__title" id="plan-starter">Starter</h3>
<p class="pricing-card__description">For side projects and trying things out.</p>
</header>
<p class="pricing-card__price"><span class="pricing-card__amount" data-monthly="0" data-yearly="0">$0</span> <span class="pricing-card__period">/ month</span></p>
<ul class="pricing-card__features" role="list">
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> 1 project</li>
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> Community support</li>
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> Basic analytics</li>
</ul>
<a class="btn btn--outline-primary btn--block pricing-card__action" href="#">Get started</a>
</article>
<article class="pricing-card pricing-card--featured" aria-labelledby="plan-team">
<header class="pricing-card__header">
<span class="pricing-card__badge">Most popular</span>
<h3 class="pricing-card__title" id="plan-team">Team</h3>
<p class="pricing-card__description">For growing teams that ship every week.</p>
</header>
<p class="pricing-card__price"><span class="pricing-card__amount" data-monthly="29" data-yearly="23">$29</span> <span class="pricing-card__period">/ month</span></p>
<ul class="pricing-card__features" role="list">
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> Unlimited projects</li>
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> Priority support</li>
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> Advanced analytics</li>
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> Custom domains</li>
</ul>
<a class="btn btn--primary btn--block pricing-card__action" href="#">Start free trial</a>
</article>
<article class="pricing-card" aria-labelledby="plan-enterprise">
<header class="pricing-card__header">
<h3 class="pricing-card__title" id="plan-enterprise">Enterprise</h3>
<p class="pricing-card__description">For organizations with advanced needs.</p>
</header>
<p class="pricing-card__price"><span class="pricing-card__amount" data-monthly="99" data-yearly="79">$99</span> <span class="pricing-card__period">/ month</span></p>
<ul class="pricing-card__features" role="list">
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> Everything in Team</li>
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> SSO and audit logs</li>
<li><svg class="pricing-card__check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M20 6 9 17l-5-5"/></svg> Dedicated manager</li>
</ul>
<a class="btn btn--outline-primary btn--block pricing-card__action" href="#">Contact sales</a>
</article>
</div>
<p class="pricing-block__note">Prices in USD. Cancel anytime.</p>
<p class="sr-only" aria-live="polite" data-pricing-status></p>
</div>
</div>
</section>
(() => {
document.querySelectorAll('[data-pricing-block]').forEach((block) => {
const status = block.querySelector('[data-pricing-status]');
block.querySelectorAll('input[name="pricing-billing"]').forEach((input) => {
input.addEventListener('change', () => {
const isYearly = input.value === 'yearly';
block.querySelectorAll('.pricing-card__amount').forEach((amount) => {
amount.textContent = `$${isYearly ? amount.dataset.yearly : amount.dataset.monthly}`;
amount.nextElementSibling.textContent = isYearly ? '/ month, billed yearly' : '/ month';
});
status.textContent = isYearly ? 'Showing yearly prices.' : 'Showing monthly prices.';
});
});
});
})();