Pricing Page — Free HTML CSS JS 3-Tier Snippet

Pricing Page · Pricing · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

3-tier grid: repeat(3,1fr) with align-items: start — natural card heights
Monthly/annual toggle: two price arrays swapped on click, no page reload
Featured plan: accent border, coloured glow shadow, solid CTA button
Popular badge: position absolute top: -12px with translateX(-50%) centering
SVG check/cross icons: background-image data URI on ::before — no icon library
Line-through text + dimmed colour on .no feature list items
Save X% chip always visible on annual toggle label
Guarantee row below plans: trial length, no credit card, cancel anytime
Responsive: repeat(3,1fr) collapses to 1-column below 700px
Export as HTML file, React JSX component, or React + Tailwind CSS

About this UI Snippet

Pricing Page — Complete 3-Tier SaaS Layout with Annual Toggle, SVG Icons & Conversion Design

Screenshot of the Pricing Page snippet rendered live

If you are building a SaaS landing page and need a pricing section that actually converts, this snippet gives you the complete HTML, CSS, and JavaScript in one copy-paste block. Three plan tiers, a monthly/annual billing toggle, a full feature comparison list, and a guarantee row — all styled with conversion-optimisation principles built in.

How the annual billing toggle works

The toggle uses two JavaScript arrays: one for monthly prices and one for annual prices. The switchBilling() function flips a boolean, picks the correct array, and updates each price element's textContent. A CSS knob slides right via transform: translateX(20px) when the .annual class is added to the button. The "Monthly" label dims and the "Annual" label brightens — both controlled by toggling a .dim class. The "Save 20%" badge stays visible on the annual label at all times, making the discount visible before the user interacts.

Featured plan design pattern

