By · Updated

Product Card CSS

Image Ratio, Sale Badge, Brand Line and Add-to-Cart Button Options, Accessible Markup

No ratings yet

Layout

Colours

Content

OneTask is free, with no sign-up, and built by one person.
If this tool saved you time, a coffee helps keep new ones coming.

How the Product Card Builder works

This product card CSS builder writes a shop card you can repeat. Product cards carry the shop: image, name, price, rating and a button, repeated hundreds of times. Choose an image ratio and badge, type your own product details, and copy a card with correct semantics, a real strikethrough sale price and an accessible star rating.

Product card CSS: image, price and button

The product card is the most repeated component in e-commerce. A category page, search results page or "you may also like" strip is just a grid of them, so small decisions multiply: a card that is 20 pixels too tall pushes a whole row below the fold, and a price that is hard to spot costs clicks on every product. Shoppers scan listings quickly and expect the image, price and key details to be visible without opening the product page.

Anatomy of a product card

The card has a fixed order because shoppers scan it in a fixed order: picture first, then price, then name, then social proof. The generated markup follows that order in the DOM as well as visually, so screen reader users get the same information in a sensible sequence.

Part Element Why this element
Wrapper <article> A self-contained item that makes sense on its own
Badge <span> over the image Decoration on top of the photo, removed when set to None
Photo <img> with aspect-ratio Space is reserved before it loads, so nothing jumps
Brand <span> A small label, not a heading
Name <h3> Lets screen reader users jump from product to product
Rating <div> with aria-label Read as one phrase instead of five images
Price <span> plus <s> <s> marks a price that is no longer accurate
Button <button type="button"> Adding to a basket is an action, not navigation

The options

Image ratio. Square (1:1) is the default because most product photography is shot square and it tiles cleanly. Portrait (4:5) suits fashion, where garments are tall, and it matches the shape Instagram shows best, so the same shots work on both. Landscape (4:3) suits furniture, electronics and anything wide. object-fit: cover crops photos of other proportions without stretching, and the light grey background shows while a photo loads or if it fails.

Badges. The badge sits in the top-left corner of the image. Sale is red by convention, because a discount is an urgency signal that should stand apart from the brand palette. New and Bestseller use the accent. Choose None to remove the element rather than hide it.

Price and strikethrough. When the Sale badge is active and a "was" price is set, the old price appears in an <s> element after the current one, smaller and faded. For example, the default card shows $64.00 with $89.00 struck through. Many regions regulate "was" prices, and the UK and EU rules generally expect the old price to be a genuine recent selling price, so only fill that field with a real figure.

Star rating. Five inline SVG stars fill or outline according to the rating. The rating is rounded to whole stars, so 4.5 draws five stars and 4.4 draws four, and the label reads "Rated 5 out of 5" to match what is drawn. Stars use currentColor, so they take the accent colour.

Sizing. Width runs from 220 to 420 pixels as a max-width, so the card shrinks inside a narrower grid column but never grows past your setting. Padding runs 10 to 32 pixels, corner radius 0 to 28, and the button radius is separate so you can pair a rounded card with a square button or a pill button with a square card.

Reading the output

The preview updates as you change any field, and the code panel holds two blocks: the HTML first, then the CSS. The class names all start with product-, so they are unlikely to clash with an existing stylesheet. Paste the HTML once per product, replacing the text, and the CSS once per page. The preview uses a gradient placeholder where your photo goes; the exported <img> has no src, so add yours.

Tips and pitfalls

FAQ

Should the product card be a link or a button?

Both, in different places. The image and name should link to the product page; the add-to-cart control should be a button. Wrap the image and heading in an <a> or make the card clickable with an overlay pseudo-element on the heading link, and keep the <button> outside that link so it remains independently focusable.

How do I show a sale price correctly?

Put the current price first and the old price second inside an <s> element, as the generated markup does. Never show only a percentage without the actual price. If you need to be explicit for screen readers, add visually hidden text such as "was" before the old price and "now" before the new one.

What image size should product cards use?

Serve a square 600×600px image for a 300px card so it stays sharp on high-density screens, in WebP or AVIF at moderate quality. Use srcset with a 300px and 600px version so phones do not download the larger file, and add loading="lazy" to cards below the fold.

How do I make the stars show half ratings?

Half stars need a two-layer approach: a row of outlined stars with a row of filled stars clipped to a percentage width on top. The generated card rounds to whole stars for simplicity. For half-star support set the filled row's width to calc(rating / 5 * 100%) and overflow: hidden.

Can I add a wishlist or quick-view icon?

Yes. Position it like the badge but at top: 12px; right: 12px, as a <button> with an aria-label. Keep it inside the card's positioned container and give it a circular background so it stays visible over any product photo.

See also: all UI Components tools, Layout & Spacing, Shadows & Motion, Shapes & SVG, Forms & Inputs, Colour.

Related tools