DEV Community

xg704863664
xg704863664

Posted on

Three interactive calculators, zero dependencies: a static-site pattern

Static sites have one obvious limitation: no server. So when I wanted to add calculators to a content site, the answer was not a backend — it was about 40 lines of vanilla JS per tool.

Here are three patterns I ended up reusing, with the real tools linked so you can see them working.

Pattern 1: unit conversion with a formula

The first tool is a raised bed soil calculator. The whole thing is one formula — volume = length × width × depth — plus unit conversion and rounding.

var U = { cm: 0.01, m: 1, ft: 0.3048, in: 0.0254 };

function run() {
  var f = U[document.getElementById("unit").value];
  var L = parseFloat(document.getElementById("len").value) * f;
  var W = parseFloat(document.getElementById("wid").value) * f;
  var D = parseFloat(document.getElementById("dep").value) * f;
  if (!(L > 0 && W > 0 && D > 0)) return;
  var m3 = L * W * D;
  // ...render
}
Enter fullscreen mode Exit fullscreen mode

The part that matters is the guard clause. Users will type 0, -, or nothing, and a calculator that renders NaN looks broken.

Live version: Raised Bed Soil Calculator

Pattern 2: rule-based sizing

The second tool takes a count and applies rules. A chicken coop needs 2–3 sq ft per bird inside and 8–10 sq ft in the run, plus one nest box per five hens.

The interesting design decision is exposing the rules as a dropdown rather than hardcoding one standard:

<select id="space">
  <option value="2,8">Minimum (2 + 8 sq ft)</option>
  <option value="3,10" selected>Comfortable (3 + 10 sq ft)</option>
  <option value="4,12">Generous (4 + 12 sq ft)</option>
</select>
Enter fullscreen mode Exit fullscreen mode
var parts = document.getElementById("space").value.split(",");
var inside = parseFloat(parts[0]);
var run = parseFloat(parts[1]);
var coopSqFt = n * inside;
Enter fullscreen mode Exit fullscreen mode

Encoding the rules in the markup rather than in JS means you can add a preset without touching the logic.

Live version: Chicken Coop Size Calculator

Pattern 3: client-side filtering as a "tool"

The third one is not a calculator at all — it is a search filter over a static table. 24 rows of food storage times, filtered as you type.

var rows = [].slice.call(document.querySelectorAll("tr[data-k]"));
function run() {
  var v = q.value.trim().toLowerCase();
  rows.forEach(function (r) {
    r.style.display = r.getAttribute("data-k").indexOf(v) >= 0 ? "" : "none";
  });
}
q.addEventListener("input", run);
Enter fullscreen mode Exit fullscreen mode

The trick is the data-k attribute holding a pre-lowercased search key. It means you can search for text that is not visible in the row — synonyms, alternate spellings, unit names.

Live version: Food Storage Time Lookup

Why bother on a static site

Three reasons that turned out to matter more than I expected:

  1. No build step. The JS is inline in the page. Nothing to compile, nothing to version.
  2. Works with JS disabled. The content is a real HTML table or a real list of numbers. The tool is an enhancement, not a requirement.
  3. Tools earn links. People link to "this calculator" far more readily than to "this article". For a new site with no authority, that is the whole game.

The bit that is easy to get wrong

Mobile. All three tools use a flex row with flex-wrap: wrap and a full-width input below 620px. Without that, the labels and inputs fight for space and the tool becomes unusable on a phone — which is where most traffic actually is.

@media (max-width: 620px) {
  .calc-row label { flex: 0 0 100%; }
  .calc-row input { width: 100%; }
}
Enter fullscreen mode Exit fullscreen mode

If you have built tools like this on a static host, I would be curious what patterns you reused. The three above cover most of what I needed, but I suspect there is a fourth one I have not hit yet.

Top comments (0)