Utilities✨ Premium

Responsive Pricing Table

Three pricing plans that stack, reveal their features, then sit side by side according to their area's width, gliding to their new place.

CSS@containerPricing

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Utilities has 43 effects, including 3 free. Explore the category →

3 usage examples

Varquelle music school — plans side by side on the Prices page, stacked in “Change plan” — Responsive Pricing Table example 1

① Varquelle music school — plans side by side on the Prices page, stacked in “Change plan”

WhenOn the Prices page, Early years, Instrument and Family show on one row with their features; when Camille opens “Change plan” from the family area, the window reuses the same grid, which stacks in its short form.
WhyOne plan grid for the public page and for the family area window: prices and names cannot drift apart.
SettingsPage rendered at 80 % (transform: scale(.8)); page grid about 630 px wide, window grid 238 px (compact tier). Names, prices and features rewritten in the sold HTML, aria-label attributes adapted.
Brovinelle marketplace — a plugin's pricing preview widened with a handle — Responsive Pricing Table example 2

② Brovinelle marketplace — a plugin's pricing preview widened with a handle

WhenOn the “Simple forms” plugin page, you pull the purple handle of the preview from 250 to 470 px: the three plans leave their stack and glide one after another onto a row, with their features.
WhyThe plugin author sees straight away how their pricing behaves on a customer's narrow or wide site.
SettingsScene rendered at 72 %; widths given before scaling. The handle follows the pointer and arrow keys; for the capture, the scene switches the preview between 250 and 470 px with no width transition, so only the card glide is seen.
Quelvanne invoicing software — drawer plans that compact when the summary opens — Responsive Pricing Table example 3

③ Quelvanne invoicing software — drawer plans that compact when the summary opens

WhenIn the “Your plan” drawer, “See details” opens the November summary on the left: the plans go from three columns to a short stack, each card gliding into place; closing it puts them back side by side.
WhyThe glide explains what just happened: the plans move aside to make room for the figures, without disappearing.
SettingsScene rendered at 75 %; plan area 464 px, then 248 px once the summary is open (216 px, no transition). Without a click, the scene opens and closes it in a loop for the capture.

How it works

.fx-0763-root is the measured container (container: rpt / inline-size). Under 280 px: stacked cards, reduced to name, price and button. From 280 to 399 px: the .rpt-features list fades in over 0.4 s and the price grows from 1.3 to 1.6 rem. From 400 px: the three cards line up on one row, buttons aligned at the bottom.

The move from one tier to another is animated by the script: a ResizeObserver follows each root, spots the change (column count or list appearing) and applies the FLIP technique. Each card visually starts from its old position, then glides to the new one through the .rpt-move class (0.45 s transform transition). Card backgrounds are opaque so a card crossing another hides it cleanly.

The highlighted plan carries .rpt-popular (#6366f1 border, #5f63f0 button, slightly darker so its white text reaches a 4.6:1 contrast). Buttons are real <button type="button"> elements: wire them to your checkout or replace them with links.

Accessibility

  • Named buttons: each button keeps its visible text (“Choose”) and gets an aria-label that completes it (“Choose the Starter plan”) so a list of buttons still makes sense out of context.
  • Visible focus: 2 px #a5b4fc outline from the keyboard (:focus-visible). On Safari for macOS, Tab only reaches buttons if the system keyboard option allows it.
  • Reduced motion: with prefers-reduced-motion: reduce, no card glide, no list fade and no button growth on hover; tiers switch instantly.
  • Features hidden when small: under 280 px the list is display:none, so screen readers skip it too; if a plan stands out by its features, keep a short version in the name or button.

Browser compatibility

Container queries (Chrome 105, Firefox 110, Safari 16), ResizeObserver and CSS animation, according to @mdn/browser-compat-data 8.1.8. Measured in Chromium 151, Firefox 153 and WebKit 26.5: 1 column without features at 220 px, 1 column with features at 300 px, 3 columns at 400 and 600 px; at a tier change, the 3 cards of the resized copy glide (moving at 30 and 150 ms, settled at 700 ms) and the neighbouring copy does not move.

Chrome 105+✓ Full (measured)
Firefox 110+✓ Full (measured)
Safari 16+✓ Full (measured in WebKit)
Edge 105+✓ Full
Mobile iOS 16+✓ Full
Android Chrome 105+✓ Full

Without JavaScript, the tiers work but cards change place at once. Without @container, the plans stay stacked and compact, buttons usable.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0763-root">
  <div class="rpt-grid">
    <div class="rpt-card">
      <h5>…</h5>
      <div class="rpt-price">…<small>/mo</small></div>
      <ul class="rpt-features"><li>…</li></ul>
      <button type="button" class="rpt-cta" aria-label="…">…</button>
    </div>
    <div class="rpt-card rpt-popular">…</div>
    <div class="rpt-card">…</div>
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Tiers (CSS — @container rpt (min-width: 280px) and (min-width: 400px)) Features at 280 px, three columns at 400 px With long features, raise the column tier to 480 px; the script follows any tier change without settings.
Glide (CSS — .rpt-card.rpt-move { transition }) transform .45s cubic-bezier(.4, 0, .2, 1) Shorten to 0.3 s for a plan grid inside a drawer that opens quickly.
List fade (CSS — @keyframes rpt-apparait) 0.4 s, from opacity 0 and 4 px higher Remove animation on .rpt-features for an abrupt appearance.
Highlighted plan (HTML — rpt-popular class) On the middle plan Move the class to another card; border, background and button follow.
Colours (CSS — .rpt-price, .rpt-popular, #16161b / #131326 backgrounds) #8b5cf6 price, #6366f1 border, #5f63f0 highlighted button Keep card backgrounds opaque: with a transparent one, cards would show their neighbours while gliding.
Texts and buttons (HTML — h5, .rpt-price, li, aria-label) Starter $9, Pro $29, Enterprise $99 Change the visible text and the aria-label together so the spoken name always starts with the displayed word.

FAQ

Yes, if the grid area changes tier at that moment: the root's width is what counts, whatever the cause (window, neighbouring panel, drawer).
Yes: add a card and switch the 400 px tier to repeat(4, 1fr) with a higher threshold (around 520 px). The glide applies to every card in the grid.
No, they are buttons with no action: add your click handler or replace each <button> with an <a> link using the same class.