Description
- adding t-shirt pricing calculator
- view demo – password: abc
- buy me a coffee

#1. Install Code
You can use an AI to tweak the code. You can also use this Calculator widget (free) if you need more style/options
#1.1. You can add a Code Block with this code
<!-- 09.26c14v1(v4) T-Shirt Pricing Calculator -->
<div class="tp-calc" data-tp-tshirt></div>
<script>
window.TShirtPricingCalcConfig = {
text: {
title: "",
quantityLabel: "Number of T-Shirts",
quantityHint: "Select the number of T-shirts you want to order.",
typeLabel: "Choose T-Shirt Type",
typeHint: "Select the type of T-shirt.",
printingLabel: "Choose Printing Option",
printingHint: "Select the type of printing option.",
totalHeading: "Total Cost",
totalHint: "The total cost for your order.",
unitPriceLabel: "Price per T-Shirt",
unitPriceHint: "Unit price of one T-shirt.",
discountLabel: "Discount",
discountHint: "Discount applied to your total order.",
ctaHeading: "Order Your Customized T-Shirts Now!",
ctaHint: "Take advantage of our competitive pricing and place your order today!",
ctaButton: "Place Order",
ctaHref: "/contact-us"
},
tags: {
title: "h2",
quantityLabel: "h3",
typeLabel: "h3",
printingLabel: "h3",
totalHeading: "h3",
unitPriceLabel: "h4",
discountLabel: "h4",
ctaHeading: "h2"
},
colors: {
title: "",
label: "",
smallText: "",
cardBg: "#e9f5ec",
cardHeading: "#111111",
cardValue: "#111111",
cardMuted: "rgba(17,17,17,0.55)"
},
slider: {
trackFill: "#2f8132",
trackEmpty: "rgba(17,17,17,0.05)",
thumbBg: "#ffffff",
thumbBorder: "rgba(17,17,17,0.1)",
trackHeight: "6px",
thumbSize: "24px"
},
layout: {
inputBorder: "1px solid rgba(17,17,17,0.2)"
},
button: {
text: "#ffffff",
bg: "#2f8132",
border: "#2f8132",
hoverText: "#ffffff",
hoverBg: "#276b29",
hoverBorder: "#276b29"
},
ranges: {
quantity: { min: 1, max: 200, step: 1, value: 1 }
},
types: [
{ label: "Basic", price: 10 },
{ label: "Premium", price: 18 },
{ label: "Organic", price: 22 }
],
printing: [
{ label: "None", price: 0 },
{ label: "Single Slide", price: 3 },
{ label: "Double Slide", price: 5 }
],
discountTiers: [
{ minQty: 1, rate: 0 },
{ minQty: 25, rate: 0.05 },
{ minQty: 50, rate: 0.10 },
{ minQty: 100, rate: 0.15 }
],
formula: {
currencySymbol: "$",
moneyDecimals: 0,
percentDecimals: 1,
totalFn: null
}
};
</script>
<script>
(function () {
var CFG = window.TShirtPricingCalcConfig;
var CSS =
".tp-calc,.tp-calc *{box-sizing:border-box}" +
".tp-calc{--tp-card-bg:#e9f5ec;--tp-track-fill:#2f8132;--tp-track-empty:rgba(17,17,17,0.05);--tp-thumb-bg:#fff;--tp-thumb-border:rgba(17,17,17,0.1);--tp-track-h:6px;--tp-thumb-size:24px;--tp-input-border:1px solid rgba(17,17,17,0.2);--tp-card-radius:22px;color:inherit}" +
".tp-calc__wrap{max-width:1180px;margin:40px auto;padding:0 24px;display:grid;grid-template-columns:1.1fr 0.9fr;gap:48px;align-items:start}" +
".tp-calc__h{margin:0}" +
".tp-calc__title{margin:0 0 32px}" +
".tp-calc__field{padding:14px 0}" +
".tp-calc__labelRow{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:18px}" +
".tp-calc__sm{margin:14px 0 0}" +
".tp-calc__pill{min-width:var(--tp-pill-min-width,64px);background:#fff;border:var(--tp-input-border);border-radius:12px;padding:12px 16px;display:inline-flex;align-items:center;justify-content:center;font-size:17px;color:#111}" +
".tp-calc__num{width:auto;min-width:1ch;border:0;background:transparent;padding:0;margin:0;color:inherit;text-align:center}" +
".tp-calc__unit{margin-left:6px}" +
".tp-calc__unit--tight{margin-left:2px}" +
".tp-calc__range{width:100%;-webkit-appearance:none;appearance:none;height:var(--tp-track-h);border-radius:999px;margin:4px 0 0;cursor:pointer;background:linear-gradient(90deg,var(--tp-track-fill) 0%,var(--tp-track-fill) var(--tp-fill,0%),var(--tp-track-empty) var(--tp-fill,0%),var(--tp-track-empty) 100%)}" +
".tp-calc__range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:var(--tp-thumb-size);height:var(--tp-thumb-size);border-radius:50%;background:var(--tp-thumb-bg);border:1px solid var(--tp-thumb-border);box-shadow:0 2px 6px rgba(0,0,0,.15);cursor:pointer}" +
".tp-calc__range::-moz-range-thumb{width:var(--tp-thumb-size);height:var(--tp-thumb-size);border-radius:50%;background:var(--tp-thumb-bg);border:1px solid var(--tp-thumb-border);box-shadow:0 2px 6px rgba(0,0,0,.15);cursor:pointer}" +
".tp-calc__minmax{display:flex;justify-content:space-between;margin-top:12px}" +
".tp-calc__selectWrap{position:relative;margin-top:4px}" +
".tp-calc__selectWrap::after{content:'';position:absolute;right:20px;top:50%;width:9px;height:9px;border-right:2px solid #111;border-bottom:2px solid #111;transform:translateY(-70%) rotate(45deg);pointer-events:none}" +
".tp-calc__select{width:100%;-webkit-appearance:none;appearance:none;border:var(--tp-input-border);border-radius:12px;padding:16px 46px 16px 18px;line-height:1.2;background:#fff;color:#111;cursor:pointer;font:inherit;font-size:18px}" +
".tp-calc__select:focus{outline:none}" +
".tp-calc__card{width:100%;background:var(--tp-card-bg);border-radius:var(--tp-card-radius);padding:44px}" +
".tp-calc__card .tp-calc__h{margin:0 0 4px}" +
".tp-calc__total{font-size:60px;line-height:1;margin:10px 0 6px}" +
".tp-calc__etaRow{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}" +
".tp-calc__etaVal{font-size:22px;white-space:nowrap}" +
".tp-calc__spacer{height:26px}" +
".tp-calc__spacer--lg{height:40px}" +
".tp-calc a.tp-calc__btn{display:block !important;width:100% !important;text-align:center !important;border-radius:10px !important;margin-top:20px}" +
"@media (max-width:980px){.tp-calc__wrap{grid-template-columns:1fr;gap:28px}.tp-calc__card{padding:34px}}" +
"@media (max-width:520px){.tp-calc__card{padding:28px}.tp-calc__total{font-size:52px}}";
function decl(prop, val) { return val ? prop + ":" + val + " !important;" : ""; }
function buttonCSS() {
var B = CFG.button;
var base = decl("color", B.text) + decl("background-color", B.bg) + decl("border-color", B.border);
var hover = decl("color", B.hoverText) + decl("background-color", B.hoverBg) + decl("border-color", B.hoverBorder);
var out = "";
if (base) out += ".tp-calc a.tp-calc__btn{" + base + "}";
if (hover) out += ".tp-calc a.tp-calc__btn:hover{" + hover + "}";
return out;
}
function injectCSS() {
if (window.__tshirtPricingCalcStyled) return;
window.__tshirtPricingCalcStyled = true;
var st = document.createElement("style");
st.type = "text/css";
st.textContent = CSS + buttonCSS();
document.head.appendChild(st);
}
function el(tag, cls, txt) {
var e = document.createElement(tag);
if (cls) e.className = cls;
if (txt != null) e.textContent = txt;
return e;
}
function heading(tag, txt, color) {
var e = el(tag, "tp-calc__h", txt);
if (color) e.style.color = color;
return e;
}
function smallP(txt, color) {
var e = el("p", "sqsrte-small tp-calc__sm", txt);
if (color) e.style.color = color;
return e;
}
function stepDecimals(step) {
var s = String(step);
var i = s.indexOf(".");
return i < 0 ? 0 : (s.length - i - 1);
}
function fmtNumber(v, decimals) {
return (+v).toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: decimals });
}
function formatMoney(n) {
var F = CFG.formula;
var d = Math.max(0, F.moneyDecimals | 0);
return F.currencySymbol + (+n).toLocaleString("en-US", { minimumFractionDigits: d, maximumFractionDigits: d });
}
function formatPercent(rate) {
var d = Math.max(0, CFG.formula.percentDecimals | 0);
return (rate * 100).toLocaleString("en-US", { minimumFractionDigits: d, maximumFractionDigits: d }) + "%";
}
function discountFor(qty) {
var tiers = CFG.discountTiers, rate = 0;
for (var i = 0; i < tiers.length; i++) {
if (qty >= tiers[i].minQty) rate = tiers[i].rate;
}
return rate;
}
function clampNum(v, min, max, decimals) {
v = +v;
if (!isFinite(v)) v = min;
v = Math.min(max, Math.max(min, v));
var f = Math.pow(10, decimals || 0);
return Math.round(v * f) / f;
}
var measureSpan;
function autosize(input) {
if (!measureSpan) {
measureSpan = document.createElement("span");
measureSpan.style.cssText = "position:absolute;visibility:hidden;white-space:pre;left:-9999px;top:0";
document.body.appendChild(measureSpan);
}
var cs = window.getComputedStyle(input);
measureSpan.style.fontFamily = cs.fontFamily;
measureSpan.style.fontSize = cs.fontSize;
measureSpan.style.fontWeight = cs.fontWeight;
measureSpan.style.fontStyle = cs.fontStyle;
measureSpan.style.letterSpacing = cs.letterSpacing;
measureSpan.textContent = input.value || "0";
input.style.width = (measureSpan.offsetWidth + 2) + "px";
}
function numField(o) {
var decimals = stepDecimals(o.r.step);
var node = el("div", "tp-calc__field");
var row = el("div", "tp-calc__labelRow");
row.appendChild(heading(o.tag, o.label, CFG.colors.label));
var pill = el("div", "tp-calc__pill");
var input = el("input", "tp-calc__num");
input.type = "text";
input.setAttribute("inputmode", decimals ? "decimal" : "numeric");
input.setAttribute("aria-label", o.label);
pill.appendChild(input);
if (o.suffix) {
pill.appendChild(el("span", "tp-calc__unit" + (o.suffixTight ? " tp-calc__unit--tight" : ""), o.suffix));
}
row.appendChild(pill);
node.appendChild(row);
var range = el("input", "tp-calc__range");
range.type = "range";
range.min = o.r.min; range.max = o.r.max; range.step = o.r.step; range.value = o.r.value;
range.setAttribute("aria-label", o.label);
node.appendChild(range);
var mm = el("div", "tp-calc__minmax");
var s1 = el("span", "sqsrte-small", labelText(o.r.min));
var s2 = el("span", "sqsrte-small", labelText(o.r.max));
if (CFG.colors.smallText) { s1.style.color = CFG.colors.smallText; s2.style.color = CFG.colors.smallText; }
mm.appendChild(s1); mm.appendChild(s2);
node.appendChild(mm);
if (o.hint) node.appendChild(smallP(o.hint, CFG.colors.smallText));
function labelText(v) {
var s = (o.prefix || "") + fmtNumber(v, decimals);
if (o.suffix) s += (o.suffixTight ? "" : " ") + o.suffix;
return s;
}
function disp(v) { return (o.prefix || "") + fmtNumber(v, decimals); }
function get() {
var cleaned = (input.value || "").replace(/[^0-9.]/g, "");
var v = cleaned === "" ? o.r.min : parseFloat(cleaned);
return clampNum(v, o.r.min, o.r.max, decimals);
}
function fill() {
var v = +range.value, min = +range.min, max = +range.max;
range.style.setProperty("--tp-fill", ((v - min) / (max - min)) * 100 + "%");
}
function sync(v) { range.value = v; fill(); autosize(input); }
var cb = function () {};
input.addEventListener("input", function () { autosize(input); cb(); });
input.addEventListener("change", function () { input.value = disp(get()); autosize(input); cb(); });
range.addEventListener("input", function () { input.value = disp(+range.value); autosize(input); cb(); });
input.value = disp(o.r.value);
fill();
return { node: node, get: get, sync: sync, onChange: function (f) { cb = f; } };
}
function selectField(o) {
var node = el("div", "tp-calc__field");
node.appendChild(heading(o.tag, o.label, CFG.colors.label));
var wrap = el("div", "tp-calc__selectWrap");
var select = el("select", "tp-calc__select");
select.setAttribute("aria-label", o.label);
for (var i = 0; i < o.options.length; i++) {
var opt = el("option", null, o.options[i].label);
opt.value = i;
select.appendChild(opt);
}
select.value = String(o.value || 0);
wrap.appendChild(select);
node.appendChild(wrap);
if (o.hint) node.appendChild(smallP(o.hint, CFG.colors.smallText));
var cb = function () {};
select.addEventListener("change", function () { cb(); });
return { node: node, get: function () { return +select.value; }, onChange: function (f) { cb = f; } };
}
function summaryRow(tag, label, hint) {
var row = el("div", "tp-calc__etaRow");
var lft = el("div");
lft.appendChild(heading(tag, label, CFG.colors.cardHeading));
if (hint) lft.appendChild(smallP(hint, CFG.colors.cardMuted));
var val = el("div", "tp-calc__etaVal");
if (CFG.colors.cardValue) val.style.color = CFG.colors.cardValue;
row.appendChild(lft); row.appendChild(val);
return { row: row, val: val };
}
function bigTotal(tag, headingText, hint) {
var frag = document.createDocumentFragment();
frag.appendChild(heading(tag, headingText, CFG.colors.cardHeading));
var val = el("div", "tp-calc__total");
if (CFG.colors.cardValue) val.style.color = CFG.colors.cardValue;
frag.appendChild(val);
frag.appendChild(smallP(hint, CFG.colors.cardMuted));
return { frag: frag, val: val };
}
function mount(root) {
if (!root || root.dataset.tpDone === "1") return;
root.dataset.tpDone = "1";
var T = CFG.text, G = CFG.tags, K = CFG.colors, S = CFG.slider, R = CFG.ranges, F = CFG.formula;
root.style.setProperty("--tp-card-bg", K.cardBg);
root.style.setProperty("--tp-track-fill", S.trackFill);
root.style.setProperty("--tp-track-empty", S.trackEmpty);
root.style.setProperty("--tp-thumb-bg", S.thumbBg);
root.style.setProperty("--tp-thumb-border", S.thumbBorder);
root.style.setProperty("--tp-track-h", S.trackHeight);
root.style.setProperty("--tp-thumb-size", S.thumbSize);
root.style.setProperty("--tp-input-border", CFG.layout.inputBorder);
var wrap = el("div", "tp-calc__wrap");
var left = el("div", "tp-calc__left");
var right = el("div", "tp-calc__right");
if (T.title) {
var title = heading(G.title, T.title, K.title);
title.classList.add("tp-calc__title");
left.appendChild(title);
}
var quantityField = numField({ label: T.quantityLabel, tag: G.quantityLabel, hint: T.quantityHint, r: R.quantity });
left.appendChild(quantityField.node);
var typeField = selectField({ label: T.typeLabel, tag: G.typeLabel, hint: T.typeHint, options: CFG.types, value: 0 });
left.appendChild(typeField.node);
var printingField = selectField({ label: T.printingLabel, tag: G.printingLabel, hint: T.printingHint, options: CFG.printing, value: 0 });
left.appendChild(printingField.node);
var card = el("div", "tp-calc__card");
var totalBlock = bigTotal(G.totalHeading, T.totalHeading, T.totalHint);
card.appendChild(totalBlock.frag);
card.appendChild(el("div", "tp-calc__spacer tp-calc__spacer--lg"));
var unitPriceRow = summaryRow(G.unitPriceLabel, T.unitPriceLabel, T.unitPriceHint);
card.appendChild(unitPriceRow.row);
card.appendChild(el("div", "tp-calc__spacer"));
var discountRow = summaryRow(G.discountLabel, T.discountLabel, T.discountHint);
card.appendChild(discountRow.row);
card.appendChild(el("div", "tp-calc__spacer tp-calc__spacer--lg"));
card.appendChild(heading(G.ctaHeading, T.ctaHeading, K.cardHeading));
card.appendChild(smallP(T.ctaHint, K.cardMuted));
var btn = el("a", "btn btn--border theme-btn--primary-inverse sqs-button-element--primary tp-calc__btn", T.ctaButton);
btn.setAttribute("href", T.ctaHref);
btn.setAttribute("rel", "noopener");
card.appendChild(btn);
right.appendChild(card);
wrap.appendChild(left); wrap.appendChild(right);
root.appendChild(wrap);
function recalc() {
var quantity = quantityField.get(); quantityField.sync(quantity);
var unitPrice = CFG.types[typeField.get()].price + CFG.printing[printingField.get()].price;
var subtotal = unitPrice * quantity;
var discountRate = discountFor(quantity);
var total = (typeof F.totalFn === "function")
? F.totalFn(subtotal, discountRate, unitPrice, quantity, F)
: subtotal * (1 - discountRate);
totalBlock.val.textContent = formatMoney(total);
unitPriceRow.val.textContent = formatMoney(unitPrice);
discountRow.val.textContent = formatPercent(discountRate);
}
quantityField.onChange(recalc);
typeField.onChange(recalc);
printingField.onChange(recalc);
recalc();
}
function init() {
var nodes = document.querySelectorAll("[data-tp-tshirt]");
for (var i = 0; i < nodes.length; i++) mount(nodes[i]);
}
function ready(fn) {
if (document.readyState !== "loading") fn();
else document.addEventListener("DOMContentLoaded", fn);
}
injectCSS();
ready(init);
if (!window.__tshirtPricingCalcBound) {
window.__tshirtPricingCalcBound = true;
window.addEventListener("mercury:load", init);
}
})();
</script>

