Construction work lives inside units. A driveway is measured in feet and inches, poured in cubic yards, and bought in 80-lb bags of premix. Get the unit conversions wrong and you either short the job or waste money on bags that sit in the truck bed. The FixUpMath calculator suite was built with Astro and published free, because the math — not a paywall — should be the product. Building a calculator like this is a small project that teaches you real things: input parsing, dimensional analysis, and defensive rounding.
Parsing ft/in/metric input
A box labeled "Length" might receive 12 ft 6 in, 12'6", 3.81 m, or just 12. Your parser has to decide the unit and return a single number in a canonical unit — usually feet for imperial, meters for metric.
A pragmatic approach is to match a compound imperial pattern first, fall back to a single number with a unit suffix, and treat a bare number as feet. Here's a starting point:
function parseLength(input) {
const s = input.trim().toLowerCase();
// "12 ft 6 in" / "12'6""
const compound = s.match(/(\d+\.?\d*)\s*(ft|'|feet?)\s*(\d+\.?\d*)\s*(in|"|inch)?/i);
if (compound) {
const feet = parseFloat(compound[1]);
const inches = parseFloat(compound[3] || 0);
return feet + inches / 12;
}
// "3.81 m"
const metric = s.match(/(\d+\.?\d*)\s*(m|meters?)/i);
if (metric) {
return parseFloat(metric[1]) * 3.28084;
}
// "12 ft" or bare "12" (assumed feet)
const ft = s.match(/(\d+\.?\d*)\s*(ft|'|feet?)$/i);
if (ft) {
return parseFloat(ft[1]);
}
// Bare number → feet
const bare = s.match(/^(\d+\.?\d*)$/);
if (bare) {
return parseFloat(bare[1]);
}
throw new Error(`Cannot parse length: "${input}"`);
}
Surface the assumption. If you silently treat a bare 12 as feet, say so in the UI with helper text like "No unit? We assume feet." Defensive parsing is a feature, not a bug.
Volume = L × W × T
Once you have length, width, and thickness all in feet, volume in cubic feet is just the product:
function volumeCubicFeet(lengthFt, widthFt, thicknessFt) {
return lengthFt * widthFt * thicknessFt;
}
The thickness is where most DIYers trip. Bagged concrete for a patio is typically 4 in (0.333 ft); a driveway pour is often 6 in (0.5 ft). Hardcoding thickness without labeling it as an assumption is a bug waiting to happen — surface it in the UI with a dropdown and a default.
Converting ft³ to yd³
Ready-mix concrete is sold by the cubic yard. One cubic yard is 27 cubic feet, so:
function cubicFeetToCubicYards(cuFt) {
return cuFt / 27;
}
Division by 27 is the canonical trap in calculator code. Write it as a named constant (const CU_FT_PER_CU_YD = 27) so the magic number can be reviewed and so a linter or a reviewer doesn't have to guess what 27 means at 2 AM.
Applying a waste factor
Concrete shrinks, edges spill, and forms leak a little. The industry rule of thumb is to add 5–10% waste. Expose it as a slider so the user can feel the risk:
function applyWaste(yards, wastePercent = 10) {
return yards * (1 + wastePercent / 100);
}
For a 2.00 yd³ slab at 10% waste you get 2.20 yd³. Round the displayed value, not the intermediate — that's a general numerical hygiene rule that saves a lot of "why is my answer off by one bag?" complaints.
Rounding up to purchasable units: the 80-lb bag
Bagged / premixed concrete is sold by the bag, not by the fraction. A standard 80-lb bag yields roughly 0.6 ft³ (about 0.0222 yd³). You can't buy 0.4 of a bag, so you always round up:
function bagsNeeded(cuYards, cuFtPerBag = 0.6) {
const cuFt = cuYards * 27;
return Math.ceil(cuFt / cuFtPerBag);
}
Math.ceil is the most important function in construction calculator code. Math.round will short the job. Math.floor is a budget disaster. Every "how many X do I buy?" question in this domain rounds up.
Putting it together
End-to-end, a patio of 12 ft × 10 ft × 4 in (0.333 ft) thickness:
- volume = 12 × 10 × 0.333 = 39.96 ft³
- yards = 39.96 / 27 = 1.48 yd³
- +10% waste = 1.63 yd³
- bags = ceil(1.63 × 27 / 0.6) = ceil(73.35) = 74 bags
Show the user the intermediate values (volume, yards, waste-adjusted) so they can audit the math, and put the bag count in big type at the top.
Why this matters
Unit-aware calculators are a great project for learning input parsing, dimensional analysis, and defensive rounding — and they're genuinely useful. The FixUpMath suite was built with Astro and published free so the math, not the paywall, is the product. If you're playing around with calculator apps, start with concrete: it teaches you parsing, unit conversion, waste factors, and the most important JavaScript function in the construction world — Math.ceil.
Try the live concrete calculator and compare it to your own implementation. The trickiest part isn't the math; it's the edge cases in what a real person will type into a box labeled "Length".