The middle Pro plan uses class="plan featured" which applies an accent-coloured border (border-color: #6366f1) and a soft coloured glow (box-shadow: 0 8px 32px rgba(99,102,241,0.15)). The "Most popular" badge sits outside the normal card flow: position: absolute; top: -12px; left: 50%; transform: translateX(-50%) centres it over the top edge so it appears to hover above the card. The CTA button uses a filled solid style instead of outline, further differentiating the recommended tier visually.

Check and cross feature icons without an icon library

The feature list items use CSS ::before pseudo-elements with background-image set to an inline SVG data URI. The SVG is URL-encoded — %3Csvg for the opening tag, %2316a34a for the green colour. No img tag, no external font, no library import. The green check circle appears on li.yes items and the grey cross on li.no items. The .no items also get text-decoration: line-through so excluded features are visually struck out — a deliberate UX pattern that makes plan differences obvious and encourages upgrades.

Grid layout with natural heights

The three-column layout uses display: grid; grid-template-columns: repeat(3,1fr); align-items: start. The align-items: start is important — without it, all cards would stretch to the same height as the tallest card, which looks wrong when feature list lengths differ. With start, each card is exactly as tall as its content. A responsive media query switches to a single column below 700px.

Customising this snippet

Change plan names, prices, and feature lists directly in the HTML. Update the monthly and annual arrays in the JS. Move class="plan featured" to whichever plan you want to highlight. Replace #6366f1 throughout the CSS to match your brand colour. The guarantee row text at the bottom is a plain paragraph — edit it to match your trial or refund policy.

Exporting for your stack

Click "JSX" to download a React component. Click "Tailwind" to download a React + Tailwind CSS version. Both export options convert the pricing section automatically. In React, manage isAnnual with useState and compute each price as isAnnual ? annual[i] : monthly[i].

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to work out the toggle-to-price-array wiring by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how switchBilling keeps the sliding knob's transform, the two label's dim classes, and the three price elements' text content all in sync from one boolean flip, and why align-items start on the plans grid matters when the three feature lists have different lengths. The same assistant can help optimize it, for example checking whether the inline SVG data-URI checkmarks in the feature list are the most maintainable approach if you need to add a fourth or fifth plan, or whether the monthly and annual price arrays should instead be a single array of objects keyed by plan for less error-prone indexing. It's also useful for extending the effect: ask it to wire each CTA button to a real Stripe Checkout session using the correct monthly or annual price ID, add a fourth Enterprise tier with a "Contact sales" CTA instead of a price, or animate the price number changing instead of an instant text swap. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a complete three-tier SaaS pricing page section in plain HTML, CSS, and vanilla JavaScript, with a working monthly/annual billing toggle — no libraries.

Requirements:
- A toggle switch styled as a pill-shaped button with a sliding circular knob, plus a "Monthly" label and an "Annual" label (with a small "Save 20%" chip always visible next to it) on either side, where clicking the toggle slides the knob to the opposite side using a CSS transform transition and dims whichever label is not currently active.
- Two parallel JavaScript arrays (one of monthly prices, one of annual prices, indexed the same way as the three plan cards) so that clicking the toggle updates every plan's displayed price by reading from whichever array matches the new billing period — with no page reload.
- Three plan cards laid out in a CSS grid that keeps each card exactly as tall as its own content (not stretched to match the tallest card), since the three feature lists have different lengths.
- One card marked as the featured/recommended plan with an accent border color, a soft colored box-shadow glow, and a "Most popular" badge that floats centered above the card's top edge regardless of the badge text's length.
- Every feature list item must show a green checkmark or a muted gray cross via a CSS pseudo-element referencing an inline, URL-encoded SVG data URI in background-image — no icon font, no separate image files — and excluded features must also get a line-through text style.
- A closing guarantee line below the three cards (trial length, no credit card required, cancel anytime) and make sure the toggle, the featured plan's accent color, and the checkmark colors are all easy to re-theme by changing a single hex value used consistently across the CSS.

Step by step

How to Use

  1. 1
    Click the billing toggleToggle between Monthly and Annual pricing. The knob slides right, labels swap colour, and prices update from the JS arrays. No page reload needed.
  2. 2
    Update plan names and pricesIn the JS panel, edit the monthly and annual arrays — one number per plan. In the HTML, update the plan-name div, plan-desc, and CTA link text for each column.
  3. 3
    Update the feature listsEdit each li text inside the .feat-list. Apply class="yes" to included features (shows green check) and class="no" to excluded features (shows grey cross and line-through text).
  4. 4
    Change the featured plan columnMove class="plan featured" and the <div class="popular"> element to whichever plan column you want to highlight. The accent border, glow, and popular badge all move with it.
  5. 5
    Change the brand colourFind #6366f1 in the CSS panel and replace all instances with your hex. This updates the toggle, featured border, glow shadow, solid CTA button, and save chip in one pass.
  6. 6
    Export in your formatClick "HTML" to download a standalone file, "JSX" for a React component with isAnnual state, or "Tailwind" for a React + Tailwind CSS version. "Copy all" copies the full code.

Real-world uses

Common Use Cases

SaaS product pricing pages
Drop this complete pricing section into any SaaS landing page, or build it up from standalone pricing cards and a pricing FAQ. The three-tier layout, feature comparison, and billing toggle cover every standard SaaS pricing pattern in a single component.
Annual billing upsell to increase revenue
The annual toggle with "Save 20%" chip always visible nudges users toward the higher-value annual plan. Wire each CTA to a different Stripe priceId based on the isAnnual boolean to route checkout correctly.
Agency, consulting, and service pricing
Replace Starter/Pro/Team with your service tiers — Basic/Standard/Enterprise or Essentials/Growth/Scale. The three-column feature list format works for any structured comparison, not just software.
Learn inline SVG data URI icon technique
The check and cross icons use background-image with a URL-encoded SVG string on a ::before pseudo-element. This technique requires no icon font, no library, and no img tag — just CSS.
Stripe checkout integration starting point
Store two Stripe priceIds per plan (monthly and annual). In the CTA click handler, read the isAnnual boolean and call stripe.redirectToCheckout({ priceId: plans[i][isAnnual ? "annual" : "monthly"] }) to send users to the correct checkout session.
Conversion-optimised page sections
The featured middle plan with popular badge, solid CTA, and accent border focuses user attention on the recommended tier. Research shows highlighted recommended plans consistently outperform uniform card grids in conversion tests.

Got questions?

Frequently Asked Questions

Two JavaScript arrays — monthly and annual — hold one price per plan. switchBilling() flips the isAnnual boolean, selects the right array, and updates each .amount span via textContent. The CSS knob animation uses transform: translateX(20px) toggled by the .annual class on the button. The label colours swap by toggling a .dim class on each label span.

Each li::before pseudo-element uses background-image with an inline SVG data URI. The SVG markup is URL-encoded — spaces become %20, # becomes %23, angle brackets become %3C/%3E. A 16x16 circle provides the background fill, and the SVG draws the check or cross on top. This works in all modern browsers with no external dependency.

Add a fourth .plan div inside .plans and add a fourth price to both the monthly and annual arrays in the JS. Update the grid CSS to grid-template-columns: repeat(4,1fr). For responsive layouts, use repeat(auto-fill, minmax(220px,1fr)) instead — the browser places as many columns as fit the viewport width automatically.

Yes. Click "JSX" to download a React component. In React, replace the vanilla JS toggle with useState(false) for isAnnual. Compute each price as isAnnual ? annual[i] : monthly[i] inline. For Next.js, drop the component into a page file or import it as a section component. The Tailwind export converts all CSS classes to utility classes for Tailwind CSS v3+ projects.