Blog · · 8 min
Add to cart button
An add to cart button names what is being added and carries the total whenever the selection above it can change the price: `Add 3 tins · $48.00`. It needs one pending state, one confirmation announced to assistive technology, a tap target of 44 CSS pixels, and no second button of equal weight beside it.
By uxgen
The button says what is going into the cart. Add 3 tins · $48.00, not Add to cart, whenever anything above it can change what the buyer gets or what it costs. On a page with one price and one variant, Add to cart is complete and the total in the label is noise. That single decision (does the selection above this button move?) settles the label, and most of the rest follows from it.

What the label has to carry
Three inputs, in this order of importance.
The verb and the object. Add alone tells the buyer nothing about what they picked, which matters on any page where more than one thing is pickable. Add 3 tins closes the loop between the tier they tapped and the action they are about to take.
The total, conditionally. Put the money in the button when the price on that screen is a function of a control on that screen. A quantity stepper, a tier selector, a size that changes price, a bundle toggle. In all four cases the button is the receipt for a calculation the buyer just made, and reading it back is what stops them scrolling up to check. On a fixed-price page, leave the money where it already is.
Nothing else. No Free shipping, no In stock, no countdown. Those are separate claims with separate consequences, and one of them has a legal shape of its own.
A worked version of the rule:
| Page | Can the price move on screen? | Label |
|---|---|---|
| Single SKU, one price | no | Add to cart |
| Quantity stepper | yes | Add 2 · $38.00 |
| Three-tier selector | yes | Add 3 tins · $48.00 |
| Size changes price | yes | Add 90 ml · €129.00 |
| Subscription toggle | yes | Subscribe · $17.10 / month |
The three states, and the one that gets skipped
Idle. The label above.
Pending. The button stays at the same width. A label that shrinks from Add 3 tins · $48.00 to Adding… makes the whole block reflow under the buyer's thumb at the exact moment they are watching it. Reserve the width, swap the inner content, and keep the accessible name stable or update it deliberately with aria-busy.
Confirmed. This is the state almost every generated implementation drops. Something has to say the item arrived, and it has to say it to a screen reader as well as to the eye. One polite live region does both:
<button onClick={add} aria-busy={pending} disabled={pending}>
{pending ? "Adding…" : `Add ${qty} tins · ${money(total)}`}
</button>
<p aria-live="polite" className="sr-only">{annonce}</p>
// annonce = "3 tins added. Cart total $48.00."
Opening a drawer counts as confirmation for a sighted buyer and counts as nothing at all for someone who cannot see it move. The live region is one line and it is the difference between a component that works and a component that looks like it works.
Colour is the question everyone asks
It is also the one with the least in it. We pulled United States Google volumes for this cluster on 31 August 2026:
| Query | Monthly searches |
|---|---|
| add to cart button | 880 |
| black add to cart button | 590 |
| green add to cart button | 390 |
| add to cart button animation | 320 |
| add to cart button with quantity | 140 |
| sticky add to cart button | 110 |
| add to cart button css | 90 |
| add to cart button color | 20 |
Almost as many people want a specific colour as want the button itself, and the two colours they want are opposites. That is the tell. No hue wins, because the variable is not hue. It is whether the button is the highest-contrast element in its region, and whether nothing else on the page shares that treatment.
Two figures are actually specified rather than argued about. WCAG 2.1 success criterion 1.4.3 asks for a contrast ratio of at least 4.5:1 between the label and the button fill for normal-sized text. Criterion 1.4.11 asks for 3:1 between the button and whatever it sits on, so a pale button on a pale card fails even when its own label passes. Measure both. Then stop reading colour psychology.
Size, and the numbers that are written down
WCAG 2.2 added success criterion 2.5.8, Target Size (Minimum), at Level AA. It asks for at least 24 by 24 CSS pixels, with exceptions for spacing and for inline targets. The older 2.5.5 sits at Level AAA and asks for 44 by 44. Apple's Human Interface Guidelines have long recommended 44 by 44 points, and Material Design asks for 48 by 48 density-independent pixels.
Take 44. A primary purchase control that only clears the AA floor is a control designed to the legal minimum, and the AA floor exists to catch small inline links rather than to size the one button the page was built around. On mobile, full bleed inside the content gutter, with the bottom safe area respected once the same button becomes sticky.
Add to cart beside Buy now
Two buttons of equal weight are two decisions. The buyer wanted to make one.
If the page needs an express path, make it visually secondary and put it second in the DOM, so the primary action is also the first thing a keyboard reaches. Where the express path is a wallet button rendered by a payment provider, its styling is often outside your control, which is an argument for keeping your own button plainly dominant rather than for matching it.
One more constraint applies in Europe and it is the kind an agent will not invent. Under Article 22 of Directive 2011/83/EU, any extra payment on top of the main contract needs the consumer's express consent, and consent inferred from a default option does not count. So a pre-ticked warranty, gift wrap or complement sitting above the button is unlawful there, whatever it does to the average order. The same rule shapes where a complement can legally sit.
What an agent writes when nothing tells it otherwise
Ask a coding agent for an add-to-cart button and you reliably get a rounded rectangle with a gradient, the literal string Add to Cart, a disabled attribute wired to a loading boolean, and no live region. Every one of those is the median of what has been published. The label is generic because most published examples are catalogue demos where nothing above the button can move, and the confirmation is missing because a demo has nothing to confirm.
The fix is not a better prompt. It is handing the agent a component whose props make the wrong version impossible to write, which is the same argument as the tier selector spec and the reason general registries stop short of these four blocks.
<AddToCart
items={[{ sku: "tin-guji", qty: 3 }]}
totalCents={4800}
currency="USD"
onAdded={openDrawer}
/>
// → "Add 3 tins · $48.00", pending state, live confirmation
No label prop. The label is derived, so it cannot drift from the selection it describes.
Disclosure. We build uxgen, an MCP server that hands a coding agent this component and the rest of the basket set. They are shown running here, and the plans are on the pricing section.
FAQ
What should an add to cart button say?
It should name what is being added, and carry the total whenever a control on the same screen can change the price. Add 3 tins · $48.00. On a page with one fixed price and one variant, Add to cart is complete and adding the total repeats what is already on screen.
Does the colour of the add to cart button matter?
Contrast matters, hue does not. Search demand splits almost evenly between black and green, which is the evidence that no colour wins. Aim for 4.5:1 between the label and the fill and 3:1 between the button and its background, then make sure nothing else on the page shares that treatment.
How big should an add to cart button be?
At least 44 by 44 CSS pixels. WCAG 2.2 sets a floor of 24 by 24 at Level AA and 44 by 44 at Level AAA, and both Apple and Material recommend 44 or 48. The AA floor is meant for small inline targets rather than for the page's primary purchase control.
Should Add to cart and Buy now sit side by side?
Only if one of them is clearly secondary. Two controls of the same visual weight turn one decision into two. Keep the add-to-cart button dominant, place the express path after it in the DOM, and never pre-tick a paid extra above either of them, which Article 22 of the EU Consumer Rights Directive prohibits.