21 CSS Pricing Sections17 / 21
Currency Switcher
A pure-CSS currency switcher (USD / EUR / GBP) using hidden radios + :has() to swap every visible price across all three tiers. Burgundy on cream — the wine-merchant / boutique-software aesthetic.
Published
The code
<section class="ps-17" aria-label="Pricing">
<header class="ps-17__head">
<h2>Pricing in your currency.</h2>
<p>Pay where you live, with the rate fixed at billing time.</p>
<fieldset class="ps-17__tabs">
<legend class="ps-17__sr">Currency</legend>
<input type="radio" name="ps-17__c" id="ps-17__usd" checked />
<label for="ps-17__usd">USD</label>
<input type="radio" name="ps-17__c" id="ps-17__eur" />
<label for="ps-17__eur">EUR</label>
<input type="radio" name="ps-17__c" id="ps-17__gbp" />
<label for="ps-17__gbp">GBP</label>
</fieldset>
</header>
<div class="ps-17__grid">
<article class="ps-17__card">
<h3>Petit</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$12</span><span class="ps-17__eur">€11</span
><span class="ps-17__gbp">£10</span>
<em>/month</em>
</div>
<ul>
<li>Solo cellar</li>
<li>3 bottles tracked</li>
<li>Email reminders</li>
</ul>
<a class="ps-17__cta" href="#petit">Choose Petit</a>
</article>
<article class="ps-17__card ps-17__best">
<span class="ps-17__pill">Sommelier’s pick</span>
<h3>Reserve</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$36</span><span class="ps-17__eur">€33</span
><span class="ps-17__gbp">£28</span>
<em>/month</em>
</div>
<ul>
<li>Full cellar</li>
<li>Unlimited bottles</li>
<li>Tasting notes</li>
<li>Pairing engine</li>
</ul>
<a class="ps-17__cta ps-17__cta-pri" href="#reserve">Choose Reserve</a>
</article>
<article class="ps-17__card">
<h3>Grand Cru</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$96</span><span class="ps-17__eur">€88</span
><span class="ps-17__gbp">£76</span>
<em>/month</em>
</div>
<ul>
<li>Multi-cellar</li>
<li>Insurance valuation</li>
<li>White-glove setup</li>
</ul>
<a class="ps-17__cta" href="#grand">Talk to us</a>
</article>
</div>
</section><section class="ps-17" aria-label="Pricing">
<header class="ps-17__head">
<h2>Pricing in your currency.</h2>
<p>Pay where you live, with the rate fixed at billing time.</p>
<fieldset class="ps-17__tabs">
<legend class="ps-17__sr">Currency</legend>
<input type="radio" name="ps-17__c" id="ps-17__usd" checked />
<label for="ps-17__usd">USD</label>
<input type="radio" name="ps-17__c" id="ps-17__eur" />
<label for="ps-17__eur">EUR</label>
<input type="radio" name="ps-17__c" id="ps-17__gbp" />
<label for="ps-17__gbp">GBP</label>
</fieldset>
</header>
<div class="ps-17__grid">
<article class="ps-17__card">
<h3>Petit</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$12</span><span class="ps-17__eur">€11</span
><span class="ps-17__gbp">£10</span>
<em>/month</em>
</div>
<ul>
<li>Solo cellar</li>
<li>3 bottles tracked</li>
<li>Email reminders</li>
</ul>
<a class="ps-17__cta" href="#petit">Choose Petit</a>
</article>
<article class="ps-17__card ps-17__best">
<span class="ps-17__pill">Sommelier’s pick</span>
<h3>Reserve</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$36</span><span class="ps-17__eur">€33</span
><span class="ps-17__gbp">£28</span>
<em>/month</em>
</div>
<ul>
<li>Full cellar</li>
<li>Unlimited bottles</li>
<li>Tasting notes</li>
<li>Pairing engine</li>
</ul>
<a class="ps-17__cta ps-17__cta-pri" href="#reserve">Choose Reserve</a>
</article>
<article class="ps-17__card">
<h3>Grand Cru</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$96</span><span class="ps-17__eur">€88</span
><span class="ps-17__gbp">£76</span>
<em>/month</em>
</div>
<ul>
<li>Multi-cellar</li>
<li>Insurance valuation</li>
<li>White-glove setup</li>
</ul>
<a class="ps-17__cta" href="#grand">Talk to us</a>
</article>
</div>
</section>.ps-17 {
padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
width: 100%;
min-height: 100vh;
background: #faf6ee;
color: #2a0a14;
font-family: 'Inter', system-ui, sans-serif;
}
.ps-17__head {
text-align: center;
margin-bottom: clamp(24px, 4vw, 36px);
}
.ps-17__head h2 {
font-family: 'Playfair Display', Georgia, serif;
font-size: clamp(26px, 4vw, 38px);
font-weight: 700;
letter-spacing: -0.015em;
margin: 0 0 8px;
color: #6b1224;
}
.ps-17__head p {
color: #8a4555;
margin: 0 0 20px;
font-size: 14px;
}
.ps-17__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
}
.ps-17__tabs {
position: relative;
display: inline-grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border: 1.5px solid #6b1224;
border-radius: 999px;
padding: 3px;
background: #fff;
margin: 0;
}
.ps-17__tabs input[type="radio"] {
position: absolute;
opacity: 0;
pointer-events: none;
}
.ps-17__tabs label {
padding: 7px 22px;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.1em;
color: #8a4555;
cursor: pointer;
border-radius: 999px;
transition: color 0.18s, background 0.18s;
}
.ps-17__tabs input:checked + label {
background: #6b1224;
color: #faf6ee;
}
.ps-17__tabs input:focus-visible + label {
outline: 2px solid #6b1224;
outline-offset: 3px;
}
.ps-17__grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
max-width: 1000px;
margin: 0 auto;
align-items: center;
}
.ps-17__card {
position: relative;
background: #fff;
border: 1px solid #e7d8c8;
border-radius: 8px;
padding: 26px 22px 22px;
display: flex;
flex-direction: column;
}
.ps-17__best {
background: #6b1224;
color: #faf6ee;
border: 0;
transform: scale(1.04);
box-shadow: 0 18px 44px rgba(107,18,36,0.3);
}
.ps-17__pill {
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
background: #faf6ee;
color: #6b1224;
font-family: 'JetBrains Mono', monospace;
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
padding: 4px 11px;
border: 1.5px solid #6b1224;
border-radius: 999px;
}
.ps-17__card h3 {
font-family: 'Playfair Display', Georgia, serif;
font-size: 22px;
font-weight: 700;
margin: 0 0 12px;
color: #6b1224;
font-style: italic;
}
.ps-17__best h3 {
color: #faf6ee;
}
.ps-17__price {
display: flex;
align-items: baseline;
gap: 4px;
margin-bottom: 18px;
padding-bottom: 18px;
border-bottom: 1px dashed #e7d8c8;
font-size: 38px;
font-weight: 800;
letter-spacing: -0.03em;
}
.ps-17__best .ps-17__price {
border-bottom-color: rgba(250,246,238,0.25);
}
.ps-17__price em {
font-size: 13px;
font-weight: 500;
color: #8a4555;
font-style: normal;
margin-left: 6px;
}
.ps-17__best .ps-17__price em {
color: rgba(250,246,238,0.7);
}
.ps-17__price > span {
display: none;
}
.ps-17:has(#ps-17__usd:checked) .ps-17__usd,
.ps-17:has(#ps-17__eur:checked) .ps-17__eur,
.ps-17:has(#ps-17__gbp:checked) .ps-17__gbp {
display: inline;
}
.ps-17__card ul {
list-style: none;
padding: 0;
margin: 0 0 20px;
flex: 1;
font-size: 13.5px;
line-height: 1.95;
color: #4a2030;
}
.ps-17__best ul {
color: rgba(250,246,238,0.85);
}
.ps-17__card ul li::before {
content: '◆';
color: #6b1224;
display: inline-block;
width: 20px;
font-size: 9px;
}
.ps-17__best ul li::before {
color: #faf6ee;
}
.ps-17__cta {
display: block;
text-align: center;
padding: 11px 16px;
border-radius: 6px;
text-decoration: none;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
border: 1.5px solid currentColor;
color: #6b1224;
background: transparent;
transition: background 0.18s, color 0.18s;
}
.ps-17__best .ps-17__cta {
color: #faf6ee;
}
.ps-17__cta-pri {
background: #faf6ee;
color: #6b1224 !important;
border-color: #faf6ee;
}
.ps-17__cta:hover {
background: #6b1224;
color: #faf6ee;
border-color: #6b1224;
}
.ps-17__cta-pri:hover {
background: transparent;
color: #faf6ee !important;
border-color: #faf6ee;
}
.ps-17__cta:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
@media (max-width: 820px) {
.ps-17__grid {
grid-template-columns: 1fr;
max-width: 380px;
}
.ps-17__best {
transform: none;
}
}
@media (prefers-reduced-motion: reduce) {
.ps-17__tabs label,
.ps-17__cta {
transition: none;
}
}.ps-17 {
padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
width: 100%;
min-height: 100vh;
background: #faf6ee;
color: #2a0a14;
font-family: 'Inter', system-ui, sans-serif;
}
.ps-17__head {
text-align: center;
margin-bottom: clamp(24px, 4vw, 36px);
}
.ps-17__head h2 {
font-family: 'Playfair Display', Georgia, serif;
font-size: clamp(26px, 4vw, 38px);
font-weight: 700;
letter-spacing: -0.015em;
margin: 0 0 8px;
color: #6b1224;
}
.ps-17__head p {
color: #8a4555;
margin: 0 0 20px;
font-size: 14px;
}
.ps-17__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
}
.ps-17__tabs {
position: relative;
display: inline-grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border: 1.5px solid #6b1224;
border-radius: 999px;
padding: 3px;
background: #fff;
margin: 0;
}
.ps-17__tabs input[type="radio"] {
position: absolute;
opacity: 0;
pointer-events: none;
}
.ps-17__tabs label {
padding: 7px 22px;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.1em;
color: #8a4555;
cursor: pointer;
border-radius: 999px;
transition: color 0.18s, background 0.18s;
}
.ps-17__tabs input:checked + label {
background: #6b1224;
color: #faf6ee;
}
.ps-17__tabs input:focus-visible + label {
outline: 2px solid #6b1224;
outline-offset: 3px;
}
.ps-17__grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
max-width: 1000px;
margin: 0 auto;
align-items: center;
}
.ps-17__card {
position: relative;
background: #fff;
border: 1px solid #e7d8c8;
border-radius: 8px;
padding: 26px 22px 22px;
display: flex;
flex-direction: column;
}
.ps-17__best {
background: #6b1224;
color: #faf6ee;
border: 0;
transform: scale(1.04);
box-shadow: 0 18px 44px rgba(107,18,36,0.3);
}
.ps-17__pill {
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
background: #faf6ee;
color: #6b1224;
font-family: 'JetBrains Mono', monospace;
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
padding: 4px 11px;
border: 1.5px solid #6b1224;
border-radius: 999px;
}
.ps-17__card h3 {
font-family: 'Playfair Display', Georgia, serif;
font-size: 22px;
font-weight: 700;
margin: 0 0 12px;
color: #6b1224;
font-style: italic;
}
.ps-17__best h3 {
color: #faf6ee;
}
.ps-17__price {
display: flex;
align-items: baseline;
gap: 4px;
margin-bottom: 18px;
padding-bottom: 18px;
border-bottom: 1px dashed #e7d8c8;
font-size: 38px;
font-weight: 800;
letter-spacing: -0.03em;
}
.ps-17__best .ps-17__price {
border-bottom-color: rgba(250,246,238,0.25);
}
.ps-17__price em {
font-size: 13px;
font-weight: 500;
color: #8a4555;
font-style: normal;
margin-left: 6px;
}
.ps-17__best .ps-17__price em {
color: rgba(250,246,238,0.7);
}
.ps-17__price > span {
display: none;
}
.ps-17:has(#ps-17__usd:checked) .ps-17__usd,
.ps-17:has(#ps-17__eur:checked) .ps-17__eur,
.ps-17:has(#ps-17__gbp:checked) .ps-17__gbp {
display: inline;
}
.ps-17__card ul {
list-style: none;
padding: 0;
margin: 0 0 20px;
flex: 1;
font-size: 13.5px;
line-height: 1.95;
color: #4a2030;
}
.ps-17__best ul {
color: rgba(250,246,238,0.85);
}
.ps-17__card ul li::before {
content: '◆';
color: #6b1224;
display: inline-block;
width: 20px;
font-size: 9px;
}
.ps-17__best ul li::before {
color: #faf6ee;
}
.ps-17__cta {
display: block;
text-align: center;
padding: 11px 16px;
border-radius: 6px;
text-decoration: none;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
border: 1.5px solid currentColor;
color: #6b1224;
background: transparent;
transition: background 0.18s, color 0.18s;
}
.ps-17__best .ps-17__cta {
color: #faf6ee;
}
.ps-17__cta-pri {
background: #faf6ee;
color: #6b1224 !important;
border-color: #faf6ee;
}
.ps-17__cta:hover {
background: #6b1224;
color: #faf6ee;
border-color: #6b1224;
}
.ps-17__cta-pri:hover {
background: transparent;
color: #faf6ee !important;
border-color: #faf6ee;
}
.ps-17__cta:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
@media (max-width: 820px) {
.ps-17__grid {
grid-template-columns: 1fr;
max-width: 380px;
}
.ps-17__best {
transform: none;
}
}
@media (prefers-reduced-motion: reduce) {
.ps-17__tabs label,
.ps-17__cta {
transition: none;
}
}Here's a working CSS Pricing Section from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Currency Switcher
Source: https://codefronts.com/layouts/css-pricing-sections/currency-switcher/
A pure-CSS currency switcher (USD / EUR / GBP) using hidden radios + :has() to swap every visible price across all three tiers. Burgundy on cream — the wine-merchant / boutique-software aesthetic.
## HTML
```html
<section class="ps-17" aria-label="Pricing">
<header class="ps-17__head">
<h2>Pricing in your currency.</h2>
<p>Pay where you live, with the rate fixed at billing time.</p>
<fieldset class="ps-17__tabs">
<legend class="ps-17__sr">Currency</legend>
<input type="radio" name="ps-17__c" id="ps-17__usd" checked />
<label for="ps-17__usd">USD</label>
<input type="radio" name="ps-17__c" id="ps-17__eur" />
<label for="ps-17__eur">EUR</label>
<input type="radio" name="ps-17__c" id="ps-17__gbp" />
<label for="ps-17__gbp">GBP</label>
</fieldset>
</header>
<div class="ps-17__grid">
<article class="ps-17__card">
<h3>Petit</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$12</span><span class="ps-17__eur">€11</span
><span class="ps-17__gbp">£10</span>
<em>/month</em>
</div>
<ul>
<li>Solo cellar</li>
<li>3 bottles tracked</li>
<li>Email reminders</li>
</ul>
<a class="ps-17__cta" href="#petit">Choose Petit</a>
</article>
<article class="ps-17__card ps-17__best">
<span class="ps-17__pill">Sommelier’s pick</span>
<h3>Reserve</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$36</span><span class="ps-17__eur">€33</span
><span class="ps-17__gbp">£28</span>
<em>/month</em>
</div>
<ul>
<li>Full cellar</li>
<li>Unlimited bottles</li>
<li>Tasting notes</li>
<li>Pairing engine</li>
</ul>
<a class="ps-17__cta ps-17__cta-pri" href="#reserve">Choose Reserve</a>
</article>
<article class="ps-17__card">
<h3>Grand Cru</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$96</span><span class="ps-17__eur">€88</span
><span class="ps-17__gbp">£76</span>
<em>/month</em>
</div>
<ul>
<li>Multi-cellar</li>
<li>Insurance valuation</li>
<li>White-glove setup</li>
</ul>
<a class="ps-17__cta" href="#grand">Talk to us</a>
</article>
</div>
</section>
```
## CSS
```css
.ps-17 {
padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
width: 100%;
min-height: 100vh;
background: #faf6ee;
color: #2a0a14;
font-family: 'Inter', system-ui, sans-serif;
}
.ps-17__head {
text-align: center;
margin-bottom: clamp(24px, 4vw, 36px);
}
.ps-17__head h2 {
font-family: 'Playfair Display', Georgia, serif;
font-size: clamp(26px, 4vw, 38px);
font-weight: 700;
letter-spacing: -0.015em;
margin: 0 0 8px;
color: #6b1224;
}
.ps-17__head p {
color: #8a4555;
margin: 0 0 20px;
font-size: 14px;
}
.ps-17__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
}
.ps-17__tabs {
position: relative;
display: inline-grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border: 1.5px solid #6b1224;
border-radius: 999px;
padding: 3px;
background: #fff;
margin: 0;
}
.ps-17__tabs input[type="radio"] {
position: absolute;
opacity: 0;
pointer-events: none;
}
.ps-17__tabs label {
padding: 7px 22px;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.1em;
color: #8a4555;
cursor: pointer;
border-radius: 999px;
transition: color 0.18s, background 0.18s;
}
.ps-17__tabs input:checked + label {
background: #6b1224;
color: #faf6ee;
}
.ps-17__tabs input:focus-visible + label {
outline: 2px solid #6b1224;
outline-offset: 3px;
}
.ps-17__grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
max-width: 1000px;
margin: 0 auto;
align-items: center;
}
.ps-17__card {
position: relative;
background: #fff;
border: 1px solid #e7d8c8;
border-radius: 8px;
padding: 26px 22px 22px;
display: flex;
flex-direction: column;
}
.ps-17__best {
background: #6b1224;
color: #faf6ee;
border: 0;
transform: scale(1.04);
box-shadow: 0 18px 44px rgba(107,18,36,0.3);
}
.ps-17__pill {
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
background: #faf6ee;
color: #6b1224;
font-family: 'JetBrains Mono', monospace;
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
padding: 4px 11px;
border: 1.5px solid #6b1224;
border-radius: 999px;
}
.ps-17__card h3 {
font-family: 'Playfair Display', Georgia, serif;
font-size: 22px;
font-weight: 700;
margin: 0 0 12px;
color: #6b1224;
font-style: italic;
}
.ps-17__best h3 {
color: #faf6ee;
}
.ps-17__price {
display: flex;
align-items: baseline;
gap: 4px;
margin-bottom: 18px;
padding-bottom: 18px;
border-bottom: 1px dashed #e7d8c8;
font-size: 38px;
font-weight: 800;
letter-spacing: -0.03em;
}
.ps-17__best .ps-17__price {
border-bottom-color: rgba(250,246,238,0.25);
}
.ps-17__price em {
font-size: 13px;
font-weight: 500;
color: #8a4555;
font-style: normal;
margin-left: 6px;
}
.ps-17__best .ps-17__price em {
color: rgba(250,246,238,0.7);
}
.ps-17__price > span {
display: none;
}
.ps-17:has(#ps-17__usd:checked) .ps-17__usd,
.ps-17:has(#ps-17__eur:checked) .ps-17__eur,
.ps-17:has(#ps-17__gbp:checked) .ps-17__gbp {
display: inline;
}
.ps-17__card ul {
list-style: none;
padding: 0;
margin: 0 0 20px;
flex: 1;
font-size: 13.5px;
line-height: 1.95;
color: #4a2030;
}
.ps-17__best ul {
color: rgba(250,246,238,0.85);
}
.ps-17__card ul li::before {
content: '◆';
color: #6b1224;
display: inline-block;
width: 20px;
font-size: 9px;
}
.ps-17__best ul li::before {
color: #faf6ee;
}
.ps-17__cta {
display: block;
text-align: center;
padding: 11px 16px;
border-radius: 6px;
text-decoration: none;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
border: 1.5px solid currentColor;
color: #6b1224;
background: transparent;
transition: background 0.18s, color 0.18s;
}
.ps-17__best .ps-17__cta {
color: #faf6ee;
}
.ps-17__cta-pri {
background: #faf6ee;
color: #6b1224 !important;
border-color: #faf6ee;
}
.ps-17__cta:hover {
background: #6b1224;
color: #faf6ee;
border-color: #6b1224;
}
.ps-17__cta-pri:hover {
background: transparent;
color: #faf6ee !important;
border-color: #faf6ee;
}
.ps-17__cta:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
@media (max-width: 820px) {
.ps-17__grid {
grid-template-columns: 1fr;
max-width: 380px;
}
.ps-17__best {
transform: none;
}
}
@media (prefers-reduced-motion: reduce) {
.ps-17__tabs label,
.ps-17__cta {
transition: none;
}
}
```Here's a working CSS Pricing Section from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Currency Switcher
Source: https://codefronts.com/layouts/css-pricing-sections/currency-switcher/
A pure-CSS currency switcher (USD / EUR / GBP) using hidden radios + :has() to swap every visible price across all three tiers. Burgundy on cream — the wine-merchant / boutique-software aesthetic.
## HTML
```html
<section class="ps-17" aria-label="Pricing">
<header class="ps-17__head">
<h2>Pricing in your currency.</h2>
<p>Pay where you live, with the rate fixed at billing time.</p>
<fieldset class="ps-17__tabs">
<legend class="ps-17__sr">Currency</legend>
<input type="radio" name="ps-17__c" id="ps-17__usd" checked />
<label for="ps-17__usd">USD</label>
<input type="radio" name="ps-17__c" id="ps-17__eur" />
<label for="ps-17__eur">EUR</label>
<input type="radio" name="ps-17__c" id="ps-17__gbp" />
<label for="ps-17__gbp">GBP</label>
</fieldset>
</header>
<div class="ps-17__grid">
<article class="ps-17__card">
<h3>Petit</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$12</span><span class="ps-17__eur">€11</span
><span class="ps-17__gbp">£10</span>
<em>/month</em>
</div>
<ul>
<li>Solo cellar</li>
<li>3 bottles tracked</li>
<li>Email reminders</li>
</ul>
<a class="ps-17__cta" href="#petit">Choose Petit</a>
</article>
<article class="ps-17__card ps-17__best">
<span class="ps-17__pill">Sommelier’s pick</span>
<h3>Reserve</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$36</span><span class="ps-17__eur">€33</span
><span class="ps-17__gbp">£28</span>
<em>/month</em>
</div>
<ul>
<li>Full cellar</li>
<li>Unlimited bottles</li>
<li>Tasting notes</li>
<li>Pairing engine</li>
</ul>
<a class="ps-17__cta ps-17__cta-pri" href="#reserve">Choose Reserve</a>
</article>
<article class="ps-17__card">
<h3>Grand Cru</h3>
<div class="ps-17__price">
<span class="ps-17__usd">$96</span><span class="ps-17__eur">€88</span
><span class="ps-17__gbp">£76</span>
<em>/month</em>
</div>
<ul>
<li>Multi-cellar</li>
<li>Insurance valuation</li>
<li>White-glove setup</li>
</ul>
<a class="ps-17__cta" href="#grand">Talk to us</a>
</article>
</div>
</section>
```
## CSS
```css
.ps-17 {
padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
width: 100%;
min-height: 100vh;
background: #faf6ee;
color: #2a0a14;
font-family: 'Inter', system-ui, sans-serif;
}
.ps-17__head {
text-align: center;
margin-bottom: clamp(24px, 4vw, 36px);
}
.ps-17__head h2 {
font-family: 'Playfair Display', Georgia, serif;
font-size: clamp(26px, 4vw, 38px);
font-weight: 700;
letter-spacing: -0.015em;
margin: 0 0 8px;
color: #6b1224;
}
.ps-17__head p {
color: #8a4555;
margin: 0 0 20px;
font-size: 14px;
}
.ps-17__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
}
.ps-17__tabs {
position: relative;
display: inline-grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border: 1.5px solid #6b1224;
border-radius: 999px;
padding: 3px;
background: #fff;
margin: 0;
}
.ps-17__tabs input[type="radio"] {
position: absolute;
opacity: 0;
pointer-events: none;
}
.ps-17__tabs label {
padding: 7px 22px;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.1em;
color: #8a4555;
cursor: pointer;
border-radius: 999px;
transition: color 0.18s, background 0.18s;
}
.ps-17__tabs input:checked + label {
background: #6b1224;
color: #faf6ee;
}
.ps-17__tabs input:focus-visible + label {
outline: 2px solid #6b1224;
outline-offset: 3px;
}
.ps-17__grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
max-width: 1000px;
margin: 0 auto;
align-items: center;
}
.ps-17__card {
position: relative;
background: #fff;
border: 1px solid #e7d8c8;
border-radius: 8px;
padding: 26px 22px 22px;
display: flex;
flex-direction: column;
}
.ps-17__best {
background: #6b1224;
color: #faf6ee;
border: 0;
transform: scale(1.04);
box-shadow: 0 18px 44px rgba(107,18,36,0.3);
}
.ps-17__pill {
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
background: #faf6ee;
color: #6b1224;
font-family: 'JetBrains Mono', monospace;
font-size: 10.5px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
padding: 4px 11px;
border: 1.5px solid #6b1224;
border-radius: 999px;
}
.ps-17__card h3 {
font-family: 'Playfair Display', Georgia, serif;
font-size: 22px;
font-weight: 700;
margin: 0 0 12px;
color: #6b1224;
font-style: italic;
}
.ps-17__best h3 {
color: #faf6ee;
}
.ps-17__price {
display: flex;
align-items: baseline;
gap: 4px;
margin-bottom: 18px;
padding-bottom: 18px;
border-bottom: 1px dashed #e7d8c8;
font-size: 38px;
font-weight: 800;
letter-spacing: -0.03em;
}
.ps-17__best .ps-17__price {
border-bottom-color: rgba(250,246,238,0.25);
}
.ps-17__price em {
font-size: 13px;
font-weight: 500;
color: #8a4555;
font-style: normal;
margin-left: 6px;
}
.ps-17__best .ps-17__price em {
color: rgba(250,246,238,0.7);
}
.ps-17__price > span {
display: none;
}
.ps-17:has(#ps-17__usd:checked) .ps-17__usd,
.ps-17:has(#ps-17__eur:checked) .ps-17__eur,
.ps-17:has(#ps-17__gbp:checked) .ps-17__gbp {
display: inline;
}
.ps-17__card ul {
list-style: none;
padding: 0;
margin: 0 0 20px;
flex: 1;
font-size: 13.5px;
line-height: 1.95;
color: #4a2030;
}
.ps-17__best ul {
color: rgba(250,246,238,0.85);
}
.ps-17__card ul li::before {
content: '◆';
color: #6b1224;
display: inline-block;
width: 20px;
font-size: 9px;
}
.ps-17__best ul li::before {
color: #faf6ee;
}
.ps-17__cta {
display: block;
text-align: center;
padding: 11px 16px;
border-radius: 6px;
text-decoration: none;
font-size: 13px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
border: 1.5px solid currentColor;
color: #6b1224;
background: transparent;
transition: background 0.18s, color 0.18s;
}
.ps-17__best .ps-17__cta {
color: #faf6ee;
}
.ps-17__cta-pri {
background: #faf6ee;
color: #6b1224 !important;
border-color: #faf6ee;
}
.ps-17__cta:hover {
background: #6b1224;
color: #faf6ee;
border-color: #6b1224;
}
.ps-17__cta-pri:hover {
background: transparent;
color: #faf6ee !important;
border-color: #faf6ee;
}
.ps-17__cta:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
@media (max-width: 820px) {
.ps-17__grid {
grid-template-columns: 1fr;
max-width: 380px;
}
.ps-17__best {
transform: none;
}
}
@media (prefers-reduced-motion: reduce) {
.ps-17__tabs label,
.ps-17__cta {
transition: none;
}
}
```How this works
The whole saas pricing page is a single semantic <section> with a header (h2 + fieldset of three radios) and a display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)) tier row. The currency switcher pricing pattern is pure CSS: three hidden <input type="radio" name="ps-17__c"> siblings live inside .ps-17__tabs, and the container uses :has() to reveal the matching price spans — .ps-17:has(#ps-17__usd:checked) .ps-17__usd { display: inline } swaps every visible price across all three tiers without a byte of JavaScript. The recommended card gets transform: scale(1.04) plus a 0 18px 44px rgba(107,18,36,0.3) burgundy glow — visual anchoring for the Sommelier's pick tier.
The palette leans wine-merchant: cream #faf6ee base, deep burgundy #6b1224 as the primary, muted rose #8a4555 for supporting copy, and warm bone #e7d8c8 for the dashed price divider. Playfair Display serif italics on the tier names read as boutique-software; JetBrains Mono at letter-spacing: 0.1em on the currency labels signals engineered precision — the exact split editorial fintech and premium B2B SaaS use to look expensive without shouting. Prices sit at font-size: 38px; font-weight: 800; letter-spacing: -0.03em so the digits carry weight even at the 340px mobile breakpoint.
Why it converts: Baymard cross-border checkout research shows that displaying prices in the shopper's home currency cuts friction on international purchases by 30-50%, and shopper trust roughly doubles versus USD-only pricing. The pill-style tab group sits directly under the h2 where scanning eyes land first, so the multi-currency pricing decision happens before the tier decision. The dashed 1px dashed #e7d8c8 divider between price and feature list creates a Baymard-validated scan break that lifts feature-read rate on global SaaS pricing pages.
Make it yours
- Recolor to your brand by editing four values: the cream background (
#faf6ee), the burgundy primary (#6b1224), the muted rose support text (#8a4555), and the bone divider (#e7d8c8). Fintech tends to prefer navy#0b1e3fprimary; dev-tools SaaS swap to charcoal#1a1a1awith lime accent. - Add JPY, CAD, or AUD by duplicating the radio + label pair inside
.ps-17__tabs, adding a matching.ps-17__jpyspan inside each.ps-17__price, and appending.ps-17:has(#ps-17__jpy:checked) .ps-17__jpy { display: inline }. The:has()pattern scales to any number of currencies with zero JS. - Swap the serif italic Playfair Display for
'Fraunces'for a warmer editorial feel,'DM Serif Display'for boutique-SaaS, or'Inter'atfont-weight: 700if you want a modern-fintech look. Keep JetBrains Mono on the currency tabs — the mono/serif contrast is what makes the picker read as intentional. - Change the CTA shape:
border-radius: 6pxreads as classic-boutique. Bump toborder-radius: 999pxfor pill-style modern SaaS, or drop toborder-radius: 0for editorial. The outlinedborder: 1.5px solid currentColorpattern makes recoloring trivial — swapcolorand the border follows. - For Tailwind: use
bg-[#faf6ee] font-sanson the section,font-serif italic text-[#6b1224]on tier names,bg-[#6b1224] text-[#faf6ee]on the recommended card. The:has()currency swap needs arbitrary variants:[&:has(#ps-17__eur:checked)_.ps-17__eur]:inline. React/Next parity: track currency in state and toggle a data attribute if:has()support is a concern (Firefox <121 lacks it).
Gotchas — read before shipping
- The
:has()selector is not supported in Firefox before 121 (Dec 2023) and Chrome/Safari before 105/15.4. If your fintech or B2B SaaS analytics show >1% traffic on older browsers, ship a JS fallback that toggles a class on.ps-17based on radiochange, and rewrite the selectors as.ps-17.is-usd .ps-17__usd { display: inline }. - The
transform: scale(1.04)on.ps-17__bestcreates a new stacking context — child z-index values now stack against this card, not the page. If you later add an absolutely-positioned tooltip that must overlap the neighbouring tier, either raise its z-index above the sibling card or drop scale in favour ofpadding. It also nudges the card ~2px past its column edge on narrow desktops — the mobile media query resets this viatransform: none. - The burgundy primary
#6b1224on cream#faf6eehits ~11.5:1 contrast — passes WCAG AAA (1.4.3). But the muted rose#8a4555support copy on cream reads at ~5.1:1, AA only for large text (14px+). The.ps-17__head psupport paragraph is 14px so it just clears; if you shrink it, either bump the color to#701f30or scale to 16px. - The hidden
<input type="radio">usesopacity: 0; pointer-events: none— visually hidden but keyboard-reachable via the label'sforattribute. The:focus-visible + labeloutline is what makes WCAG 2.4.7 (Focus Visible) pass. Never remove the outline. Also keep thelegend.ps-17__srscreen-reader label — screen-reader users need to know the fieldset is a currency picker, not just three buttons. - Playfair Display italics look great when the font file actually ships italics; the Google Fonts default variant does. If you self-host and forget the italic subset, browsers synthesize a slanted roman that looks janky on tier names. Verify your
@font-faceblock includesfont-style: italic, or the boutique-software vibe collapses. - The
.ps-17__price > span { display: none }+:has()reveal pattern means every currency span still sits in the DOM — screen readers may read all three prices in a row on page load before JS or CSS class-based hiding kicks in. If your international SaaS audience relies on assistive tech, addaria-hidden="true"to non-active currency spans via a tiny script; a pure-CSScontent-visibility: hiddenwon't help because:has()can't toggle attributes.