#1.2. Change text, button text, url (line 06 – 24)
text: {
title: "",
quantityLabel: "Number of T-Shirts",
quantityHint: "Select the number of T-shirts you want to order.",
typeLabel: "Choose T-Shirt Type",
typeHint: "Select the type of T-shirt.",
printingLabel: "Choose Printing Option",
printingHint: "Select the type of printing option.",
totalHeading: "Total Cost",
totalHint: "The total cost for your order.",
unitPriceLabel: "Price per T-Shirt",
unitPriceHint: "Unit price of one T-shirt.",
discountLabel: "Discount",
discountHint: "Discount applied to your total order.",
ctaHeading: "Order Your Customized T-Shirts Now!",
ctaHint: "Take advantage of our competitive pricing and place your order today!",
ctaButton: "Place Order",
ctaHref: "/contact-us"
},
#1.3. Change style (line 25 – 62)
tags: {
title: "h2",
quantityLabel: "h3",
typeLabel: "h3",
printingLabel: "h3",
totalHeading: "h3",
unitPriceLabel: "h4",
discountLabel: "h4",
ctaHeading: "h2"
},
colors: {
title: "",
label: "",
smallText: "",
cardBg: "#e9f5ec",
cardHeading: "#111111",
cardValue: "#111111",
cardMuted: "rgba(17,17,17,0.55)"
},
slider: {
trackFill: "#2f8132",
trackEmpty: "rgba(17,17,17,0.05)",
thumbBg: "#ffffff",
thumbBorder: "rgba(17,17,17,0.1)",
trackHeight: "6px",
thumbSize: "24px"
},
layout: {
inputBorder: "1px solid rgba(17,17,17,0.2)"
},
button: {
text: "#ffffff",
bg: "#2f8132",
border: "#2f8132",
hoverText: "#ffffff",
hoverBg: "#276b29",
hoverBorder: "#276b29"
},
#1.4. Change value of T-Shirt Type, Printing Options, Discount (line 63 – 81)
ranges: {
quantity: { min: 1, max: 200, step: 1, value: 1 }
},
types: [
{ label: "Basic", price: 10 },
{ label: "Premium", price: 18 },
{ label: "Organic", price: 22 }
],
printing: [
{ label: "None", price: 0 },
{ label: "Single Slide", price: 3 },
{ label: "Double Slide", price: 5 }
],
discountTiers: [
{ minQty: 1, rate: 0 },
{ minQty: 25, rate: 0.05 },
{ minQty: 50, rate: 0.10 },
{ minQty: 100, rate: 0.15 }
],
#1.5. Change formula (line 82 – 87), you can use AI to write formula for you
formula: {
currencySymbol: "$",
moneyDecimals: 0,
percentDecimals: 1,
totalFn: null
}