Tools – DTF Pricing Calculator

Below is a working example of a tool we coded – below that is the code so you can use it on your website as well or custom tailor it!

DTF Sizing & Pricing Calculator

DTF Sizing & Pricing Calculator

Garment Details

Size Qty Your Cost Client Price
S
M
L
XL
2XL
3XL
4XL
5XL
6XL

⚠️ Advanced Cost Adjustments

Image / Job Name:

Print Breakdown by Location:



  

Garment Breakdown:



  

Height:

Width:

Area per Unit: sq ft

Total Print Area: sq ft

Total Print Cost: $

Total Print Charge: $


Total Garment Cost: $

Total Garment Charge: $

Total Garment Qty:


Total Order Cost (Print + Garment): $

Total Client Charge (Print + Garment): $

Estimated Profit: $


Below is the Code Snippet you can use to insert into your site via HTML blocks


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>DTF Sizing & Pricing Calculator</title>
  <style>


.attention {
  color: red;
  font-weight: bold;
}

  body {
    font-family: Arial, sans-serif;
    background: #f4f4f4;
    padding: 20px;
  }

  h2 {
    text-align: center;
  }

  .calculator {
    background: #fff;
    border-radius: 8px;
    padding: 20px;
    box-shadow: 0 0 10px rgba(0,0,0,0.1);
  }

  label {
    display: block;
    margin-top: 15px;
  }

  input, select {
    width: 100%;
    padding: 8px;
    margin-top: 5px;
    border-radius: 4px;
    border: 1px solid #ccc;
  }

  button {
    margin-top: 20px;
    width: 100%;
    padding: 10px;
    background-color: #0073aa;
    color: #fff;
    border: none;
    border-radius: 4px;
    font-weight: bold;
    cursor: pointer;
  }

  .result {
    margin-top: 20px;
    padding: 15px;
    background-color: #e6ffe6;
    border-left: 4px solid #2e7d32;
    display: none;
  }

  .result p {
    margin: 6px 0;
  }

