sodium calculator

Calculate your daily sodium intake from foods, convert salt (NaCl) to sodium (Na), check % Daily Value, and compare against guideline limits. Accessible, mobile-first tool for diet & nutrition.

Full original guide (expanded)

Authoritative data source & methodology

Primary reference thresholds commonly used on nutrition labels and public health guidance include:

  • Daily Value (DV) for sodium: 2,300 mg (U.S. FDA labeling basis).
  • Population intake target: many guidelines advise ≈2,000 mg/day (≈5 g salt). Follow your clinician’s advice if different.

Tutti i calcoli si basano rigorosamente sulle formule e sui dati forniti da questa fonte.

The formula explained

Salt → Sodium

$$\\text{Na (mg)} = \\text{Salt (g)} \\times 1000 \\times \\frac{M_{Na}}{M_{NaCl}} \\approx \\text{Salt (g)}\\times 393.4$$ where \(M_{Na}=22.99\\,g/mol\\) and \(M_{NaCl}=58.44\\,g/mol\\).

% Daily Value

$$\\%\\,DV = \\frac{\\text{Total Na (mg)}}{\\text{DV base (mg)}} \\times 100$$

Food total

$$\\text{Total Na (mg)} = \\sum_i (\\text{Na per serving}_i \\times \\text{servings}_i) + \\text{converted Na (mg)}$$

Glossary of variables

Symbol / FieldMeaning
Na (mg)Total sodium in milligrams.
Salt (g)Sodium chloride grams. Na ≈ 39.34% of NaCl by mass.
DV base (mg)Daily Value baseline (default 2300 mg).
%DVPercent of daily value: Na ÷ DV × 100.
Sodium / servingLabel sodium per serving in mg.
ServingsNumber of servings consumed.

How it works: a step-by-step example

Example

Suppose you ate:

  • Soup: 650 mg per serving × 1.5 servings = 975 mg
  • Bread: 180 mg per serving × 2 servings = 360 mg
  • Added salt: 2 g salt → \(2 \\times 393.4 = 786.8\\) mg Na

Total Na = 975 + 360 + 787 ≈ 2,122 mg. With DV base = 2,300 mg, %DV ≈ \(2,122/2,300 \\times 100 = 92.3\\%\\).

Frequently asked questions

Is Himalayan or sea salt lower in sodium?

By weight, sodium content is similar. Mineral differences don’t meaningfully reduce sodium load.

Should I use 2,000 or 2,300 mg as my limit?

Label DV is often 2,300 mg; many public health targets are ≈2,000 mg. Use what your clinician recommends.

How do I handle homemade recipes?

Sum sodium from each ingredient (using databases or labels) and divide by portions to get per-serving sodium.

Does potassium salt (KCl) count?

KCl provides potassium, not sodium. It may taste salty but does not add sodium; consult your clinician regarding potassium intake.

Any quick label heuristic?

≈5% DV (≤115 mg) per serving is low; ≥20% DV (≥460 mg) is high.

Last accuracy review:


Audit: Complete
Formula (LaTeX) + variables + units
This section shows the formulas used by the calculator engine, plus variable definitions and units.
Formula (extracted LaTeX)
\[', right:'\]
', right:'
Formula (extracted LaTeX)
\[\\text{Na (mg)} = \\text{Salt (g)} \\times 1000 \\times \\frac{M_{Na}}{M_{NaCl}} \\approx \\text{Salt (g)}\\times 393.4\]
\\text{Na (mg)} = \\text{Salt (g)} \\times 1000 \\times \\frac{M_{Na}}{M_{NaCl}} \\approx \\text{Salt (g)}\\times 393.4
Formula (extracted LaTeX)
\[\\%\\,DV = \\frac{\\text{Total Na (mg)}}{\\text{DV base (mg)}} \\times 100\]
\\%\\,DV = \\frac{\\text{Total Na (mg)}}{\\text{DV base (mg)}} \\times 100
Formula (extracted LaTeX)
\[\\text{Total Na (mg)} = \\sum_i (\\text{Na per serving}_i \\times \\text{servings}_i) + \\text{converted Na (mg)}\]
\\text{Total Na (mg)} = \\sum_i (\\text{Na per serving}_i \\times \\text{servings}_i) + \\text{converted Na (mg)}
Formula (extracted LaTeX)
\[= (sel, root=document) => Array.from(root.querySelectorAll(sel)); const els = { dvBase: $('#dvBase'), targetMg: $('#targetMg'), unitPref: $('#unitPref'), dvBaseErr: $('#dvBase-err'), targetErr: $('#target-err'), dvBaseHelp: $('#dvBase-help'), dvBaseTip: $('#dvBase-tip'), saltG: $('#saltG'), sodiumMgConv: $('#sodiumMgConv'), saltTipBtn: $('#saltTipBtn'), saltHelp: $('#salt-help'), applyConv: $('#applyConv'), foodBody: $('#foodBody'), addRow: $('#addRow'), clearRows: $('#clearRows'), totalSodium: $('#totalSodium'), saltEquiv: $('#saltEquiv'), percentDV: $('#percentDV'), versusTarget: $('#versusTarget'), advice: $('#advice'), dvBar: $('#dvBar') }; // Accessibility: toggle tooltips function toggleHelp(btn, panel){ const expanded = btn.getAttribute('aria-expanded') === 'true'; btn.setAttribute('aria-expanded', String(!expanded)); panel.classList.toggle('hidden', expanded); } els.dvBaseTip.addEventListener('click', ()=>toggleHelp(els.dvBaseTip, els.dvBaseHelp)); els.saltTipBtn.addEventListener('click', ()=>toggleHelp(els.saltTipBtn, els.saltHelp)); // Constants const FRACTION_NA_IN_SALT = 22.99 / 58.44; // 0.3934 const MG_PER_G = 1000; // State let convertedExtraMg = 0; // sodium added from converter let dvChart; // Validation helpers function setErr(el, errEl, msg){ errEl.textContent = msg || ''; el.setAttribute('aria-invalid', msg ? 'true' : 'false'); } function onBlurNumber(el, errEl, {min=null, max=null, name='value'}){ el.addEventListener('blur', ()=>{ const v = el.value.trim()==='' ? NaN : Number(el.value); if (Number.isNaN(v)) { setErr(el, errEl, `Enter a valid number for ${name}.`); return; } if (min!==null && v<min) { setErr(el, errEl, `${name} must be ≥ ${min}.`); return; } if (max!==null && v>max) { setErr(el, errEl, `${name} must be ≤ ${max}.`); return; } setErr(el, errEl, ''); }); } onBlurNumber(els.dvBase, els.dvBaseErr, {min:1000, max:4000, name:'Daily Value base'}); onBlurNumber(els.targetMg, els.targetErr, {min:0, max:4000, name:'Personal target'}); // Food rows function newFoodRow(prefill={}){ const tr = document.createElement('tr'); tr.innerHTML = ` <td class="px-3 py-2"> <input type="text" aria-label="Food name" class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500" value="${prefill.name||''}"> </td> <td class="px-3 py-2"> <div> <input type="number" inputmode="decimal" required aria-required="true" aria-describedby="food-err" class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500 food-mg" min="0" step="1" value="${typeof prefill.mg==='number'?prefill.mg:''}"> <p class="text-sm text-red-600 mt-1 food-err" aria-live="polite"></p> </div> </td> <td class="px-3 py-2"> <div> <input type="number" inputmode="decimal" required aria-required="true" aria-describedby="serv-err" class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500 food-serv" min="0" step="0.25" value="${typeof prefill.serv==='number'?prefill.serv:''}"> <p class="text-sm text-red-600 mt-1 serv-err" aria-live="polite"></p> </div> </td> <td class="px-3 py-2 text-right"> <span class="food-total">0</span> mg </td> <td class="px-3 py-2 text-center"> <button type="button" class="px-2 py-1 border rounded hover:bg-gray-100 removeRow" aria-label="Remove item">Remove</button> </td> `; // inline validation on blur const mgEl = tr.querySelector('.food-mg'); const mgErr = tr.querySelector('.food-err'); const svEl = tr.querySelector('.food-serv'); const svErr = tr.querySelector('.serv-err'); onBlurNumber(mgEl, mgErr, {min:0, name:'Sodium per serving (mg)'}); onBlurNumber(svEl, svErr, {min:0, name:'Servings'}); // bind changes [mgEl, svEl].forEach(el=>el.addEventListener('input', recompute)); tr.querySelector('.removeRow').addEventListener('click', ()=>{ tr.remove(); recompute(); }); els.foodBody.appendChild(tr); } // Seed with two example rows for UX newFoodRow({name:'Soup (canned)', mg:650, serv:1}); newFoodRow({name:'Bread slice', mg:180, serv:2}); els.addRow.addEventListener('click', ()=>newFoodRow()); els.clearRows.addEventListener('click', ()=>{ els.foodBody.innerHTML=''; convertedExtraMg = 0; recompute(); }); // Converter two-way function saltToSodiumMg(g){ return g * MG_PER_G * FRACTION_NA_IN_SALT; } function sodiumMgToSaltG(mg){ return mg / (MG_PER_G * FRACTION_NA_IN_SALT); } let lockConv = false; els.saltG.addEventListener('input', ()=>{ if (lockConv) return; lockConv = true; const g = parseFloat(els.saltG.value); const mg = Number.isFinite(g) ? saltToSodiumMg(g) : 0; els.sodiumMgConv.value = mg ? Math.round(mg) : ''; lockConv = false; }); els.sodiumMgConv.addEventListener('input', ()=>{ if (lockConv) return; lockConv = true; const mg = parseFloat(els.sodiumMgConv.value); const g = Number.isFinite(mg) ? sodiumMgToSaltG(mg) : 0; els.saltG.value = g ? (Math.round(g*10)/10).toString() : ''; lockConv = false; }); els.applyConv.addEventListener('click', ()=>{ const mg = parseFloat(els.sodiumMgConv.value); if (!Number.isFinite(mg) || mg<0){ alert('Enter a non-negative sodium amount (mg) to add.'); return; } convertedExtraMg += mg; // Reset converter inputs els.saltG.value = ''; els.sodiumMgConv.value = ''; recompute(); }); [els.dvBase, els.targetMg, els.unitPref].forEach(el=>el.addEventListener('input', recompute)); function sumFoodsMg(){ let total = 0;\]
= (sel, root=document) => Array.from(root.querySelectorAll(sel)); const els = { dvBase: $('#dvBase'), targetMg: $('#targetMg'), unitPref: $('#unitPref'), dvBaseErr: $('#dvBase-err'), targetErr: $('#target-err'), dvBaseHelp: $('#dvBase-help'), dvBaseTip: $('#dvBase-tip'), saltG: $('#saltG'), sodiumMgConv: $('#sodiumMgConv'), saltTipBtn: $('#saltTipBtn'), saltHelp: $('#salt-help'), applyConv: $('#applyConv'), foodBody: $('#foodBody'), addRow: $('#addRow'), clearRows: $('#clearRows'), totalSodium: $('#totalSodium'), saltEquiv: $('#saltEquiv'), percentDV: $('#percentDV'), versusTarget: $('#versusTarget'), advice: $('#advice'), dvBar: $('#dvBar') }; // Accessibility: toggle tooltips function toggleHelp(btn, panel){ const expanded = btn.getAttribute('aria-expanded') === 'true'; btn.setAttribute('aria-expanded', String(!expanded)); panel.classList.toggle('hidden', expanded); } els.dvBaseTip.addEventListener('click', ()=>toggleHelp(els.dvBaseTip, els.dvBaseHelp)); els.saltTipBtn.addEventListener('click', ()=>toggleHelp(els.saltTipBtn, els.saltHelp)); // Constants const FRACTION_NA_IN_SALT = 22.99 / 58.44; // 0.3934 const MG_PER_G = 1000; // State let convertedExtraMg = 0; // sodium added from converter let dvChart; // Validation helpers function setErr(el, errEl, msg){ errEl.textContent = msg || ''; el.setAttribute('aria-invalid', msg ? 'true' : 'false'); } function onBlurNumber(el, errEl, {min=null, max=null, name='value'}){ el.addEventListener('blur', ()=>{ const v = el.value.trim()==='' ? NaN : Number(el.value); if (Number.isNaN(v)) { setErr(el, errEl, `Enter a valid number for ${name}.`); return; } if (min!==null && v<min) { setErr(el, errEl, `${name} must be ≥ ${min}.`); return; } if (max!==null && v>max) { setErr(el, errEl, `${name} must be ≤ ${max}.`); return; } setErr(el, errEl, ''); }); } onBlurNumber(els.dvBase, els.dvBaseErr, {min:1000, max:4000, name:'Daily Value base'}); onBlurNumber(els.targetMg, els.targetErr, {min:0, max:4000, name:'Personal target'}); // Food rows function newFoodRow(prefill={}){ const tr = document.createElement('tr'); tr.innerHTML = ` <td class="px-3 py-2"> <input type="text" aria-label="Food name" class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500" value="${prefill.name||''}"> </td> <td class="px-3 py-2"> <div> <input type="number" inputmode="decimal" required aria-required="true" aria-describedby="food-err" class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500 food-mg" min="0" step="1" value="${typeof prefill.mg==='number'?prefill.mg:''}"> <p class="text-sm text-red-600 mt-1 food-err" aria-live="polite"></p> </div> </td> <td class="px-3 py-2"> <div> <input type="number" inputmode="decimal" required aria-required="true" aria-describedby="serv-err" class="w-full px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500 food-serv" min="0" step="0.25" value="${typeof prefill.serv==='number'?prefill.serv:''}"> <p class="text-sm text-red-600 mt-1 serv-err" aria-live="polite"></p> </div> </td> <td class="px-3 py-2 text-right"> <span class="food-total">0</span> mg </td> <td class="px-3 py-2 text-center"> <button type="button" class="px-2 py-1 border rounded hover:bg-gray-100 removeRow" aria-label="Remove item">Remove</button> </td> `; // inline validation on blur const mgEl = tr.querySelector('.food-mg'); const mgErr = tr.querySelector('.food-err'); const svEl = tr.querySelector('.food-serv'); const svErr = tr.querySelector('.serv-err'); onBlurNumber(mgEl, mgErr, {min:0, name:'Sodium per serving (mg)'}); onBlurNumber(svEl, svErr, {min:0, name:'Servings'}); // bind changes [mgEl, svEl].forEach(el=>el.addEventListener('input', recompute)); tr.querySelector('.removeRow').addEventListener('click', ()=>{ tr.remove(); recompute(); }); els.foodBody.appendChild(tr); } // Seed with two example rows for UX newFoodRow({name:'Soup (canned)', mg:650, serv:1}); newFoodRow({name:'Bread slice', mg:180, serv:2}); els.addRow.addEventListener('click', ()=>newFoodRow()); els.clearRows.addEventListener('click', ()=>{ els.foodBody.innerHTML=''; convertedExtraMg = 0; recompute(); }); // Converter two-way function saltToSodiumMg(g){ return g * MG_PER_G * FRACTION_NA_IN_SALT; } function sodiumMgToSaltG(mg){ return mg / (MG_PER_G * FRACTION_NA_IN_SALT); } let lockConv = false; els.saltG.addEventListener('input', ()=>{ if (lockConv) return; lockConv = true; const g = parseFloat(els.saltG.value); const mg = Number.isFinite(g) ? saltToSodiumMg(g) : 0; els.sodiumMgConv.value = mg ? Math.round(mg) : ''; lockConv = false; }); els.sodiumMgConv.addEventListener('input', ()=>{ if (lockConv) return; lockConv = true; const mg = parseFloat(els.sodiumMgConv.value); const g = Number.isFinite(mg) ? sodiumMgToSaltG(mg) : 0; els.saltG.value = g ? (Math.round(g*10)/10).toString() : ''; lockConv = false; }); els.applyConv.addEventListener('click', ()=>{ const mg = parseFloat(els.sodiumMgConv.value); if (!Number.isFinite(mg) || mg<0){ alert('Enter a non-negative sodium amount (mg) to add.'); return; } convertedExtraMg += mg; // Reset converter inputs els.saltG.value = ''; els.sodiumMgConv.value = ''; recompute(); }); [els.dvBase, els.targetMg, els.unitPref].forEach(el=>el.addEventListener('input', recompute)); function sumFoodsMg(){ let total = 0;
Formula (extracted text)
Salt → Sodium $\\text{Na (mg)} = \\text{Salt (g)} \\times 1000 \\times \\frac{M_{Na}}{M_{NaCl}} \\approx \\text{Salt (g)}\\times 393.4$ where \(M_{Na}=22.99\\,g/mol\\) and \(M_{NaCl}=58.44\\,g/mol\\). % Daily Value $\\%\\,DV = \\frac{\\text{Total Na (mg)}}{\\text{DV base (mg)}} \\times 100$ Food total $\\text{Total Na (mg)} = \\sum_i (\\text{Na per serving}_i \\times \\text{servings}_i) + \\text{converted Na (mg)}$
Variables and units
  • No variables provided in audit spec.
Sources (authoritative):
Changelog
Version: 0.1.0-draft
Last code update: 2026-01-19
0.1.0-draft · 2026-01-19
  • Initial audit spec draft generated from HTML extraction (review required).
  • Verify formulas match the calculator engine and convert any text-only formulas to LaTeX.
  • Confirm sources are authoritative and relevant to the calculator methodology.
Verified by Ugo Candido on 2026-01-19
Profile · LinkedIn
Formulas

(Formulas preserved from original page content, if present.)

Version 0.1.0-draft
Citations

Add authoritative sources relevant to this calculator (standards bodies, manuals, official docs).

Changelog
  • 0.1.0-draft — 2026-01-19: Initial draft (review required).