Authoritative Engineering Content
Data Source and Methodology
Authoritative source: National Electrical Code (NEC) — NFPA 70 (2020), Article 314.16 and Table 314.16(B). Official NFPA code page (free view with account).
All calculations strictly follow the formulas and allowances provided by this source.
- Insulated conductors that enter and terminate/splice in the box: count 1 each.
- Pass-through (unspliced) insulated conductors: count 1 each.
- Equipment grounding conductors (all): count as 1 volume using the largest EGC present.
- Each device yoke: counts as 2 volumes using the largest conductor connected to that yoke.
- Integral internal clamps: count as 1 volume of the largest insulated conductor entering the box.
- Internal fittings (e.g., hickeys): count as 1 volume each of the largest insulated conductor in the box.
For additional background see: ECM: Box Fill Calculations, JADE Learning: NEC 314.16.
The Formula Explained
18→1.50, 16→1.75, 14→2.00, 12→2.25, 10→2.50, 8→3.00, 6→5.00 (cubic inches)
Total required volume:
$$V_{req} \;=\; \sum_{i} n_i \cdot V(\mathrm{AWG}_i)\;+\; \mathbf{1}_{\mathrm{EGC}>0}\cdot V(\mathrm{AWG}_{\mathrm{EGC,max}})\;+\; 2\!\!\sum_{j} y_j \cdot V(\mathrm{AWG}_{y_j})\;+\; \mathbf{1}_{\mathrm{clamp}}\cdot V(\mathrm{AWG}_{\max})\;+\; f \cdot V(\mathrm{AWG}_{\max})$$ where:
- $n_i$ = insulated conductors of size $\mathrm{AWG}_i$ that enter and terminate/splice (pass-through counts as 1).
- $\mathrm{EGC,max}$ = largest equipment grounding conductor AWG (counted once if any EGCs are present).
- $y_j$ = number of device yokes connected to conductors of $\mathrm{AWG}_{y_j}$ (each counts as 2 conductors).
- $\mathrm{AWG}_{\max}$ = largest insulated conductor AWG present in the box (used for clamp and fitting allowances).
- $f$ = number of internal support fittings.
Glossary of Variables
- Box marked volume (in³): Manufacturer-stamped cubic-inch capacity of the box.
- Insulated conductors: Current-carrying conductors that enter and terminate or splice in the box; pass-throughs count once; pigtails within same box add no extra count.
- Equipment grounding conductors (EGC): Green/bare conductors; all EGCs together count as one conductor volume using the largest EGC present.
- Device yoke: A strap holding one or more devices (e.g., duplex receptacle). Each yoke counts as two conductors of the largest conductor on that yoke.
- Internal clamps: Integral cable clamps inside the box; count as one conductor of the largest insulated conductor present.
- Internal fittings: Accessories like hickeys; each counts as one conductor of the largest insulated conductor present.
- V(AWG): NEC Table 314.16(B) volume per conductor size (in³): 18→1.50, 16→1.75, 14→2.00, 12→2.25, 10→2.50, 8→3.00, 6→5.00.
How It Works: A Step-by-Step Example
Scenario. Box contains: six 12 AWG insulated conductors; one duplex receptacle on 12 AWG (one yoke); two EGCs with largest EGC 12 AWG; integral clamps present; no fittings. Box marked volume = 20.3 in³.
- Conductor allowance: 6 × V(12) = 6 × 2.25 = 13.50 in³.
- EGC allowance: present → 1 × V(12) = 2.25 in³.
- Device yoke: 1 yoke → 2 × V(12) = 4.50 in³.
- Clamp: present → 1 × V(12) = 2.25 in³.
- Fittings: none → 0.
- Total required: 13.50 + 2.25 + 4.50 + 2.25 = 22.50 in³.
- Comparison: 20.3 in³ box does not comply (short by 2.2 in³).
FAQ
Do pigtails count toward box fill?
No additional count for pigtails that originate and terminate in the same box. Their conductors are already included per NEC 314.16(B).
How are equipment grounding conductors counted?
All EGCs taken together count as a single conductor volume based on the largest EGC present.
Do pass-through conductors count?
Yes. Each insulated pass-through (unspliced) conductor counts as one conductor volume.
How do devices like duplex receptacles count?
Each yoke counts as two conductor volumes using the largest conductor attached to that yoke.
Do internal clamps and fittings count?
Internal clamps count as one conductor volume; each internal fitting counts as one, both based on the largest insulated conductor in the box.
Which AWG sizes are supported?
18, 16, 14, 12, 10, 8, and 6 AWG, using the cubic-inch values in NEC Table 314.16(B).
Can I use this for multi-gang boxes?
Yes. Enter the total manufacturer-marked volume (sum of gangs) and include all conductors/devices in the calculation.
Formula (LaTeX) + variables + units
','
V_{req} \;=\; \sum_{i} n_i \cdot V(\mathrm{AWG}_i)\;+\; \mathbf{1}_{\mathrm{EGC}>0}\cdot V(\mathrm{AWG}_{\mathrm{EGC,max}})\;+\; 2\!\!\sum_{j} y_j \cdot V(\mathrm{AWG}_{y_j})\;+\; \mathbf{1}_{\mathrm{clamp}}\cdot V(\mathrm{AWG}_{\max})\;+\; f \cdot V(\mathrm{AWG}_{\max})
= (sel, ctx=document) => Array.from(ctx.querySelectorAll(sel)); const els = { boxVolume: $('#boxVolume'), boxVolumeError: $('#boxVolumeError'), quickPicks:
('.help-btn'), }; function createConductorRow(initial = {awg:'', count:''}) { const rowId = `cg-${conductorRowId++}`; const row = document.createElement('div'); row.className = 'group-row'; row.setAttribute('data-role', 'conductor-row'); row.innerHTML = ` <div> <label class="sr-only" for="${rowId}-awg">Conductor size (AWG)</label> <select id="${rowId}-awg" class="form-control" aria-describedby="${rowId}-error"> <option value="">AWG size</option> <option>18</option><option>16</option><option>14</option><option>12</option><option>10</option><option>8</option><option>6</option> </select> </div> <div> <label class="sr-only" for="${rowId}-count">Count of insulated conductors</label> <input id="${rowId}-count" class="form-control" type="number" inputmode="numeric" min="0" step="1" placeholder="Count" aria-describedby="${rowId}-error"> </div> <div style="display:flex; gap:.5rem; align-items:center"> <button class="remove-btn" type="button" aria-label="Remove this conductor group">Remove</button> </div> <div id="${rowId}-error" class="error-message" role="alert" aria-live="polite"></div> `; if (initial.awg) row.querySelector(`#${rowId}-awg`).value = initial.awg; if (initial.count !== '') row.querySelector(`#${rowId}-count`).value = initial.count; els.conductorGroups.appendChild(row); } function createYokeRow(initial = {awg:'', count:''}) { const rowId = `yg-${yokeRowId++}`; const row = document.createElement('div'); row.className = 'group-row'; row.setAttribute('data-role', 'yoke-row'); row.innerHTML = ` <div> <label class="sr-only" for="${rowId}-awg">Device yoke conductor size (AWG)</label> <select id="${rowId}-awg" class="form-control" aria-describedby="${rowId}-error"> <option value="">AWG size</option> <option>18</option><option>16</option><option>14</option><option>12</option><option>10</option><option>8</option><option>6</option> </select> </div> <div> <label class="sr-only" for="${rowId}-count">Number of device yokes</label> <input id="${rowId}-count" class="form-control" type="number" inputmode="numeric" min="0" step="1" placeholder="Yokes" aria-describedby="${rowId}-error"> </div> <div style="display:flex; gap:.5rem; align-items:center"> <button class="remove-btn" type="button" aria-label="Remove this yoke group">Remove</button> </div> <div id="${rowId}-error" class="error-message" role="alert" aria-live="polite"></div> `; if (initial.awg) row.querySelector(`#${rowId}-awg`).value = initial.awg; if (initial.count !== '') row.querySelector(`#${rowId}-count`).value = initial.count; els.yokeGroups.appendChild(row); } // Validation helpers function setError(el, msg) { el.textContent = msg || ''; } function markInvalid(input, invalid, describedById) { input.setAttribute('aria-invalid', invalid ? 'true' : 'false'); if (describedById) input.setAttribute('aria-describedby', describedById); } function parseIntSafe(value) { if (value === '' || value === null || value === undefined) return NaN; const n = Number(value); return Number.isFinite(n) ? n : NaN; } function parseFloatSafe(value) { if (value === '' || value === null || value === undefined) return NaN; const n = Number(value); return Number.isFinite(n) ? n : NaN; } // Field-specific validation function validateBoxVolume() { const val = parseFloatSafe(els.boxVolume.value); if (isNaN(val)) { setError(els.boxVolumeError, 'Please enter the marked box volume in cubic inches.'); markInvalid(els.boxVolume, true, 'boxVolumeError'); return null; } if (val <= 0) { setError(els.boxVolumeError, 'Box volume must be greater than 0. Check the manufacturer marking.'); markInvalid(els.boxVolume, true, 'boxVolumeError'); return null; } setError(els.boxVolumeError, ''); markInvalid(els.boxVolume, false, 'boxVolumeError'); return val; } function validateEgc() { const count = parseIntSafe(els.egcCount.value); const awg = els.egcAwg.value; let ok = true; if (!isNaN(count) && count < 0) { setError(els.egcCountError, 'Count cannot be negative.'); markInvalid(els.egcCount, true, 'egcCountError'); ok = false; } else { setError(els.egcCountError, ''); markInvalid(els.egcCount, false, 'egcCountError'); } if (count > 0 && !awg) { setError(els.egcAwgError, 'Select the largest EGC size (AWG).'); markInvalid(els.egcAwg, true, 'egcAwgError'); ok = false; } else { setError(els.egcAwgError, ''); markInvalid(els.egcAwg, false, 'egcAwgError'); } return ok ? {count: isNaN(count) ? 0 : count, awg: awg || ''} : null; } function validateFittings() { const count = parseIntSafe(els.fittingCount.value); if (isNaN(count)) { setError(els.fittingCountError, ''); markInvalid(els.fittingCount, false, 'fittingCountError'); return 0; } if (count < 0) { setError(els.fittingCountError, 'Count cannot be negative.'); markInvalid(els.fittingCount, true, 'fittingCountError'); return null; } setError(els.fittingCountError, ''); markInvalid(els.fittingCount, false, 'fittingCountError'); return count; } function validateGroupRow(row) { const isConductor = row.getAttribute('data-role') === 'conductor-row'; const idPrefix = row.querySelector('select').id.replace(/-awg$/, ''); const sel = row.querySelector(`#${idPrefix}-awg`); const cntInput = row.querySelector(`#${idPrefix}-count`); const err = row.querySelector(`#${idPrefix}-error`); const count = parseIntSafe(cntInput.value); const awg = sel.value; let valid = true; if (!isNaN(count) && count < 0) { err.textContent = 'Count cannot be negative.'; cntInput.setAttribute('aria-invalid','true'); valid = false; } else { cntInput.setAttribute('aria-invalid','false'); } if ((count || count === 0) && count > 0 && !awg) { err.textContent = 'Select an AWG size for this group.'; sel.setAttribute('aria-invalid','true'); valid = false; } else { sel.setAttribute('aria-invalid','false'); } if ((count === 0 || isNaN(count)) && !awg) { err.textContent = ''; } else if (valid) { err.textContent = ''; } // For yokes, ensure integer counts if (row.getAttribute('data-role') === 'yoke-row' && !isNaN(count) && !Number.isInteger(count)) { err.textContent = 'Number of yokes must be a whole number.'; cntInput.setAttribute('aria-invalid','true'); valid = false; } return valid ? { count: isNaN(count) ? 0 : count, awg: awg || '' } : null; } function collectInputs() { // Box volume can be null (not provided); we still compute required const boxVol = (els.boxVolume.value.trim() === '') ? null : validateBoxVolume(); // Conductors const conductors = []; for (const row of
('#yokeGroups .group-row')) { const v = validateGroupRow(row); if (v === null) return null; // invalid if (v.count > 0 && v.awg) yokes.push(v); } // EGC const egc = validateEgc(); if (egc === null) return null; // Fittings const fittings = validateFittings(); if (fittings === null) return null; const clamps = els.internalClamps.checked; return { boxVol, conductors, yokes, egc, fittings, clamps }; } function largestInsulatedAWG(conductors, yokes) { // Return the physically largest conductor (smallest AWG number) // We compare by numerical value, but NEC table is discrete for listed sizes only. const sizes = new Set(); conductors.forEach(c => sizes.add(c.awg)); yokes.forEach(y => sizes.add(y.awg)); const arr = Array.from(sizes).map(Number).filter(Boolean); if (arr.length === 0) return null; // Larger conductor is smaller numeric AWG (e.g., 6 is larger than 12) return Math.min(...arr); } function compute() { const input = collectInputs(); if (!input) { // Invalid fields; keep results minimal renderResults({required: 0, box: readBoxVolOrNull(), margin: null, ok: null, equiv: 0, breakdown: []}); return; } const { boxVol, conductors, yokes, egc, fittings, clamps } = input; // Aggregate by AWG for conductors let breakdown = []; let required = 0; let equivalents = 0; // Conductors const condMap = new Map(); for (const c of conductors) { const cnt = condMap.get(c.awg) || 0; condMap.set(c.awg, cnt + c.count); } for (const [awg, count] of condMap) { const vol = (VOLUME_BY_AWG[awg] || 0) * count; required += vol; equivalents += count; breakdown.push({label:`Insulated conductors ${awg} AWG × ${count}`, vol}); } // EGC (all count as one of largest EGC present) if (egc.count > 0 && egc.awg) { const vol = (VOLUME_BY_AWG[egc.awg] || 0) * 1; required += vol; equivalents += 1; breakdown.push({label:`Equipment grounding conductors (all) counted as 1 of ${egc.awg} AWG`, vol}); } // Yokes for (const y of yokes) { const addEq = y.count * 2; const vol = (VOLUME_BY_AWG[y.awg] || 0) * addEq; required += vol; equivalents += addEq; breakdown.push({label:`Device yokes ${y.awg} AWG × ${y.count} (2 conductors per yoke)`, vol}); } // Largest insulated AWG for clamps/fittings const awgMax = largestInsulatedAWG(conductors, yokes); if (clamps && awgMax) { const vol = (VOLUME_BY_AWG[awgMax] || 0) * 1; required += vol; equivalents += 1; breakdown.push({label:`Internal clamps (1 × ${awgMax} AWG)`, vol}); } if (fittings > 0 && awgMax) { const vol = (VOLUME_BY_AWG[awgMax] || 0) * fittings; required += vol; equivalents += fittings; breakdown.push({label:`Internal fittings × ${fittings} (${awgMax} AWG)`, vol}); } const result = { required, box: boxVol, margin: (typeof boxVol === 'number') ? (boxVol - required) : null, ok: (typeof boxVol === 'number') ? (boxVol >= required) : null, equiv: equivalents, breakdown }; renderResults(result); } function formatIn3(n) { return `${n.toFixed(2)} in³`; } function readBoxVolOrNull(){ const v = parseFloatSafe(els.boxVolume.value); return isNaN(v) ? null : v; } function renderResults({required, box, margin, ok, equiv, breakdown}) { // Required $('#requiredVolume').textContent = formatIn3(required || 0); // Box and margin if (typeof box === 'number') { $('#boxVolumeOut').textContent = formatIn3(box); const mEl = $('#marginOut'); if (typeof margin === 'number') { const pct = (box > 0) ? (margin / box * 100) : 0; mEl.textContent = `${formatIn3(margin)} (${pct.toFixed(1)}%)`; mEl.className = 'value ' + (margin >= 0 ? 'value-ok' : 'value-bad'); } else { mEl.textContent = '—'; mEl.className = 'value'; } } else { $('#boxVolumeOut').textContent = '—'; $('#marginOut').textContent = '—'; $('#marginOut').className = 'value'; } // Equivalents $('#equivOut').textContent = String(equiv || 0); // Status const status = $('#statusBadge'); if (ok === null) { status.className = 'status-badge'; status.textContent = 'Waiting for inputs'; } else if (ok) { status.className = 'status-badge status-ok'; status.textContent = 'Compliant ✓'; } else { status.className = 'status-badge status-fail'; status.textContent = 'Not compliant ✕'; } // Breakdown const list = $('#breakdownList'); list.innerHTML = ''; if (!breakdown || breakdown.length === 0) { const li = document.createElement('li'); li.innerHTML = '<span class="muted">No items yet</span><span>—</span>'; list.appendChild(li); } else { for (const item of breakdown) { const li = document.createElement('li'); const left = document.createElement('span'); const right = document.createElement('span'); left.textContent = item.label; right.textContent = formatIn3(item.vol); li.appendChild(left); li.appendChild(right); list.appendChild(li); } } } // Event wiring function onBlurRecalc(e) { const target = e.target; if (target.matches('input, select')) { // Validate specific fields if (target === els.boxVolume) validateBoxVolume(); if (target === els.egcCount || target === els.egcAwg) validateEgc(); if (target === els.fittingCount) validateFittings(); if (target.closest('.group-row')) validateGroupRow(target.closest('.group-row')); compute(); } } function onClick(e){ const t = e.target; // Quick pick chips if (t.matches('.chip[data-volume]')) { els.boxVolume.value = t.getAttribute('data-volume'); validateBoxVolume(); compute(); } // Add/Remove rows if (t === els.addConductorGroup) { createConductorRow({awg:'', count:''}); // Move focus into new row count const rows =
Given the NEC volume allowance function V(AWG) from Table 314.16(B): 18→1.50, 16→1.75, 14→2.00, 12→2.25, 10→2.50, 8→3.00, 6→5.00 (cubic inches) Total required volume: $V_{req} \;=\; \sum_{i} n_i \cdot V(\mathrm{AWG}_i)\;+\; \mathbf{1}_{\mathrm{EGC}>0}\cdot V(\mathrm{AWG}_{\mathrm{EGC,max}})\;+\; 2\!\!\sum_{j} y_j \cdot V(\mathrm{AWG}_{y_j})\;+\; \mathbf{1}_{\mathrm{clamp}}\cdot V(\mathrm{AWG}_{\max})\;+\; f \cdot V(\mathrm{AWG}_{\max})$ where: - $n_i$ = insulated conductors of size $\mathrm{AWG}_i$ that enter and terminate/splice (pass-through counts as 1). - $\mathrm{EGC,max}$ = largest equipment grounding conductor AWG (counted once if any EGCs are present). - $y_j$ = number of device yokes connected to conductors of $\mathrm{AWG}_{y_j}$ (each counts as 2 conductors). - $\mathrm{AWG}_{\max}$ = largest insulated conductor AWG present in the box (used for clamp and fitting allowances). - $f$ = number of internal support fittings.
- No variables provided in audit spec.
- Engineering — calcdomain.com · Accessed 2026-01-19
https://calcdomain.com/engineering - Electrical (US NEC) — calcdomain.com · Accessed 2026-01-19
https://calcdomain.com/subcategories/electrical - Official NFPA code page — nfpa.org · Accessed 2026-01-19
https://www.nfpa.org/codes-and-standards/all-codes-and-standards/list-of-codes-and-standards/detail?code=70 - ECM: Box Fill Calculations — ecmweb.com · Accessed 2026-01-19
https://www.ecmweb.com/content/article/20886012/box-fill-calculations - JADE Learning: NEC 314.16 — jadelearning.com · Accessed 2026-01-19
https://www.jadelearning.com/blog/nec-2017-article-314-16/
Last code update: 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.