Add-on Checklist Total
A copy-paste pricing tables component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
Pricing TablesHTMLJavaScriptCSSany framework
+$10
+$15
+$8
Total $38/mo
Copy into your project
HTML
<!-- Add-on Checklist Total — checking items updates the running total -->
<div class="nuda-pr2-addon-total">
<div class="nuda-pr2-addon-total__row">
<label class="nuda-pr2-addon-total__label">
<input class="nuda-pr2-addon-total__checkbox" type="checkbox" checked data-price="10" />
Extra seats
</label>
<span class="nuda-pr2-addon-total__price">+$10</span>
</div>
<div class="nuda-pr2-addon-total__row">
<label class="nuda-pr2-addon-total__label">
<input class="nuda-pr2-addon-total__checkbox" type="checkbox" data-price="15" />
Priority support
</label>
<span class="nuda-pr2-addon-total__price">+$15</span>
</div>
<div class="nuda-pr2-addon-total__row">
<label class="nuda-pr2-addon-total__label">
<input class="nuda-pr2-addon-total__checkbox" type="checkbox" checked data-price="8" />
Extra storage
</label>
<span class="nuda-pr2-addon-total__price">+$8</span>
</div>
<div class="nuda-pr2-addon-total__divider"></div>
<div class="nuda-pr2-addon-total__total">Total <b>$38</b><i>/mo</i></div>
</div>JavaScript
/* Add-on Checklist Total — sums the base plan + checked add-ons. */
(function () {
var card = document.querySelector('.nuda-pr2-addon-total');
if (!card) return;
var base = 20;
var boxes = card.querySelectorAll('.nuda-pr2-addon-total__checkbox');
var totalEl = card.querySelector('.nuda-pr2-addon-total__total');
var totalB = totalEl.querySelector('b');
function recalc() {
var sum = base;
boxes.forEach(function (b) {
if (b.checked) sum += Number(b.dataset.price || 0);
});
totalB.textContent = '$' + sum;
totalEl.classList.remove('is-updated');
void totalEl.offsetWidth; // restart animation
totalEl.classList.add('is-updated');
}
boxes.forEach(function (b) { b.addEventListener('change', recalc); });
})();CSS
.nuda-pr2-addon-total {
display: flex;
flex-direction: column;
gap: 8px;
padding: 14px;
width: 190px;
background: rgba(255,255,255,.03);
border: 1px solid rgba(255,255,255,.08);
border-radius: 12px;
}
.nuda-pr2-addon-total__row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.nuda-pr2-addon-total__label {
display: flex;
align-items: center;
gap: 8px;
font: 500 10px ui-sans-serif,system-ui;
color: #cfcfcf;
cursor: pointer;
min-height: 28px;
}
.nuda-pr2-addon-total__checkbox {
appearance: none;
-webkit-appearance: none;
width: 16px;
height: 16px;
flex-shrink: 0;
border-radius: 4px;
border: 1px solid rgba(255,255,255,.2);
background: transparent;
cursor: pointer;
position: relative;
transition: background .2s,border-color .2s,transform .2s;
}
.nuda-pr2-addon-total__checkbox:checked {
background: #e4ff54;
border-color: #e4ff54;
transform: scale(1.05);
}
.nuda-pr2-addon-total__checkbox:checked::after {
content: "";
position: absolute;
left: 3px;
top: 0;
width: 4px;
height: 8px;
border: solid #09090b;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
.nuda-pr2-addon-total__checkbox:focus-visible {
outline: 2px solid #e4ff54;
outline-offset: 2px;
}
.nuda-pr2-addon-total__price {
font: 600 10px ui-sans-serif,system-ui;
color: #a1a1aa;
font-variant-numeric: tabular-nums;
}
.nuda-pr2-addon-total__divider {
height: 1px;
background: rgba(255,255,255,.08);
margin: 2px 0;
}
.nuda-pr2-addon-total__total {
font: 600 10px ui-sans-serif,system-ui;
color: #a1a1aa;
display: flex;
align-items: baseline;
gap: 2px;
}
.nuda-pr2-addon-total__total b {
font: 800 16px ui-sans-serif,system-ui;
color: #fafafa;
font-variant-numeric: tabular-nums;
}
.nuda-pr2-addon-total__total.is-updated b {
animation: nuda-pr2-addon-total-pop .35s ease;
}
@keyframes nuda-pr2-addon-total-pop {
0% {
transform: scale(1.15);
filter: drop-shadow(0 0 6px rgba(228,255,84,.6));
}
100% {
transform: scale(1);
filter: drop-shadow(0 0 0 rgba(228,255,84,0));
}
}
@media (prefers-reduced-motion:reduce) {
.nuda-pr2-addon-total__checkbox {
transition: none;
}
.nuda-pr2-addon-total__total.is-updated b {
animation: none !important;
}
}
How to use Add-on Checklist Total
Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.
Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.