CSS has evolved far beyond simple styling. With modern features like calc(), attr(), and the :has() selector, you can perform real-time calculations and display dynamic prices directly in the browser — no JavaScript required. Imagine showing discounted prices, sale tags, or progress bars with zero server round trips. In this listicle, we’ll explore ten powerful CSS techniques that let you compute and display discounted prices purely with stylesheets. Whether you’re building an e‑commerce site or a subscription service, these tricks will make your pages faster and more maintainable. Let’s dive in!
1. CSS Math: More Than Just Layout
CSS isn’t only about colors and positioning. Functions like calc() let you perform arithmetic on numeric values — adding, subtracting, multiplying, or dividing lengths and percentages. But you can also use them for numeric data display. For example, you can calculate the percentage of tasks completed in a to‑do list or, as we’ll see, the final price after a discount. All this happens without scripting, preserving performance and simplifying your codebase.

2. The attr() Function: Fetching Data from Attributes
Data attributes (data-*) store information directly in HTML. The attr() CSS function reads those values. In modern browsers (with the type parameter), attr(data-price number) returns a number you can use inside calc(). This lets you store base prices and discount percentages as attributes, then compute the discounted price entirely in CSS.
3. Building the Markup for Dynamic Pricing
Start with a list of services (e.g., Netflix, Disney+). Each item includes a label with the service name, a div containing the base price and discount (data-price, data-discount), and a checkbox to toggle the discount. The markup stays clean: no JavaScript, only semantic HTML with data attributes ready for CSS consumption.
<li>
<label>
<span>Netflix</span>
<div class="ott-price" data-price="7.99" data-discount="0.2">$7.99</div>
<input type="checkbox" class="is-ott-discounted">
</label>
</li>
4. The :has() Selector: Reacting to User Toggles
The :has() pseudo‑class lets you style a parent element based on the state of its descendants. When a child checkbox (like “Apply Student Discount”) is checked, :has() applies styles to the parent .ott container. This is the key to creating interactive pricing without any JavaScript event listeners.
5. Strike Through the Original Price
Once the discount toggle is activated, the first visual change is to cross out the base price. Using .ott:has(.is-ott-discounted:checked) .ott-price { text-decoration: line-through; }, the original price receives a strikethrough, clearly indicating it’s no longer the current price.
6. Calculating the Discounted Price with calc()
Now for the math. Use calc() together with attr() to compute the sale price: e.g., --discounted-price: calc(attr(data-price number) * (1 - attr(data-discount number)));. Then display that value using a pseudo-element or a custom property as the content of a ::after element. The calculation happens live as soon as the discount is toggled.

7. Showing the Discount Amount or Percentage
You can also compute the absolute discount or the percentage saved. For instance, --savings: calc(attr(data-price number) - var(--discounted-price));. Display this in a separate span using a counter or attr() based content. This gives users a clear sense of how much they’re saving.
8. Interactivity with Checkboxes and Labels
Checkboxes serve as the user interface. A label styled as a button toggles the student discount. The :has() selector watches the checkbox state and triggers the CSS calculations. This approach is accessible (checkboxes are natively keyboard‑friendly) and requires zero JavaScript — just HTML and CSS.
9. Browser Support and Future Readiness
While attr() with a numeric type and :has() are still gaining traction (Chrome 105+, Firefox 120+, Safari TP), they represent the future of CSS interactivity. For now, you can use fallbacks: a small JavaScript snippet to set CSS custom properties if the browser doesn’t support attr() in calc(). The technique is still worth learning for when support becomes universal.
10. Real‑World Applications Beyond Pricing
This pattern applies to more than e‑commerce. Use it for subscription tiers, donation sliders, progress trackers, or even real‑time loan calculators. Anywhere you have numeric data and user choices, CSS can compute and update the display instantly. The result: faster pages, simpler code, and a better user experience.
CSS is no longer just a styling language — it’s a tool for dynamic data presentation. By combining calc(), attr(), and :has(), you can create interactive pricing displays that rival JavaScript solutions in speed and simplicity. Start experimenting with these techniques today, and when browser support catches up, you’ll be ready to build blazing‑fast, script‑free interfaces.