v133 · css

Product Card

Four data attributes — data-price, data-rating, data-stock, data-discount — drive everything visual: the price counter, the star fill, the stock bar underline, and the out-of-stock state. Zero inline styles; all values come from HTML attributes via typed attr().

Feature detection: checking…

Every visual state is derived from HTML data attributes. Click a card's "Edit" to change attributes and watch the CSS respond in real time.

Attribute → CSS mapping
data-price type(<integer>) counter-reset: price attr(…) → price counter
data-rating integer (selector) [data-rating="N"] .star:nth-child(-n+N) → star fill
data-stock type(<number>) width: calc(attr(…) * 1%) → stock bar
data-discount presence [data-discount] .badge { display: block } → ribbon
/* Price counter from integer attribute */
.product-price {
  counter-reset: price attr(data-price type(), 0);
}
.product-price::before { content: '$' counter(price); }

/* Stock bar from number attribute */
.product-card::before {
  content: '';
  width: calc(attr(data-stock type(), 50) * 1%);
  height: 3px;
  background: green;
}

/* No JS needed — just update data-price="49" in HTML */

see also