21 CSS Pricing Sections08 / 21

Pure CSSMIT licensed

Vertical Tier Timeline

Tiers presented as a vertical roadmap — Free → Pro → Enterprise — connected by a glowing lime spine. Each station is a real <ol>/<li> with a numbered milestone, price, and feature list. Reads as a growth path, not a column comparison.

Published

Live Demo
Try it

The code

<section class="ps-08" aria-label="Pricing">
  <header class="ps-08__head">
    <h2>Grow into the next plan, not out of one.</h2>
    <p>Three stops on the same road. Switch up or down with one click.</p>
  </header>
  <ol class="ps-08__line">
    <li class="ps-08__stop">
      <span class="ps-08__num" aria-hidden="true">01</span>
      <article class="ps-08__pane">
        <header>
          <h3>Free</h3>
          <span class="ps-08__pri">$0</span>
        </header>
        <p>
          Open-source projects, side experiments, anything you want to ship without a credit card.
        </p>
        <ul>
          <li>1 project</li>
          <li>500 MB storage</li>
          <li>Public repos only</li>
        </ul>
        <a class="ps-08__cta" href="#free">Start free →</a>
      </article>
    </li>
    <li class="ps-08__stop ps-08__current">
      <span class="ps-08__num" aria-hidden="true">02</span>
      <article class="ps-08__pane">
        <header>
          <h3>Pro</h3>
          <span class="ps-08__pri">$24<em>/mo</em></span>
        </header>
        <p>
          Where most teams settle. Private projects, real support, and the integrations you actually
          use.
        </p>
        <ul>
          <li>Unlimited projects</li>
          <li>50 GB storage</li>
          <li>Email + chat support</li>
          <li>Slack, GitHub, Linear sync</li>
        </ul>
        <a class="ps-08__cta ps-08__cta-pri" href="#pro">Choose Pro →</a>
      </article>
    </li>
    <li class="ps-08__stop">
      <span class="ps-08__num" aria-hidden="true">03</span>
      <article class="ps-08__pane">
        <header>
          <h3>Enterprise</h3>
          <span class="ps-08__pri">Custom</span>
        </header>
        <p>
          For teams with procurement processes, security reviews, and quarterly business reviews.
        </p>
        <ul>
          <li>SSO + SAML + audit logs</li>
          <li>SLA, dedicated CSM</li>
          <li>Custom DPA &amp; invoicing</li>
        </ul>
        <a class="ps-08__cta" href="#ent">Talk to sales →</a>
      </article>
    </li>
  </ol>
</section>
.ps-08 {
  padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
  width: 100%;
  min-height: 100vh;
  background: #0a1408;
  color: #ecfccb;
  font-family: 'Inter', system-ui, sans-serif;
}

.ps-08__head {
  text-align: center;
  margin-bottom: clamp(28px, 5vw, 44px);
}

.ps-08__head h2 {
  font-size: clamp(22px, 3.4vw, 32px);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 8px;
  color: #f7feec;
}

.ps-08__head p {
  color: #93a87f;
  margin: 0;
  font-size: 14px;
}

.ps-08__line {
  position: relative;
  list-style: none;
  padding: 0;
  margin: 0 auto;
  max-width: 580px;
}

