By Tim King · Updated
Product Card CSS
Image Ratio, Sale Badge, Brand Line and Add-to-Cart Button Options, Accessible Markup
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
- Fill in the alt text. The exported image has
alt="", which tells screen readers to skip it. That is fine when the product name sits right below, but a short description such as "Grey merino crew-neck sweater" helps shoppers using image search and assistive technology. - Check button contrast. White text on the default orange accent (#ed8800) is about 2.6:1, below the 4.5:1 WCAG AA needs for normal-size text. Darken the accent or test your own colours in the contrast checker before you ship.
- Keep names short. Cards in a row only line up when the names wrap to the same number of lines. Two lines is a sensible limit; put the full name on the product page.
- Size the photos. A listing page might load 24 to 48 images at once. Serve them at roughly twice the card width for sharp screens and compress them, as covered in how to compress an image for the web.
- In a grid. Drop several cards into a CSS grid with
repeat(auto-fill, minmax(240px, 1fr))and they wrap responsively. The CSS grid generator builds that layout, and the pricing card builder covers subscription plans rather than products.
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
Blog Card Builder
Article preview cards with image, tag, excerpt and author.
Hover Card Builder
Card hover effects with timing controls, previewed live.
Comparison Card Builder
Side-by-side comparison cards with ticks, crosses and a highlighted column.
3D Tilt Card
Build a card that tilts in 3D toward the cursor with a glare.
404 Page Generator
Custom "page not found" HTML page with home link and search.