Pricing card with CQ
Pricing card that adapts layout via container queries — no media queries needed.
Quick implementation
/* HTML:
<div class="pricing-wrapper">
<div class="pricing-card">
<div class="pricing-header">
<div class="plan-name">Pro</div>
<div class="price">$29</div>
</div>
<div class="pricing-features">...</div>
<div class="pricing-cta"><button>Get started</button></div>
</div>
</div>
*/
.pricing-wrapper {
container-type: inline-size;
container-name: pricing;
}
.pricing-card {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1.5rem;
border: 1px solid var(--card-border);
border-radius: var(--radius);
background: var(--card);
}
.pricing-header {
text-align: center;
padding-bottom: 1rem;
border-bottom: 1px solid var(--card-border);
}
.pricing-features {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.pricing-cta {
border-top: 1px solid var(--card-border);
padding-top: 1rem;
}
/* Wide layout (container >= 18rem) */
@container pricing (min-width: 18rem) {
.pricing-card {
flex-direction: row;
align-items: stretch;
}
.pricing-header {
flex: 0 0 8rem;
text-align: left;
border-bottom: none;
border-right: 1px solid var(--card-border);
}
.pricing-features {
flex: 1;
border-right: 1px solid var(--card-border);
}
.pricing-cta {
flex: 0 0 8rem;
border-top: none;
border-left: 1px solid var(--card-border);
}
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer specializing in modern CSS layout.
Goal: Build a pricing card component that adapts its layout based on available container width — no JavaScript.
Technical constraints:
- Use container-type: inline-size and @container queries to detect wrapper width.
- Structure: header (plan name + price) + features list + CTA button.
- Use oklch() for all colors — no hex or rgba().
- Layout shift: horizontal (side-by-side sections) when wide, vertical (stacked) when narrow.
- Include focus-visible styles for interactive elements (buttons, links).
Framework variant (pick one):
A) Vanilla HTML + CSS only.
B) React component — accept `plan`, `price`, `period`, `features` (array), `onCtaClick` props; include CSS as a CSS module.
Edge cases to handle:
- Popular/featured variant with accent border and badge.
- What happens if container queries are not supported? Provide a media query fallback.
- ARIA: use semantic elements (<article> for card, <h3> for plan name) and aria-label on the wrapper.
Why this matters in 2026
Pricing pages traditionally rely on fixed-width columns or media queries that break when you reuse cards in different contexts. Container queries let each pricing card self-adapt to its wrapper — stacked in a narrow sidebar, horizontal in a wide pricing section. The same component works everywhere without modifier classes.
This is component-driven design at its best: the card knows its constraints and styles accordingly. No more passing width props or maintaining separate mobile/desktop variants.
The logic
container-type: inline-size on the wrapper establishes a sizing context. The @container pricing (min-width: 18rem) rule switches the card from flex-direction: column to row when space allows. Sections get fixed flex-basis values (flex: 0 0 8rem) to create balanced columns.
Why 18rem? It's the minimum width where side-by-side sections remain readable. Below that, stacking preserves vertical rhythm. Tune the breakpoint based on your content's actual minimums.
Accessibility & performance
Container queries are pure CSS — no performance cost. For accessibility, wrap cards in <article> and use proper heading hierarchy (<h3> for plan names). Buttons must have visible focus rings. The popular badge should be decorative only — don't rely on color alone to distinguish plans; use text labels too.
@media (min-width: 18rem) fallback that defaults to the wide layout.