.add-button-red {
  background-color: #dc3545 !important; /* Bootstrap Red */
  color: white;
  border: none;
  padding: 10px 16px;
  margin-top: 10px;
  font-weight: bold;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.add-button-red:hover {
  background-color: #c82333;
}

</style>

</head>
<body>
  <h2>DTF Sizing & Pricing Calculator</h2>
  <div class="calculator">
    <label>
      Image / Job Name:
      <input type="text" id="jobName" placeholder="e.g. Window Decal Order">
    </label>

    <div id="printSections">
  <div class="print-section" data-index="1">
    <label>
      Print Location:
      <select class="printLocation">
        <option value="Front">Front</option>
        <option value="Left Chest">Left Chest</option>
        <option value="Right Chest">Right Chest</option>
        <option value="Back">Back</option>
        <option value="Left Sleeve">Left Sleeve</option>
        <option value="Right Sleeve">Right Sleeve</option>
        <option value="Other">Other</option>
      </select>
    </label>

    <label>
      Width:
      <input type="number" class="widthValue" step="0.01">
      <select class="widthUnit">
        <option value="inches">Inches</option>
        <option value="feet">Feet</option>
        <option value="yards">Yards</option>
        <option value="cm">Centimeters</option>
        <option value="meters">Meters</option>
      </select>
    </label>

    <label>
      Height:
      <input type="number" class="heightValue" step="0.01">
      <select class="heightUnit">
        <option value="inches">Inches</option>
        <option value="feet">Feet</option>
        <option value="yards">Yards</option>
        <option value="cm">Centimeters</option>
        <option value="meters">Meters</option>
      </select>
    </label>

    <label>
      Print Cost (Your Supplier Rate):
      <input type="number" class="costValue" step="0.01">
      <select class="costUnit">
        <option value="inches">Per Sq Inch</option>
        <option value="feet" selected>Per Sq Foot</option>
        <option value="yards">Per Sq Yard</option>
        <option value="cm">Per Sq CM</option>
        <option value="meters">Per Sq Meter</option>
      </select>
    </label>

    <label>
      Print Price (What You Charge Client):
      <input type="number" class="priceValue" step="0.01">
      <select class="priceUnit">
        <option value="inches">Per Sq Inch</option>
        <option value="feet" selected>Per Sq Foot</option>
        <option value="yards">Per Sq Yard</option>
        <option value="cm">Per Sq CM</option>
        <option value="meters">Per Sq Meter</option>
      </select>
    </label>

    <label>
      Print QTY:
      <input type="number" class="qtyValue" value="1" min="1">
    </label>

    <hr>
  </div>
</div>

<!-- Add Button -->
<button type="button" class="add-button-red" onclick="addPrintSection()">Add Print Location</button>


<div id="garmentSections">
  <div class="garment-section" data-index="1">
    <h3>Garment Details</h3>
    <label>
      Garment Name / Style / Color:
      <input type="text" class="garmentName" placeholder="e.g. Gildan 5000 - White Tee">
    </label>

    <div style="overflow-x:auto; margin-top: 10px;">
      <table style="width:100%; border-collapse: collapse;">
        <thead>
          <tr>
            <th style="text-align:left;">Size</th>
            <th>Qty</th>
            <th>Your Cost</th>
            <th>Client Price</th>
          </tr>
        </thead>
        <tbody>
          <tr><td>S</td><td><input type="number" class="garmentQty" data-size="S" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="S" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="S" value="0" step="0.01"></td></tr>
          <tr><td>M</td><td><input type="number" class="garmentQty" data-size="M" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="M" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="M" value="0" step="0.01"></td></tr>
          <tr><td>L</td><td><input type="number" class="garmentQty" data-size="L" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="L" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="L" value="0" step="0.01"></td></tr>
          <tr><td>XL</td><td><input type="number" class="garmentQty" data-size="XL" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="XL" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="XL" value="0" step="0.01"></td></tr>
          <tr><td>2XL</td><td><input type="number" class="garmentQty" data-size="2XL" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="2XL" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="2XL" value="0" step="0.01"></td></tr>
          <tr><td>3XL</td><td><input type="number" class="garmentQty" data-size="3XL" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="3XL" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="3XL" value="0" step="0.01"></td></tr>
          <tr><td>4XL</td><td><input type="number" class="garmentQty" data-size="4XL" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="4XL" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="4XL" value="0" step="0.01"></td></tr>
          <tr><td>5XL</td><td><input type="number" class="garmentQty" data-size="5XL" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="5XL" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="5XL" value="0" step="0.01"></td></tr>
          <tr><td>6XL</td><td><input type="number" class="garmentQty" data-size="6XL" value="0" min="0"></td><td><input type="number" class="garmentCost" data-size="6XL" value="0" step="0.01"></td><td><input type="number" class="garmentPrice" data-size="6XL" value="0" step="0.01"></td></tr>
        </tbody>
      </table>
    </div>
    <hr>
  </div>
</div>

<!-- Add Button -->
<button type="button" class="add-button-red" onclick="addGarmentSection()">Add Another Garment</button>

<div style="border: 2px dashed red; padding: 15px; margin-top: 20px;">
  <h3 class="attention">⚠️ Advanced Cost Adjustments</h3>

  <!-- Additional Print Supplier Costs -->
<label class="attention">Print Shipping (Your Cost)</label>
<input type="number" id="printShipping" value="0" step="0.01" placeholder="Flat $ amount">

<label class="attention">Print Tax % (Your Cost)</label>
<input type="number" id="printTax" value="0" step="0.1" placeholder="Percent (e.g. 8.5)">

<label class="attention">Transaction Fee Surcharge % (Print Supplier)</label>
<input type="number" id="printTransactionFee" value="0" step="0.1" placeholder="Percent (e.g. 3)">


  <!-- Garment Supplier Costs -->
  <label class="attention">Garment Shipping (Your Cost)</label>
  <input type="number" id="garmentShipping" value="0" step="0.01" placeholder="Flat $ amount">

  <label class="attention">Garment Tax % (Your Cost)</label>
  <input type="number" id="garmentTax" value="0" step="0.1" placeholder="Percent (e.g. 8.5)">

  <label class="attention">Garment Transaction Fee % (Your Cost)</label>
  <input type="number" id="garmentTransactionFee" value="0" step="0.1" placeholder="Percent (e.g. 3)">

  <!-- Client Charges -->
  <label class="attention">Client Shipping Fee</label>
  <input type="number" id="clientShippingFee" value="0" step="0.01" placeholder="Flat $ amount">

  <label class="attention">Client Sales Tax %</label>
  <input type="number" id="clientTax" value="0" step="0.1" placeholder="Percent (e.g. 6.75)">

  <label class="attention">Client Transaction Fee % (Optional)</label>
  <input type="number" id="clientSurcharge" value="0" step="0.1" placeholder="Percent (e.g. 3)">
</div>

<label class="attention">Actual Shipping to Client (UPS/FedEx/USPS)</label>
<input type="number" id="actualShippingToClient" value="0" step="0.01" placeholder="Flat $ amount">


    <button onclick="calculate()">Calculate</button>

  <div class="result" id="resultBox">
  <p><strong>Image / Job Name:</strong> <span id="outJob"></span></p>

  <p><strong>Print Breakdown by Location:</strong></p>
  <pre id="printBreakdownText" style="background: #eef; padding: 10px; white-space: pre-wrap;"></pre>

  <p><strong>Garment Breakdown:</strong></p>
  <pre id="garmentBreakdownText" style="background: #ffe; padding: 10px; white-space: pre-wrap;"></pre>

  <p><strong>Height:</strong> <span id="outHeight"></span></p>
  <p><strong>Width:</strong> <span id="outWidth"></span></p>
  <p><strong>Area per Unit:</strong> <span id="areaUnit"></span> sq ft</p>
  <p><strong>Total Print Area:</strong> <span id="areaTotal"></span> sq ft</p>
  <p><strong>Total Print Cost:</strong> $<span id="outPrintCost"></span></p>
  <p><strong>Total Print Charge:</strong> $<span id="outPrintPrice"></span></p>

  <hr>

  <p><strong>Total Garment Cost:</strong> $<span id="outGarmentCost"></span></p>
  <p><strong>Total Garment Charge:</strong> $<span id="outGarmentPrice"></span></p>
  <p><strong>Total Garment Qty:</strong> <span id="outGarmentQty"></span></p>

  <hr>

  <p><strong>Total Order Cost (Print + Garment):</strong> $<span id="costTotal"></span></p>
<p><strong>Total Client Charge (Print + Garment):</strong> $<span id="priceTotal"></span></p>
<p><strong>Estimated Profit:</strong> $<span id="profit"></span></p>

<!-- Dynamically injected adjusted cost outputs go here -->
  <div id="adjustedCostsBox"></div>
</div>



 <script>
let printSectionIndex = 1;

function addPrintSection() {
  printSectionIndex++;

  const printSections = document.getElementById('printSections');
  const firstSection = printSections.querySelector('.print-section');
  const newSection = firstSection.cloneNode(true);

  // Reset inputs inside clone
  newSection.setAttribute('data-index', printSectionIndex);
  newSection.querySelectorAll('input').forEach(input => input.value = input.type === "number" ? 0 : "");
  newSection.querySelectorAll('select').forEach(select => {
  if (select.classList.contains('priceUnit') || select.classList.contains('costUnit')) {
    select.value = 'feet'; // default to Per Sq Ft
  } else {
    select.selectedIndex = 0;
  }
});


  printSections.appendChild(newSection);
}

function convertToSqFt(value, unit) {
  const unitMap = {
    inches: value => (value / 12),
    feet: value => value,
    yards: value => (value * 3),
    cm: value => (value / 30.48),
    meters: value => (value * 3.28084)
  };
  return unitMap[unit](value);
}

function convertRateToSqFt(rate, unit) {
  const conversion = {
    inches: 144,
    feet: 1,
    yards: 1/9,
    cm: 929.03,
    meters: 10.7639
  };
  return rate / conversion[unit];
}

//Garment Script
function addGarmentSection() {
  const sections = document.querySelectorAll('.garment-section');
  const last = sections[sections.length - 1];
  const clone = last.cloneNode(true);

  // Clear all inputs inside the clone
  clone.querySelectorAll('input').forEach(input => {
    if (input.type === "number") input.value = 0;
    else input.value = "";
  });

  document.getElementById('garmentSections').appendChild(clone);
}


function calculate() {

  const jobName = document.getElementById('jobName').value || 'Untitled Job';
  let totalPrintCost = 0;
  let totalPrintPrice = 0;

  let printBreakdown = "";

  const printSections = document.querySelectorAll('.print-section');

  printSections.forEach((section, i) => {
    const location = section.querySelector('.printLocation').value;
    const hVal = parseFloat(section.querySelector('.heightValue').value);
    const hUnit = section.querySelector('.heightUnit').value;
    const wVal = parseFloat(section.querySelector('.widthValue').value);
    const wUnit = section.querySelector('.widthUnit').value;
    const printQty = parseInt(section.querySelector('.qtyValue').value);
    const price = parseFloat(section.querySelector('.priceValue').value);
    const priceUnit = section.querySelector('.priceUnit').value;
    const cost = parseFloat(section.querySelector('.costValue').value);
    const costUnit = section.querySelector('.costUnit').value;

    if (isNaN(hVal) || isNaN(wVal) || isNaN(printQty) || isNaN(price) || isNaN(cost)) {
      alert(`Please fill in all print fields for section ${i + 1}.`);
      return;
    }

    const hFeet = convertToSqFt(hVal, hUnit);
    const wFeet = convertToSqFt(wVal, wUnit);
    const areaPerUnit = hFeet * wFeet;
    const totalArea = areaPerUnit * printQty;

    const pricePerSqFt = convertRateToSqFt(price, priceUnit);
    const costPerSqFt = convertRateToSqFt(cost, costUnit);

    const sectionPrintPrice = totalArea * pricePerSqFt;
    const sectionPrintCost = totalArea * costPerSqFt;

    totalPrintPrice += sectionPrintPrice;
    totalPrintCost += sectionPrintCost;

    printBreakdown += `➤ Location: ${location}\n`;
    printBreakdown += `Area: ${totalArea.toFixed(2)} sq ft\n`;
    printBreakdown += `Cost: $${sectionPrintCost.toFixed(2)}\n`;
    printBreakdown += `Charge: $${sectionPrintPrice.toFixed(2)}\n\n`;
  });

// Garment Breakdown Logic Section
let totalGarmentQty = 0;
let totalGarmentCost = 0;
let totalGarmentCharge = 0;
let garmentBreakdown = '';

const garmentSections = document.querySelectorAll('.garment-section');


garmentSections.forEach((section, index) => {
  const name = section.querySelector('.garmentName').value || `Garment #${index + 1}`;
  const sizeInputs = section.querySelectorAll('.garmentQty');
  const costInputs = section.querySelectorAll('.garmentCost');
  const chargeInputs = section.querySelectorAll('.garmentPrice');

  let subQty = 0;
  let subCost = 0;
  let subCharge = 0;

  garmentBreakdown += `► Garment: ${name}\n`;

  sizeInputs.forEach((input, i) => {
    const size = input.dataset.size;
    const qty = parseInt(input.value) || 0;
    const cost = parseFloat(costInputs[i].value) || 0;
    const charge = parseFloat(chargeInputs[i].value) || 0;

    if (qty > 0) {
      garmentBreakdown += `  • ${size}: ${qty} @ $${cost.toFixed(2)} | $${charge.toFixed(2)}\n`;
      subQty += qty;
      subCost += qty * cost;
      subCharge += qty * charge;
    }
  });

  garmentBreakdown += `  Total Qty: ${subQty}\n`;
  garmentBreakdown += `  Total Cost: $${subCost.toFixed(2)}\n`;
  garmentBreakdown += `  Total Charge: $${subCharge.toFixed(2)}\n\n`;

  // 👇 Add these 3 lines here
  totalGarmentQty += subQty;
  totalGarmentCost += subCost;
  totalGarmentCharge += subCharge;
});


// --- Advanced Cost Adjustments ---

// PRINT SUPPLIER Cost Adjustments
const printShipping = parseFloat(document.getElementById('printShipping')?.value || 0);
const printTax = parseFloat(document.getElementById('printTax')?.value || 0);
const printTransactionFee = parseFloat(document.getElementById('printTransactionFee')?.value || 0);

const printTaxAmount = (totalPrintCost * printTax) / 100;
const printFeeAmount = (totalPrintCost * printTransactionFee) / 100;

const adjustedTotalPrintCost = totalPrintCost + printShipping + printTaxAmount + printFeeAmount;

// GARMENT SUPPLIER Cost Adjustments
const garmentShipping = parseFloat(document.getElementById('garmentShipping')?.value || 0);
const garmentTaxPercent = parseFloat(document.getElementById('garmentTax')?.value || 0);
const garmentFeePercent = parseFloat(document.getElementById('garmentTransactionFee')?.value || 0);

const garmentTaxAmount = (totalGarmentCost * garmentTaxPercent) / 100;
const transactionFeeAmountSupplier = ((totalGarmentCost + totalPrintCost) * garmentFeePercent) / 100;

const adjustedTotalGarmentCost = totalGarmentCost + garmentShipping + garmentTaxAmount + transactionFeeAmountSupplier;

// CLIENT-SIDE Adjustments
const clientShippingFee = parseFloat(document.getElementById('clientShippingFee')?.value || 0);
const clientTaxPercent = parseFloat(document.getElementById('clientTax')?.value || 0);
const clientSurchargePercent = parseFloat(document.getElementById('clientSurcharge')?.value || 0);

const subtotalForCustomer = totalPrintPrice + totalGarmentCharge;
const clientTaxAmount = (subtotalForCustomer * clientTaxPercent) / 100;
const clientSurchargeAmount = (subtotalForCustomer * clientSurchargePercent) / 100;

const adjustedTotalPrintPrice = totalPrintPrice; // currently unchanged
const adjustedTotalGarmentCharge = totalGarmentCharge + clientShippingFee + clientTaxAmount + clientSurchargeAmount;

// FINAL TOTALS (Unadjusted)
const totalCost = totalPrintCost + totalGarmentCost;
const totalCharge = totalPrintPrice + totalGarmentCharge;
const profit = totalCharge - totalCost;

// Get actual shipping to client value
const actualShippingToClient = parseFloat(document.getElementById('actualShippingToClient')?.value || 0);

// FINAL TOTALS (Adjusted)
const totalCostAdjusted = adjustedTotalPrintCost + adjustedTotalGarmentCost + actualShippingToClient;
const totalChargeAdjusted = adjustedTotalPrintPrice + adjustedTotalGarmentCharge;
const profitAdjusted = totalChargeAdjusted - totalCostAdjusted;



  // Output

//copy breakdown style for each garment to match print location breakdowns

document.getElementById('outJob').innerText = jobName;


document.getElementById('garmentBreakdownText').innerHTML = garmentBreakdown
  .split('\n\n')
  .map(block => {
    const lines = block.trim().split('\n');
    const title = lines[0].replace('➤ ', '');
    const body = lines.slice(1).join('\n');
    return `<details><summary><strong>${title}</strong></summary><pre>${body}</pre></details>`;
  })
  .join('');


  document.getElementById('outWidth').innerText = 'Multiple';
document.getElementById('outHeight').innerText = 'Multiple';
document.getElementById('areaUnit').innerText = 'N/A';
document.getElementById('areaTotal').innerText = totalPrintPrice > 0 ? totalPrintPrice.toFixed(2) : '-';

  document.getElementById('outPrintCost').innerText = totalPrintCost.toFixed(2);
  document.getElementById('outPrintPrice').innerText = totalPrintPrice.toFixed(2);

  document.getElementById('outGarmentQty').innerText = totalGarmentQty;
  document.getElementById('outGarmentCost').innerText = totalGarmentCost.toFixed(2);
  document.getElementById('outGarmentPrice').innerText = totalGarmentCharge.toFixed(2);

  document.getElementById('costTotal').innerText = totalCost.toFixed(2);
  document.getElementById('priceTotal').innerText = totalCharge.toFixed(2);
  document.getElementById('profit').innerText = profit.toFixed(2);

document.getElementById('printBreakdownText').innerText = printBreakdown.trim();


// Calculate adjusted totals
const trueTotalCost = totalCost + garmentShipping + garmentTaxAmount + transactionFeeAmountSupplier;
const trueTotalCharge = totalCharge + clientShippingFee + clientTaxAmount + clientSurchargeAmount;
const trueProfit = trueTotalCharge - trueTotalCost;


// Build updated Adjusted Cost Output in proper order

const supplierCostsHTML = `
  <hr>
  <h4>Supplier-Side Cost Adjustments:</h4>
  <p><strong>Print Shipping:</strong> $${printShipping.toFixed(2)}</p>
  <p><strong>Print Tax:</strong> $${printTaxAmount.toFixed(2)}</p>
  <p><strong>Print Transaction Fee:</strong> $${printFeeAmount.toFixed(2)}</p>
  <p><strong>Garment Shipping:</strong> $${garmentShipping.toFixed(2)}</p>
  <p><strong>Garment Tax:</strong> $${garmentTaxAmount.toFixed(2)}</p>
  <p><strong>Garment Transaction Fee:</strong> $${transactionFeeAmountSupplier.toFixed(2)}</p>
`;

const clientCostsHTML = `
  <h4>Customer-Side Charge Adjustments:</h4>
  <p><strong>Client Shipping Fee:</strong> $${clientShippingFee.toFixed(2)}</p>
  <p><strong>Client Tax:</strong> $${clientTaxAmount.toFixed(2)}</p>
  <p><strong>Client Surcharge:</strong> $${clientSurchargeAmount.toFixed(2)}</p>
`;

const adjustedTotalsHTML = `
  <hr>
  <p><strong>Adjusted Totals (Including Supplier & Client Adjustments):</strong></p>
  <p><strong>Adjusted Order Cost (Print + Garment + Supplier Costs + Your Shipping):</strong> $${totalCostAdjusted.toFixed(2)}</p>
  <p><strong>Adjusted Client Charge (Print + Garment + Client Costs):</strong> $${totalChargeAdjusted.toFixed(2)}</p>
  <p><strong>Adjusted Profit:</strong> $${profitAdjusted.toFixed(2)}</p>
`;


// Append cleanly in correct order
document.getElementById('adjustedCostsBox').innerHTML = supplierCostsHTML + clientCostsHTML + adjustedTotalsHTML;


  document.getElementById('resultBox').style.display = 'block';

  // Optional: print breakdown to console or alert (add below if desired)
  console.log(printBreakdown);
}
</script>


</body>
</html>
JavaScript