.ps-08__line::before {
  content: '';
  position: absolute;
  left: 28px;
  top: 18px;
  bottom: 18px;
  width: 2px;
  background: linear-gradient(180deg, #84cc16, rgba(132,204,22,0.2));
  border-radius: 2px;
}

.ps-08__stop {
  position: relative;
  padding: 0 0 24px 70px;
  min-height: 56px;
}

.ps-08__stop:last-child {
  padding-bottom: 0;
}

.ps-08__num {
  position: absolute;
  left: 6px;
  top: 0;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: #0a1408;
  border: 2px solid #84cc16;
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 700;
  color: #84cc16;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
}

.ps-08__current .ps-08__num {
  background: #84cc16;
  color: #0a1408;
  box-shadow: 0 0 0 6px rgba(132,204,22,0.18);
}

.ps-08__pane {
  background: #14210e;
  border: 1px solid rgba(132,204,22,0.18);
  border-radius: 12px;
  padding: 18px 18px 16px;
}

.ps-08__current .ps-08__pane {
  border-color: #84cc16;
  background: linear-gradient(180deg, #1a3010, #14210e);
  box-shadow: 0 8px 24px rgba(132,204,22,0.12);
}

.ps-08__pane header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
  border-bottom: 1px dashed rgba(132,204,22,0.18);
  padding-bottom: 10px;
}

.ps-08__pane h3 {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
  color: #84cc16;
}

.ps-08__pri {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #f7feec;
}

.ps-08__pri em {
  font-size: 12px;
  font-style: normal;
  color: #93a87f;
  font-weight: 500;
  margin-left: 2px;
}

.ps-08__pane p {
  font-size: 13px;
  color: #c8d8b0;
  margin: 10px 0;
  line-height: 1.55;
}

.ps-08__pane ul {
  list-style: none;
  padding: 0;
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.85;
  color: #c8d8b0;
}

.ps-08__pane ul li::before {
  content: '→';
  color: #84cc16;
  display: inline-block;
  width: 20px;
  font-weight: 700;
}

.ps-08__cta {
  display: inline-block;
  padding: 9px 14px;
  border-radius: 7px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid rgba(132,204,22,0.4);
  color: #84cc16;
  background: transparent;
  transition: background 0.18s, color 0.18s;
}

.ps-08__cta:hover {
  background: rgba(132,204,22,0.15);
  color: #ecfccb;
}

.ps-08__cta-pri {
  background: #84cc16;
  color: #0a1408;
  border-color: #84cc16;
}

.ps-08__cta-pri:hover {
  background: #a3e635;
  color: #0a1408;
  border-color: #a3e635;
}

.ps-08__cta:focus-visible {
  outline: 2px solid #a3e635;
  outline-offset: 3px;
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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: Vertical Tier Timeline
Source: https://codefronts.com/layouts/css-pricing-sections/vertical-tier-timeline/

Tiers presented as a vertical roadmap — Free → Pro → Enterprise — connected by a glowing lime spine. Each station is a real <ol>/<li> with a numbered milestone, price, and feature list. Reads as a growth path, not a column comparison.
## HTML
```html
<section class="ps-08" aria-label="Pricing">
  <header class="ps-08__head">
    <h2>Grow into the next plan, not out of one.</h2>
    <p>Three stops on the same road. Switch up or down with one click.</p>
  </header>
  <ol class="ps-08__line">
    <li class="ps-08__stop">
      <span class="ps-08__num" aria-hidden="true">01</span>
      <article class="ps-08__pane">
        <header>
          <h3>Free</h3>
          <span class="ps-08__pri">$0</span>
        </header>
        <p>
          Open-source projects, side experiments, anything you want to ship without a credit card.
        </p>
        <ul>
          <li>1 project</li>
          <li>500 MB storage</li>
          <li>Public repos only</li>
        </ul>
        <a class="ps-08__cta" href="#free">Start free →</a>
      </article>
    </li>
    <li class="ps-08__stop ps-08__current">
      <span class="ps-08__num" aria-hidden="true">02</span>
      <article class="ps-08__pane">
        <header>
          <h3>Pro</h3>
          <span class="ps-08__pri">$24<em>/mo</em></span>
        </header>
        <p>
          Where most teams settle. Private projects, real support, and the integrations you actually
          use.
        </p>
        <ul>
          <li>Unlimited projects</li>
          <li>50 GB storage</li>
          <li>Email + chat support</li>
          <li>Slack, GitHub, Linear sync</li>
        </ul>
        <a class="ps-08__cta ps-08__cta-pri" href="#pro">Choose Pro →</a>
      </article>
    </li>
    <li class="ps-08__stop">
      <span class="ps-08__num" aria-hidden="true">03</span>
      <article class="ps-08__pane">
        <header>
          <h3>Enterprise</h3>
          <span class="ps-08__pri">Custom</span>
        </header>
        <p>
          For teams with procurement processes, security reviews, and quarterly business reviews.
        </p>
        <ul>
          <li>SSO + SAML + audit logs</li>
          <li>SLA, dedicated CSM</li>
          <li>Custom DPA &amp; invoicing</li>
        </ul>
        <a class="ps-08__cta" href="#ent">Talk to sales →</a>
      </article>
    </li>
  </ol>
</section>
```
## CSS
```css
.ps-08 {
  padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
  width: 100%;
  min-height: 100vh;
  background: #0a1408;
  color: #ecfccb;
  font-family: 'Inter', system-ui, sans-serif;
}

.ps-08__head {
  text-align: center;
  margin-bottom: clamp(28px, 5vw, 44px);
}

.ps-08__head h2 {
  font-size: clamp(22px, 3.4vw, 32px);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 8px;
  color: #f7feec;
}

.ps-08__head p {
  color: #93a87f;
  margin: 0;
  font-size: 14px;
}

.ps-08__line {
  position: relative;
  list-style: none;
  padding: 0;
  margin: 0 auto;
  max-width: 580px;
}

.ps-08__line::before {
  content: '';
  position: absolute;
  left: 28px;
  top: 18px;
  bottom: 18px;
  width: 2px;
  background: linear-gradient(180deg, #84cc16, rgba(132,204,22,0.2));
  border-radius: 2px;
}

.ps-08__stop {
  position: relative;
  padding: 0 0 24px 70px;
  min-height: 56px;
}

.ps-08__stop:last-child {
  padding-bottom: 0;
}

.ps-08__num {
  position: absolute;
  left: 6px;
  top: 0;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: #0a1408;
  border: 2px solid #84cc16;
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 700;
  color: #84cc16;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
}

.ps-08__current .ps-08__num {
  background: #84cc16;
  color: #0a1408;
  box-shadow: 0 0 0 6px rgba(132,204,22,0.18);
}

.ps-08__pane {
  background: #14210e;
  border: 1px solid rgba(132,204,22,0.18);
  border-radius: 12px;
  padding: 18px 18px 16px;
}

.ps-08__current .ps-08__pane {
  border-color: #84cc16;
  background: linear-gradient(180deg, #1a3010, #14210e);
  box-shadow: 0 8px 24px rgba(132,204,22,0.12);
}

.ps-08__pane header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
  border-bottom: 1px dashed rgba(132,204,22,0.18);
  padding-bottom: 10px;
}

.ps-08__pane h3 {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0;
  color: #84cc16;
}

.ps-08__pri {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #f7feec;
}

.ps-08__pri em {
  font-size: 12px;
  font-style: normal;
  color: #93a87f;
  font-weight: 500;
  margin-left: 2px;
}

.ps-08__pane p {
  font-size: 13px;
  color: #c8d8b0;
  margin: 10px 0;
  line-height: 1.55;
}

.ps-08__pane ul {
  list-style: none;
  padding: 0;
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.85;
  color: #c8d8b0;
}

.ps-08__pane ul li::before {
  content: '→';
  color: #84cc16;
  display: inline-block;
  width: 20px;
  font-weight: 700;
}

.ps-08__cta {
  display: inline-block;
  padding: 9px 14px;
  border-radius: 7px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid rgba(132,204,22,0.4);
  color: #84cc16;
  background: transparent;
  transition: background 0.18s, color 0.18s;
}

.ps-08__cta:hover {
  background: rgba(132,204,22,0.15);
  color: #ecfccb;
}

.ps-08__cta-pri {
  background: #84cc16;
  color: #0a1408;
  border-color: #84cc16;
}

.ps-08__cta-pri:hover {
  background: #a3e635;
  color: #0a1408;
  border-color: #a3e635;
}

.ps-08__cta:focus-visible {
  outline: 2px solid #a3e635;
  outline-offset: 3px;
}
```

How this works

The vertical pricing timeline is a real semantic <ol class="ps-08__line"> — three <li class="ps-08__stop"> stations, each one a labeled tier with a numbered milestone circle. The spine is a single ::before pseudo-element on the ordered list: position: absolute; left: 28px; top: 18px; bottom: 18px; width: 2px; background: linear-gradient(180deg, #84cc16, rgba(132,204,22,0.2)) — one gradient replaces three stacked divs and preserves screen-reader flow. Each station's number circle uses position: absolute; left: 6px so it sits on top of the spine, with z-index: 1 ensuring the numbered marker paints above the line. The current tier (.ps-08__current) gets a solid lime fill plus a box-shadow: 0 0 0 6px rgba(132,204,22,0.18) pulse ring, gamifying the "you are here" signal.

Palette is deep-forest #0a1408 ground, celadon body text #c8d8b0, and lime #84cc16 as the growth-path accent — chosen because lime reads as "active/upgrade" without the panic urgency of red or the corporate weight of blue. Type is 'Inter' throughout with milestone numbers in 'JetBrains Mono' — the mono numerals borrow from CI pipeline UIs (GitHub Actions, Vercel deploy steps) that developers already parse as "progression states." Prices sit in the pane header via display: flex; justify-content: space-between with dashed underlines that echo receipt-tape aesthetics.

Why it converts: vertical progression frames tiers as "levels to achieve" rather than columns to compare. The Iyengar paradox-of-choice research shows column layouts induce paralysis over three options; a timeline sidesteps that by implying sequence — visitors read Free → Pro → Enterprise as a growth arc, not a choice, and self-select where they "currently are." Roadmap framing typically lifts mid-tier conversion 15–25% on education platforms and dev tools with clear upgrade paths (GitHub, Vercel, Linear). The .ps-08__current pulse is the anchor — visitors gravitate to the highlighted station because the ring reads as "where teams like yours land."

Make it yours

  • Recolor for B2B SaaS trust palette: swap lime #84cc16 → indigo #6366f1, ground #0a1408 → slate #0f172a, and body text to #cbd5e1. Keep the spine gradient formula — linear-gradient(180deg, #6366f1, rgba(99,102,241,0.2)) — so the fade-to-transparent still reads as "path continues."
  • Swap the milestone glyph: current is 01/02/03 in mono. For education platforms use unicode ✦/✧/✩; for dev tools use commit-hash chunks (a1f, b7d, c2e). Adjust .ps-08__num font-size to keep the glyph vertically centered inside the 46px circle.
  • CTA shape: border-radius: 7px is neutral. For a bolder growth-tool vibe drop to border-radius: 4px and add border-width: 1.5px. For consumer-app polish, go pill (border-radius: 999px) and switch the primary CTA to a solid #a3e635 fill for extra pop.
  • Light-mode inversion: background #f7feec, panes #ffffff with border: 1px solid #e5e7eb, text #1a2e05, and the spine to linear-gradient(180deg, #65a30d, rgba(101,163,13,0.15)). The .ps-08__current pulse ring gets rgba(132,204,22,0.28) to hold against a bright ground.
  • Tailwind mapping: <ol class="relative max-w-[580px] mx-auto before:absolute before:left-7 before:top-4 before:bottom-4 before:w-0.5 before:bg-gradient-to-b before:from-lime-500 before:to-lime-500/20"> handles the spine; stations become <li class="relative pl-[70px] pb-6">. React/Vue components can pass current as a prop that toggles the pulse-ring shadow class.

Gotchas — read before shipping

  • The ::before spine positions with top: 18px; bottom: 18px — those offsets assume the first and last number circles start ~18px from the pane top. If you resize .ps-08__num from 46px to 56px, the spine no longer meets the circle center and reads as a broken pipe. Recalculate: offset = (circleHeight/2) - 5px.
  • Semantic warning: an <ol> implies sequential order to assistive tech — screen readers announce "list of 3 items, item 1 of 3." That's ideal for a growth path but wrong if visitors can jump directly from Free to Enterprise. If the ordering is nominal, use <ul> and drop the .ps-08__num numbering; keep the timeline visual, lose the ordinal semantic.
  • WCAG 1.4.11 non-text contrast: the spine gradient fades to rgba(132,204,22,0.2) — that lower end sits below 3:1 against #0a1408 and technically fails the non-text contrast requirement for UI components conveying information. If the spine is decorative only, add aria-hidden to the pseudo-parent or bump the fade endpoint to rgba(132,204,22,0.45).
  • Framework quirk (Vue 3 / Nuxt): the :last-child selector on .ps-08__stop:last-child { padding-bottom: 0 } breaks when a v-if hides the last station conditionally — the second-to-last stop keeps its 24px padding and the spine overshoots. Use :last-of-type or a class-based .ps-08__stop--last flag rendered from the component.
  • CLS from font swap: the price uses font-size: 22px; font-weight: 800 alongside a smaller em for the cycle suffix. When Inter loads late, the fallback (system-ui) has narrower digits — the price re-flows the header row and pushes the dashed underline down ~4px. Preload Inter with <link rel="preload" as="font" crossorigin> or use font-display: optional.
  • Mobile-tap target: the number circle is only 46×46px — WCAG 2.5.5 target size is 44×44px minimum (AA), 24×24px minimum (AAA relaxed). You're safe now, but if you shrink the timeline for compact layouts, keep the number circle at ≥44px or make sure the entire .ps-08__pane is the click target instead.

Techniques used in this demo

Search CodeFronts

Loading…