Plan Comparison Table
Use this after a pricing section when buyers need more confidence before choosing a plan family.
FeatureSharedVPSDedicated
CPUShared pool4 vCPU8 dedicated cores
MemoryBurst allocation8 GB32 GB
Storage25 GB NVMe120 GB NVMe2 x 960 GB NVMe
BackupsWeeklyDailyDaily + snapshots
SupportEmail24/7 chatNamed engineer
Why it works
- Feature labels are short and high signal.
- The table stays readable without turning into a spec dump.
- It naturally supports shared, VPS, and dedicated tiers.
Copy paste code
const rows = [
{label: 'CPU', shared: 'Shared pool', vps: '4 vCPU', dedicated: '8 dedicated cores'},
{label: 'Memory', shared: 'Burst allocation', vps: '8 GB', dedicated: '32 GB'},
{label: 'Storage', shared: '25 GB NVMe', vps: '120 GB NVMe', dedicated: '2 x 960 GB NVMe'},
{label: 'Backups', shared: 'Weekly', vps: 'Daily', dedicated: 'Daily + snapshots'},
{label: 'Support', shared: 'Email', vps: '24/7 chat', dedicated: 'Named engineer'},
];
export function PlanComparisonTable() {
return (
<div className="overflow-hidden rounded-[28px] border border-slate-200 bg-white shadow-[0_24px_80px_-48px_rgba(15,23,42,0.35)]">
<div className="grid grid-cols-[1.1fr_repeat(3,minmax(0,1fr))] border-b border-slate-200 bg-slate-50 px-4 py-4 text-sm font-semibold text-slate-700 sm:px-6">
<span>Feature</span>
<span>Shared</span>
<span>VPS</span>
<span>Dedicated</span>
</div>
<div className="divide-y divide-slate-200">
{rows.map((row) => (
<div key={row.label} className="grid grid-cols-[1.1fr_repeat(3,minmax(0,1fr))] px-4 py-4 text-sm sm:px-6">
<span className="font-medium text-slate-950">{row.label}</span>
<span className="text-slate-600">{row.shared}</span>
<span className="text-slate-600">{row.vps}</span>
<span className="text-slate-600">{row.dedicated}</span>
</div>
))}
</div>
</div>
);
}
Customization notes
- Highlight only the features buyers actually use to decide.
- Keep the left column short and standardized.
- On production pages, add sticky headers if the table becomes longer.