{"id":9872,"date":"2025-10-13T09:59:50","date_gmt":"2025-10-13T09:59:50","guid":{"rendered":"https:\/\/qxaccounting.com\/uk\/?page_id=9872"},"modified":"2026-01-23T10:55:28","modified_gmt":"2026-01-23T10:55:28","slug":"payroll-calculator","status":"publish","type":"page","link":"https:\/\/qxaccounting.com\/uk\/tools-for-accountants\/payroll-calculator\/","title":{"rendered":"Content Payroll Calculator UK"},"content":{"rendered":"              <section class=\"bannerstyle2\" style=\"min-height: 250px;\">\r\n                    <div class=\"container\">\r\n                    <div class=\"row d-flex align-items-start justify-content-between\">\r\n                    <div class=\"col-xxl-6 col-lg-7 d-flex flex-column align-items-start content\">\r\n                     <h1>Free Online Payroll Calculator for the 2025\/26 UK Tax Year<\/h1>\n<p>Easily work out payroll costs for UK businesses, including gross salary, employer National Insurance, pension contributions, and deductions. Updated with the latest HMRC 2025 to 2026 rules to help employers and HR teams calculate pay accurately.<\/p>\n                <\/div>\r\n                    <div class=\"col-lg-5 d-none d-lg-block align-self-baseline\"><div class=\"imagebox\">\r\n                        <img decoding=\"async\" src=\"https:\/\/qxaccounting.com\/uk\/wp-content\/uploads\/sites\/2\/2025\/10\/calculator.webp\" alt=\"\"><\/div><\/div>\r\n                    <\/div>\r\n                    <\/div>\r\n            <\/section>\r\n       \r\n\n\n\n<!DOCTYPE html> \n\n<html lang=\"en\"> \n\n<head> \n\n  <meta charset=\"UTF-8\" \/> \n\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" \/> \n\n  <title>Payroll Calculator UK (2025\/2026)<\/title> \n\n  <style> \n\n    :root{ \n\n      \/* QX UK-inspired light theme *\/ \n\n      --bg:#ffffff;             \/* page background *\/ \n\n      --card:#ffffff;           \/* cards *\/ \n\n      --ink:#0a1f44;            \/* primary text: deep navy *\/ \n\n      --muted:#5a6b82;          \/* secondary text *\/ \n\n      --accent:#2d6bff;         \/* QX-style royal blue *\/ \n\n      --accent-ink:#ffffff;     \/* text on accent *\/ \n\n      --gold:#b37f4f;           \/* warm bronze accent used across QX *\/ \n\n      --line:#e6edf7;           \/* light divider *\/ \n\n      --good:#1f9e63;           \/* success green *\/ \n\n      --bad:#d64545;            \/* error red *\/ \n\n      --soft:#f5f8ff;           \/* very light blue background *\/ \n\n    } \n\n    *{box-sizing:border-box} \n\n    body{margin:0;background:var(--bg);font:16px\/1.5 system-ui,Segoe UI,Roboto,Helvetica,Arial;color:var(--ink)} \n\n    .wrap{max-width:1100px;margin:0 auto;padding:32px 16px} \n\n \n\n    \n\n    .pill{display:inline-block;padding:.35rem .7rem;border:1px solid #e6d6c9;border-radius:999px;background:color-mix(in oklab, var(--gold) 20%, white);color:#7a5535;font-weight:700;font-size:.8rem} \n\n \n\n    \/* BANNER *\/ \n\n\n    \/* LAYOUT *\/ \n\n    .grid{display:grid;gap:14px;grid-template-columns:1.3fr 1fr} \n\n    @media (max-width:960px){.grid{grid-template-columns:1fr}} \n\n \n\n    \/* CARDS *\/ \n\n    .card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:16px;box-shadow:0 1px 0 rgba(0,0,0,.02)} \n\n    .card h3{margin:0 0 10px 0;color:var(--ink)} \n\n \n\n    \/* FORM *\/ \n\n    label{display:block;font-weight:700;font-size:.9rem;margin:.35rem 0;color:var(--ink)} \n\n    input,select{width:100%;padding:10px 12px;border-radius:10px;border:1px solid var(--line);background:#fff;color:var(--ink)} \n\n    input:focus,select:focus{outline:2px solid color-mix(in oklab, var(--accent) 25%, transparent)} \n\n   #newk .row{display:grid;grid-template-columns:1fr 1fr;gap:10px} \n\n    .row3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px} \n\n \n\n    \/* BUTTONS *\/ \n\n   #newk .btn{display:inline-flex;align-items:center;gap:8px;padding:10px 14px;border-radius:12px;border:1px solid color-mix(in oklab, var(--accent) 20%, white);background:var(--accent);color:var(--accent-ink);font-weight:800;cursor:pointer;transition:transform .05s ease, box-shadow .2s ease} \n\n   #newk .btn:hover{transform:translateY(-1px);box-shadow:0 6px 16px rgba(45,107,255,.2)} \n\n   #newk .btn.secondary{background:#fff;color:var(--accent);border:1px solid var(--accent)} \n\n    #newk .btn.danger{background:var(--bad);border-color:var(--bad);color:#fff} \n\n \n\n    \/* TABLE *\/ \n\n    table{width:100%;border-collapse:collapse;background:#fff;border-radius:12px;overflow:hidden} \n\n    th,td{padding:10px;border-bottom:1px solid var(--line);text-align:right} \n\n    thead th{font-weight:800;color:var(--ink);background:var(--soft)} \n\n    th:first-child,td:first-child{text-align:left} \n\n \n\n    \/* KPI *\/ \n\n    .kpi{display:flex;gap:10px;flex-wrap:wrap} \n\n    .kpi .tile{flex:1 1 220px;background:var(--soft);border:1px solid var(--line);border-radius:12px;padding:12px} \n\n    .kpi .label{font-size:.8rem;color:var(--muted)} \n\n    .kpi .value{font-size:1.25rem;font-weight:900;color:var(--ink)} \n\n \n\n    .hint{font-size:.82rem;color:var(--muted)} \n\n    .link{color:var(--accent);text-decoration:none} \n\n    .stack-sm{display:grid;gap:10px} \n\n    .note{font-size:.85rem;color:var(--muted);margin-top:8px} \n\n    .foot{margin-top:12px;color:var(--muted);font-size:.8rem} \n\n  <\/style> \n\n  <style id=\"brand-overrides\"> \n\n    :root{ \n\n      --ink:#0f1436;      \/* QX deep navy headings *\/ \n\n      --accent:#4958ff;   \/* QX primary blue *\/ \n\n      --accent-ink:#ffffff; \n\n      --accent-2:#6a3ff6; \/* QX purple tint *\/ \n\n      --cta:#ff6b5a;      \/* coral CTA like site *\/ \n\n      --line:#e8ecf7; \n\n      --soft:#f6f8ff; \n\n    } \n\n    .hero{background:linear-gradient(160deg, color-mix(in oklab, var(--accent) 8%, white) 0%, color-mix(in oklab, var(--accent-2) 6%, white) 40%, #ffffff 100%)} \n\n  #newk .btn{display:inline-flex;align-items:center;gap:8px;padding:10px 14px;border-radius:12px;border:1px solid color-mix(in oklab, var(--accent) 20%, white);background:linear-gradient(180deg, var(--accent), color-mix(in oklab, var(--accent-2) 40%, var(--accent)));color:var(--accent-ink);font-weight:900;cursor:pointer;transition:transform .05s ease, box-shadow .2s ease} \n\n   #newk .btn:hover{transform:translateY(-1px);box-shadow:0 6px 16px rgba(73,88,255,.25)} \n\n    #newk .btn.secondary{background:#fff;color:var(--accent);border:1px solid var(--accent)} \n\n    #newk .btn.alt{background:var(--cta);border-color:var(--cta);color:#fff} \n\n  <\/style> \n\n<\/head> \n\n<body> \n\n  <div class=\"wrap\" id=\"newk\"> \n\n    <!-- HERO --> \n\n   \n\n \n\n    <!-- HOW TO USE BANNER --> \n\n    <section class=\"banner\"> \n\n      <h2>How to Use a Payroll Calculator UK<\/h2> \n\n      <ul> \n\n        <li>Enter each employee\u2019s gross annual or monthly salary.<\/li> \n\n        <li>Add details such as pension contributions, tax code, and student loan deductions if applicable.<\/li> \n\n        <li>The calculator applies the latest Income Tax and National Insurance rates for the 2025 to 2026 tax year.<\/li> \n\n        <li>Instantly view a full payslip breakdown, including net salary, employer NI, and total payroll cost.<\/li> \n\n      <\/ul> \n\n    <\/section> \n\n \n\n    <!-- CONTROLS --> \n\n    <div class=\"grid\" style=\"margin-top:16px\"> \n\n      <div class=\"card\"> \n\n        <h3>Add employee<\/h3> \n\n        <div class=\"row\"> \n\n          <div> \n\n            <label>Employee name<\/label> \n\n            <input id=\"empName\" placeholder=\"e.g. Alex\" \/> \n\n          <\/div> \n\n          <div> \n\n            <label>Region<\/label> \n\n            <select id=\"region\"> \n\n              <option value=\"EW\">England and Wales<\/option> \n\n              <option value=\"SCOT\">Scotland<\/option> \n\n              <option value=\"NI\">Northern Ireland<\/option> \n\n            <\/select> \n\n          <\/div> \n\n        <\/div> \n\n        <div class=\"row\"> \n\n          <div> \n\n            <label>Salary amount<\/label> \n\n            <input id=\"salary\" type=\"number\" min=\"0\" step=\"0.01\" placeholder=\"e.g. 42000\" \/> \n\n          <\/div> \n\n          <div> \n\n            <label>Salary period<\/label> \n\n            <select id=\"period\"> \n\n              <option value=\"annual\">Annual<\/option> \n\n              <option value=\"monthly\">Monthly<\/option> \n\n            <\/select> \n\n          <\/div> \n\n        <\/div> \n\n \n\n        <div class=\"row3\"> \n\n          <div> \n\n            <label>Tax code<\/label> \n\n            <input id=\"taxCode\" placeholder=\"1257L\" value=\"1257L\" \/> \n\n          <\/div> \n\n          <div> \n\n            <label>Personal allowance override<\/label> \n\n            <input id=\"paOverride\" type=\"number\" min=\"0\" step=\"1\" placeholder=\"leave blank for default\" \/> \n\n          <\/div> \n\n          <div> \n\n            <label>Student loan plan<\/label> \n\n            <select id=\"slPlan\"> \n\n              <option value=\"none\">None<\/option> \n\n              <option value=\"plan1\">Plan 1<\/option> \n\n              <option value=\"plan2\">Plan 2<\/option> \n\n              <option value=\"plan4\">Plan 4<\/option> \n\n            <\/select> \n\n          <\/div> \n\n        <\/div> \n\n \n\n        <div class=\"row3\"> \n\n          <div> \n\n            <label>Postgraduate loan<\/label> \n\n            <select id=\"pgl\"> \n\n              <option value=\"no\">No<\/option> \n\n              <option value=\"yes\">Yes<\/option> \n\n            <\/select> \n\n          <\/div> \n\n          <div> \n\n            <label>Pension basis<\/label> \n\n            <select id=\"pensionBasis\"> \n\n              <option value=\"qe\">Qualifying earnings band<\/option> \n\n              <option value=\"all\">All pensionable pay<\/option> \n\n            <\/select> \n\n          <\/div> \n\n          <div> \n\n            <label>Auto enrolment on<\/label> \n\n            <select id=\"aeOn\"> \n\n              <option value=\"yes\">Yes<\/option> \n\n              <option value=\"no\">No<\/option> \n\n            <\/select> \n\n          <\/div> \n\n        <\/div> \n\n \n\n        <div class=\"row3\"> \n\n          <div> \n\n            <label>Employee pension percent<\/label> \n\n            <input id=\"eePct\" type=\"number\" min=\"0\" max=\"100\" step=\"0.1\" value=\"5\" \/> \n\n          <\/div> \n\n          <div> \n\n            <label>Employer pension percent<\/label> \n\n            <input id=\"erPct\" type=\"number\" min=\"0\" max=\"100\" step=\"0.1\" value=\"3\" \/> \n\n          <\/div> \n\n          <div> \n\n            <label>Employment Allowance applied<\/label> \n\n            <select id=\"eaOn\"> \n\n              <option value=\"no\">No<\/option> \n\n              <option value=\"yes\">Yes<\/option> \n\n            <\/select> \n\n            <div class=\"hint\">For totals only, \u00a310,500 cap per employer. We apply remaining allowance across rows.<\/div> \n\n          <\/div> \n\n        <\/div> \n\n \n\n        <div class=\"stack-sm\" style=\"margin-top:10px\"> \n\n          <button class=\"btn\" id=\"addBtn\">Add employee<\/button> \n\n          <div class=\"hint\">Student loan uses the income used for Class 1 NI. Plan 5 starts from April 2026 so is not included for 2025 to 2026.<\/div> \n\n        <\/div> \n\n      <\/div> \n\n \n\n      <div class=\"card\"> \n\n        <h3>Key totals<\/h3> \n\n        <div class=\"kpi\"> \n\n          <div class=\"tile\"> \n\n            <div class=\"label\">Total employer cost per month<\/div> \n\n            <div class=\"value\" id=\"k_totalCost\">\u00a30.00<\/div> \n\n          <\/div> \n\n          <div class=\"tile\"> \n\n            <div class=\"label\">Total net pay per month<\/div> \n\n            <div class=\"value\" id=\"k_totalNet\">\u00a30.00<\/div> \n\n          <\/div> \n\n          <div class=\"tile\"> \n\n            <div class=\"label\">Employer NI per month<\/div> \n\n            <div class=\"value\" id=\"k_totalENI\">\u00a30.00<\/div> \n\n          <\/div> \n\n        <\/div> \n\n        <div class=\"foot\">Rates source: HMRC and public guidance for 2025 to 2026.<\/div> \n\n      <\/div> \n\n    <\/div> \n\n \n\n    <!-- TABLE --> \n\n    <div class=\"card\" style=\"margin-top:14px\"> \n\n      <div style=\"display:flex;justify-content:space-between;align-items:center;gap:10px\"> \n\n        <h3>Employees<\/h3> \n\n        <div style=\"display:flex;gap:8px;align-items:center\"> \n\n          <div class=\"hint\">Click a row to expand the full payslip<\/div> \n\n          <button class=\"btn secondary\" id=\"downloadBtn\">Download CSV<\/button> \n\n        <\/div> \n\n      <\/div> \n\n      <div style=\"overflow:auto\"> \n\n        <table id=\"empTable\" aria-label=\"Payroll table\"> \n\n          <thead> \n\n            <tr> \n\n              <th>Name<\/th> \n\n              <th>Gross pay mo<\/th> \n\n              <th>Income tax<\/th> \n\n              <th>NI employee<\/th> \n\n              <th>Student loan<\/th> \n\n              <th>PGL<\/th> \n\n              <th>Pension EE<\/th> \n\n              <th>Pension ER<\/th> \n\n              <th>NI employer<\/th> \n\n              <th>Net pay<\/th> \n\n              <th>Employer cost<\/th> \n\n              <th><\/th> \n\n            <\/tr> \n\n          <\/thead> \n\n          <tbody><\/tbody> \n\n        <\/table> \n\n      <\/div> \n\n      <div class=\"note\">Employer cost equals gross pay plus employer NI plus employer pension minus Employment Allowance share where selected.<\/div> \n\n    <\/div> \n\n \n\n    <div class=\"foot\"> \n\n      Assumptions: This tool is a guide. Scotland uses different Income Tax bands. Student loan and PGL are calculated on earnings used for Class 1 NI. Pension qualifying earnings band for 2025 to 2026 is \u00a36,240 to \u00a350,270. Employer NI is 15% above \u00a35,000 per year. Employee NI is 8% between \u00a312,570 and \u00a350,270, then 2% thereafter. Personal allowance is \u00a312,570 and tapers by \u00a31 for every \u00a32 over \u00a3100,000, reaching nil at \u00a3125,140. \n\n    <\/div> \n\n  <\/div> \n\n \n\n  <script> \n\n    \/\/ ======= CONSTANTS: 2025\/26 ======= \n\n    const TAX = { \n\n      PA: 12570, \/\/ default personal allowance \n\n      taperStart: 100000, \n\n      taperEnd: 125140, \n\n      bandsEW: [ \/\/ England Wales NI bands (Northern Ireland follows rUK income tax) \n\n        { upTo: 50270, rate: 0.20 }, \n\n        { upTo: 125140, rate: 0.40 }, \n\n        { upTo: Infinity, rate: 0.45 } \n\n      ], \n\n      bandsScot: [ \n\n        { upTo: 2827, rate: 0.19 }, \n\n        { upTo: 14921, rate: 0.20 }, \n\n        { upTo: 31092, rate: 0.21 }, \n\n        { upTo: 62430, rate: 0.42 }, \n\n        { upTo: 125140, rate: 0.45 }, \n\n        { upTo: Infinity, rate: 0.48 } \n\n      ] \n\n    }; \n\n \n\n    const NI = { \n\n      LEL: 6500, \/\/ employee gets credit but pays 0 below PT \n\n      PT: 12570, \/\/ primary threshold employees \n\n      ST: 5000,  \/\/ secondary threshold employers (reduced from \u00a39,100) \n\n      UEL: 50270, \n\n      empMain: 0.08, \n\n      empUpper: 0.02, \n\n      erRate: 0.15 \n\n    }; \n\n \n\n    const PENSION_QE = { lower: 6240, upper: 50270 }; \n\n \n\n    const SL = { \n\n      plan1: { threshold: 26065, rate: 0.09 }, \n\n      plan2: { threshold: 28470, rate: 0.09 }, \n\n      plan4: { threshold: 32745, rate: 0.09 }, \n\n      pgl:   { threshold: 21000, rate: 0.06 } \n\n    }; \n\n \n\n    \/\/ Employment Allowance cap (for totals only). If on, we will deduct up to this from employer NI total. \n\n    const EMPLOYMENT_ALLOWANCE = 10500; \n\n \n\n    \/\/ ======= STATE ======= \n\n    let employees = []; \n\n    let employmentAllowanceOn = false; \/\/ will mirror first row setting \n\n \n\n    \/\/ ======= HELPERS ======= \n\n    const toMonthly = (annual) => annual \/ 12; \n\n    const toAnnualFromMonthly = (monthly) => monthly * 12; \n\n \n\n    function parseAllowanceFromCode(code){ \n\n      \/\/ Very simple parser: 1257L => 12570. If not numeric, fall back to default PA. \n\n      const m = String(code || '').match(\/(\\d{3,4})\/); \n\n      return m ? parseInt(m[1],10) * 10 : TAX.PA; \n\n    } \n\n \n\n    function taperedPA(income, pa){ \n\n      if(income <= TAX.taperStart) return pa; \n\n      const reduction = Math.floor((income - TAX.taperStart) \/ 2); \n\n      const newPA = Math.max(0, pa - reduction); \n\n      return newPA; \n\n    } \n\n \n\n    function incomeTaxAnnual(gross, region, pa){ \n\n      const bands = region === 'SCOT' ? TAX.bandsScot : TAX.bandsEW; \n\n      \/\/ Apply tapering of PA \n\n      const adjPA = taperedPA(gross, pa); \n\n      let taxable = Math.max(0, gross - adjPA); \n\n      let tax = 0, last = 0; \n\n      for(const b of bands){ \n\n        const slice = Math.max(0, Math.min(taxable, b.upTo - last)); \n\n        tax += slice * b.rate; \n\n        taxable -= slice; \n\n        last = b.upTo; \n\n        if(taxable <= 0) break; \n\n      } \n\n      return tax; \n\n    } \n\n \n\n    function niEmployeeAnnual(gross){ \n\n      const main = Math.max(0, Math.min(gross, NI.UEL) - NI.PT) * NI.empMain; \n\n      const upper = Math.max(0, gross - NI.UEL) * NI.empUpper; \n\n      return Math.max(0, main) + Math.max(0, upper); \n\n    } \n\n \n\n    function niEmployerAnnual(gross){ \n\n      return Math.max(0, gross - NI.ST) * NI.erRate; \n\n    } \n\n \n\n    function pensionablePay(gross, basis){ \n\n      if(basis === 'all') return gross; \n\n      const lower = PENSION_QE.lower, upper = PENSION_QE.upper; \n\n      const within = Math.min(Math.max(gross, lower), upper); \n\n      return Math.max(0, within - lower); \n\n    } \n\n \n\n    function studentLoanAnnual(gross, plan){ \n\n      if(plan === 'none') return 0; \n\n      const t = SL[plan]; \n\n      return Math.max(0, gross - t.threshold) * t.rate; \n\n    } \n\n \n\n    function pglAnnual(gross, on){ \n\n      if(on !== 'yes') return 0; \n\n      const t = SL.pgl; \n\n      return Math.max(0, gross - t.threshold) * t.rate; \n\n    } \n\n \n\n    function currency(n){ \n\n      return new Intl.NumberFormat('en-GB',{style:'currency',currency:'GBP'}).format(n); \n\n    } \n\n \n\n    function addEmployee(){ \n\n      const name = document.getElementById('empName').value || 'Employee'; \n\n      const region = document.getElementById('region').value; \n\n      let salary = parseFloat(document.getElementById('salary').value || '0'); \n\n      const period = document.getElementById('period').value; \n\n      const taxCode = document.getElementById('taxCode').value.trim(); \n\n      const paOverride = document.getElementById('paOverride').value; \n\n      const slPlan = document.getElementById('slPlan').value; \n\n      const pgl = document.getElementById('pgl').value; \n\n      const pensionBasis = document.getElementById('pensionBasis').value; \n\n      const aeOn = document.getElementById('aeOn').value; \n\n      const eePct = parseFloat(document.getElementById('eePct').value || '0'); \n\n      const erPct = parseFloat(document.getElementById('erPct').value || '0'); \n\n      const eaOn = document.getElementById('eaOn').value; \n\n \n\n      if(period === 'monthly') salary = toAnnualFromMonthly(salary); \n\n      const pa = paOverride ? parseFloat(paOverride) : parseAllowanceFromCode(taxCode); \n\n \n\n      employees.push({ id: crypto.randomUUID(), name, region, salary, taxCode, pa, slPlan, pgl, pensionBasis, aeOn, eePct, erPct, eaOn}); \n\n      employmentAllowanceOn = employmentAllowanceOn || eaOn === 'yes'; \n\n      render(); \n\n    } \n\n \n\n    function removeEmployee(id){ \n\n      employees = employees.filter(e => e.id !== id); \n\n      render(); \n\n    } \n\n \n\n    function calcRow(e){ \n\n      const grossA = e.salary; \n\n \n\n      \/\/ Core statutory items \n\n      const taxA = incomeTaxAnnual(grossA, e.region, e.pa); \n\n      const eeNIA = niEmployeeAnnual(grossA); \n\n      const erNIA = niEmployerAnnual(grossA); \n\n \n\n      \/\/ Loans \n\n      const slA = studentLoanAnnual(grossA, e.slPlan); \n\n      const pglA = pglAnnual(grossA, e.pgl); \n\n \n\n      \/\/ Pension \n\n      const penBaseA = e.aeOn === 'yes' ? pensionablePay(grossA, e.pensionBasis) : 0; \n\n      const penEEA = penBaseA * (e.eePct\/100); \n\n      const penERA = penBaseA * (e.erPct\/100); \n\n \n\n      \/\/ Net and employer cost \n\n      const netA = grossA - taxA - eeNIA - slA - pglA - penEEA; \/\/ assumes net pay arrangement or post tax contribution for simplicity \n\n      const employerCostA = grossA + erNIA + penERA; \/\/ before Employment Allowance \n\n \n\n      \/\/ Monthly \n\n      const toM = (x)=>x\/12; \n\n      return { \n\n        grossA, grossM: toM(grossA), \n\n        taxA, taxM: toM(taxA), \n\n        eeNIA, eeNIM: toM(eeNIA), \n\n        erNIA, erNIM: toM(erNIA), \n\n        slA, slM: toM(slA), \n\n        pglA, pglM: toM(pglA), \n\n        penEEA, penEEM: toM(penEEA), \n\n        penERA, penERM: toM(penERA), \n\n        netA, netM: toM(netA), \n\n        employerCostA, employerCostM: toM(employerCostA) \n\n      }; \n\n    } \n\n \n\n    function render(){ \n\n      const tbody = document.querySelector('#empTable tbody'); \n\n      tbody.innerHTML = ''; \n\n \n\n      \/\/ Pre compute rows \n\n      const rows = employees.map(e => ({...e, calc: calcRow(e)})); \n\n \n\n      \/\/ Employment Allowance: simple allocation across rows in order \n\n      let remainingEA = employmentAllowanceOn ? EMPLOYMENT_ALLOWANCE : 0; \n\n \n\n      let totalNetM = 0, totalErNIM = 0, totalCostM = 0; \n\n \n\n      for(const r of rows){ \n\n        let erNIM = r.calc.erNIM; \n\n        let eaUsed = 0; \n\n        if(remainingEA > 0 && r.eaOn === 'yes'){ \n\n          const erNIAmt = r.calc.erNIA; \/\/ annual \n\n          const eaApply = Math.min(remainingEA, erNIAmt); \n\n          remainingEA -= eaApply; \n\n          eaUsed = eaApply\/12; \n\n          erNIM = Math.max(0, erNIM - eaUsed); \n\n        } \n\n \n\n        totalNetM += r.calc.netM; \n\n        totalErNIM += erNIM; \n\n        totalCostM += r.calc.grossM + erNIM + r.calc.penERM; \n\n \n\n        const tr = document.createElement('tr'); \n\n        tr.innerHTML = ` \n\n          <td>${r.name}<\/td> \n\n          <td>${currency(r.calc.grossM)}<\/td> \n\n          <td>${currency(r.calc.taxM)}<\/td> \n\n          <td>${currency(r.calc.eeNIM)}<\/td> \n\n          <td>${currency(r.calc.slM)}<\/td> \n\n          <td>${currency(r.calc.pglM)}<\/td> \n\n          <td>${currency(r.calc.penEEM)}<\/td> \n\n          <td>${currency(r.calc.penERM)}<\/td> \n\n          <td>${currency(erNIM)}<\/td> \n\n          <td>${currency(r.calc.netM)}<\/td> \n\n          <td>${currency(r.calc.grossM + erNIM + r.calc.penERM)}<\/td> \n\n          <td><button class=\"btn danger\" aria-label=\"Remove\" onclick=\"removeEmployee('${r.id}')\">Remove<\/button><\/td> \n\n        `; \n\n        \/\/ Expandable details \n\n        tr.addEventListener('click', () => { \n\n          const next = tr.nextElementSibling; \n\n          if(next && next.classList.contains('details')){ next.remove(); return; } \n\n          const d = document.createElement('tr'); \n\n          d.className = 'details'; \n\n          d.innerHTML = `<td colspan=\"12\"> \n\n            <div class=\"stack-sm\"> \n\n              <div class=\"hint\">Payslip preview for ${r.name} (monthly and annual)<\/div> \n\n              <div class=\"row\"> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">Gross pay<\/div> \n\n                  <div class=\"value\">${currency(r.calc.grossM)} mo \u00b7 ${currency(r.calc.grossA)} yr<\/div> \n\n                <\/div> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">Income tax<\/div> \n\n                  <div class=\"value\">${currency(r.calc.taxM)} mo \u00b7 ${currency(r.calc.taxA)} yr<\/div> \n\n                <\/div> \n\n              <\/div> \n\n              <div class=\"row\"> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">NI employee<\/div> \n\n                  <div class=\"value\">${currency(r.calc.eeNIM)} mo \u00b7 ${currency(r.calc.eeNIA)} yr<\/div> \n\n                <\/div> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">NI employer<\/div> \n\n                  <div class=\"value\">${currency(r.calc.erNIM)} mo \u00b7 ${currency(r.calc.erNIA)} yr<\/div> \n\n                <\/div> \n\n              <\/div> \n\n              <div class=\"row\"> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">Student loan<\/div> \n\n                  <div class=\"value\">${currency(r.calc.slM)} mo \u00b7 ${currency(r.calc.slA)} yr<\/div> \n\n                <\/div> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">Postgraduate loan<\/div> \n\n                  <div class=\"value\">${currency(r.calc.pglM)} mo \u00b7 ${currency(r.calc.pglA)} yr<\/div> \n\n                <\/div> \n\n              <\/div> \n\n              <div class=\"row\"> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">Pension employee<\/div> \n\n                  <div class=\"value\">${currency(r.calc.penEEM)} mo \u00b7 ${currency(r.calc.penEEA)} yr<\/div> \n\n                <\/div> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">Pension employer<\/div> \n\n                  <div class=\"value\">${currency(r.calc.penERM)} mo \u00b7 ${currency(r.calc.penERA)} yr<\/div> \n\n                <\/div> \n\n              <\/div> \n\n              <div class=\"row\"> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">Net pay<\/div> \n\n                  <div class=\"value\">${currency(r.calc.netM)} mo \u00b7 ${currency(r.calc.netA)} yr<\/div> \n\n                <\/div> \n\n                <div class=\"tile\"> \n\n                  <div class=\"label\">Employer cost<\/div> \n\n                  <div class=\"value\">${currency(r.calc.employerCostM)} mo \u00b7 ${currency(r.calc.employerCostA)} yr<\/div> \n\n                <\/div> \n\n              <\/div> \n\n              <div class=\"note\">Personal allowance used: \u00a3${r.pa.toLocaleString()} ${r.region==='SCOT' ? '(Scottish bands applied)' : ''}. NI rates applied at 8 percent main, 2 percent above upper limit for employees, 15 percent for employers. Pension basis: ${r.pensionBasis==='all'?'all pay':'qualifying earnings'}.<\/div> \n\n            <\/div> \n\n          <\/td>`; \n\n          tr.after(d); \n\n        }); \n\n        tbody.appendChild(tr); \n\n      } \n\n \n\n      document.getElementById('k_totalNet').textContent = currency(totalNetM); \n\n      document.getElementById('k_totalENI').textContent = currency(totalErNIM); \n\n      document.getElementById('k_totalCost').textContent = currency(totalCostM); \n\n    } \n\n \n\n    document.getElementById('addBtn').addEventListener('click', addEmployee); \n\n  <\/script> \n\n  <!-- Lead capture modal --> \n\n  <div id=\"leadModal\" style=\"position:fixed;inset:0;display:none;align-items:center;justify-content:center;background:rgba(10,31,68,.45);backdrop-filter:saturate(140%) blur(4px);z-index:9999\"> \n\n    <div class=\"card\" style=\"width:min(560px,92vw);box-shadow:0 20px 60px rgba(10,31,68,.15)\"> \n\n      <h3 style=\"margin-bottom:6px\">Tell us where to send your CSV<\/h3> \n\n      <p class=\"hint\" style=\"margin-top:0\">Fill this short form to download your payroll results. We\u2019ll email you helpful resources too.<\/p> \n\n      <div class=\"row\"> \n\n        <div> \n\n          <label>Full Name<\/label> \n\n          <input id=\"leadName\" placeholder=\"Your name\" \/> \n\n        <\/div> \n\n        <div> \n\n          <label>Firm&#8217;s Name<\/label> \n\n          <input id=\"firmName\" placeholder=\"Your firm\" \/> \n\n        <\/div> \n\n      <\/div> \n\n      <div class=\"row\"> \n\n        <div> \n\n          <label>Contact Email ID<\/label> \n\n          <input id=\"leadEmail\" type=\"email\" placeholder=\"name@company.com\" \/> \n\n        <\/div> \n\n        <div> \n\n          <label>&nbsp;<\/label> \n\n          <button class=\"btn\" id=\"leadSubmit\">Submit &#038; Download<\/button> \n\n        <\/div> \n\n      <\/div> \n\n      <div class=\"hint\" style=\"margin-top:8px\">By submitting, you consent to receive communications related to payroll and capacity solutions. You can unsubscribe anytime.<\/div> \n\n      <div style=\"display:flex;justify-content:flex-end;margin-top:10px\"><button class=\"btn secondary\" id=\"leadClose\">Close<\/button><\/div> \n\n    <\/div> \n\n  <\/div> \n\n \n\n  <script> \n\n    \/\/ === HubSpot config (replace with real values) === \n\n    const HUBSPOT_PORTAL_ID = \"YOUR_PORTAL_ID\";     \/\/ e.g. \"1234567\" \n\n    const HUBSPOT_FORM_GUID = \"YOUR_FORM_GUID\";     \/\/ e.g. \"a1b2c3d4-e5f6-...\" \n\n \n\n    function openLeadModal(){ \n\n      const modal = document.getElementById('leadModal'); \n\n      modal.style.display = 'flex'; \n\n    } \n\n    function closeLeadModal(){ \n\n      document.getElementById('leadModal').style.display = 'none'; \n\n    } \n\n \n\n    function tableToCsv(){ \n\n      \/\/ Build CSV from current calculated rows (monthly figures) \n\n      if(employees.length === 0){ \n\n        alert('Please add at least one employee before downloading.'); \n\n        return null; \n\n      } \n\n      const headers = [ \n\n        'Name','Gross pay (mo)','Income tax (mo)','NI employee (mo)','Student loan (mo)','PGL (mo)','Pension EE (mo)','Pension ER (mo)','NI employer (mo)','Net pay (mo)','Employer cost (mo)' \n\n      ]; \n\n      const rows = employees.map(e=>{ \n\n        const c = calcRow(e); \n\n        return [ \n\n          e.name, \n\n          (c.grossM).toFixed(2), \n\n          (c.taxM).toFixed(2), \n\n          (c.eeNIM).toFixed(2), \n\n          (c.slM).toFixed(2), \n\n          (c.pglM).toFixed(2), \n\n          (c.penEEM).toFixed(2), \n\n          (c.penERM).toFixed(2), \n\n          (c.erNIM).toFixed(2), \n\n          (c.netM).toFixed(2), \n\n          (c.grossM + c.erNIM + c.penERM).toFixed(2) \n\n        ]; \n\n      }); \n\n      const csv = [headers.join(','), ...rows.map(r=>r.map(v=>`\"${String(v).replaceAll('\"','\"\"')}\"`).join(','))].join(' \n\n'); \n\n      return csv; \n\n    } \n\n \n\n    function triggerCsvDownload(csv, filename){ \n\n      const blob = new Blob([csv], {type:'text\/csv;charset=utf-8;'}); \n\n      const url = URL.createObjectURL(blob); \n\n      const a = document.createElement('a'); \n\n      a.href = url; \n\n      a.download = filename; \n\n      document.body.appendChild(a); \n\n      a.click(); \n\n      document.body.removeChild(a); \n\n      URL.revokeObjectURL(url); \n\n    } \n\n \n\n    async function submitLeadAndDownload(){ \n\n      const fullName = document.getElementById('leadName').value.trim(); \n\n      const firm = document.getElementById('firmName').value.trim(); \n\n      const email = document.getElementById('leadEmail').value.trim(); \n\n \n\n      if(!fullName || !firm || !email){ \n\n        alert('Please complete Full Name, Firm\\'s Name, and Contact Email ID.'); \n\n        return; \n\n      } \n\n      \/\/ Basic HTML5 validity check \n\n      const emailEl = document.getElementById('leadEmail'); \n\n      if(!emailEl.checkValidity()){ \n\n        emailEl.reportValidity(); \n\n        return; \n\n      } \n\n      const csv = tableToCsv(); \n\n      if(csv === null) return; \n\n \n\n      \/\/ HubSpot submission (Forms API). If IDs are placeholders, skip network call. \n\n      const shouldSubmit = HUBSPOT_PORTAL_ID !== 'YOUR_PORTAL_ID' && HUBSPOT_FORM_GUID !== 'YOUR_FORM_GUID'; \n\n      let submitted = false; \n\n      if(shouldSubmit){ \n\n        try{ \n\n          const payload = { \n\n            fields: [ \n\n              { name: 'email', value: email }, \n\n              { name: 'firstname', value: fullName }, \n\n              { name: 'company', value: firm }, \n\n              { name: 'calculator_tool', value: 'Payroll Calculator UK 2025\/26' } \n\n            ], \n\n            context: { \n\n              pageUri: location.href, \n\n              pageName: document.title \n\n            } \n\n          }; \n\n          const url = `https:\/\/api.hsforms.com\/submissions\/v3\/integration\/submit\/${HUBSPOT_PORTAL_ID}\/${HUBSPOT_FORM_GUID}`; \n\n          const res = await fetch(url, { method:'POST', headers:{'Content-Type':'application\/json'}, body: JSON.stringify(payload)}); \n\n          submitted = res.ok; \n\n        }catch(err){ \n\n          console.warn('HubSpot submission failed', err); \n\n          submitted = false; \n\n        } \n\n      } \n\n \n\n      const timestamp = new Date().toISOString().slice(0,10); \n\n      triggerCsvDownload(csv, `payroll_employees_${timestamp}.csv`); \n\n      closeLeadModal(); \n\n    } \n\n \n\n    \/\/ Wire up UI \n\n    document.getElementById('downloadBtn').addEventListener('click', ()=>{ \n\n      if(employees.length === 0){ \n\n        alert('Add at least one employee to generate a CSV.'); \n\n        return; \n\n      } \n\n      openLeadModal(); \n\n    }); \n\n    document.getElementById('leadClose').addEventListener('click', closeLeadModal); \n\n    document.getElementById('leadSubmit').addEventListener('click', submitLeadAndDownload); \n\n  <\/script> \n\n<\/body> \n\n<\/html>\n\n\n<section class=\"cussto-ctabox calculator-cta\">\r\n<div class=\"container\">\r\n<div class=\"row justify-content-center text-start text-sm-center\">\r\n<div class=\"col-lg-9 col-xxl-8 position-relative z-1\">\r\n    <h3>Your Next Move Starts Here<\/h3>\n<p>Book a short call to explore how our specialist teams can help you turn these results into stronger outcomes for your clients and your firm.<\/p>\n<div class=\"bookmytime gap-4 flex-column flex-sm-row text-start d-flex mx-auto\">\r\n<div class=\"photobox\">\r\n  <div class=\"photo\">\r\n    <img decoding=\"async\" src=\"https:\/\/qxaccounting.com\/uk\/wp-content\/uploads\/sites\/2\/2025\/10\/Swati-Yadav.webp\" alt=\"\">\r\n<\/div>\r\n<a target=\"_blank\" href=\"https:\/\/www.linkedin.com\/in\/sy05\/\" class=\"linkedin\"><img decoding=\"async\" src=\"https:\/\/qxaccounting.com\/uk\/wp-content\/themes\/qxaccount\/assets\/images\/common\/Linkedin.png\" alt=\"\"><\/a><\/div>\r\n<div class=\"d-flex flex-column align-items-start\">\r\n<h5>Swati Yadav<\/h5>\r\n<h6>Business Development Manager QXAS<\/h6>\r\n  <a target=\"_blank\" href=\"https:\/\/meetings.hubspot.com\/swati-yadav\">Book My Time <i><img decoding=\"async\" src=\"https:\/\/qxaccounting.com\/uk\/wp-content\/themes\/qxaccount\/assets\/images\/SVG\/calendar_month_30.svg\" alt=\"\"><\/i>\r\n<\/a> <\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<\/section>\r\n","protected":false},"excerpt":{"rendered":"<p>Payroll Calculator UK (2025\/2026) How to Use a Payroll Calculator UK Enter each employee\u2019s gross annual or monthly salary. Add details such as pension contributions, tax code, and student loan deductions if applicable. The calculator applies the latest Income Tax and National Insurance rates for the 2025 to 2026 tax year. Instantly view a full [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":9880,"parent":9868,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template\/home-new.php","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-9872","page","type-page","status-publish","has-post-thumbnail","hentry"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/pages\/9872","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/comments?post=9872"}],"version-history":[{"count":0,"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/pages\/9872\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/pages\/9868"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/media\/9880"}],"wp:attachment":[{"href":"https:\/\/qxaccounting.com\/uk\/wp-json\/wp\/v2\/media?parent=9872"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}