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 */