DEV Community

loading...
Cover image for 275 bytes BMI Calculator

275 bytes BMI Calculator

madsstoumann profile image Mads Stoumann ・2 min read

You don't always need a large frontend framework for interactive components.

As an example, I've made a BMI Calculator, which is only 275 bytes, minified and gzipped.

I always wrap smaller, interactive components, in either a <form> or a <fieldset>-tag.
Depending on the component, I add a single eventListener, either onchange or oninput.

This is a "catch all" for any input within the <form> or <fieldset>. If I need to know the specific element that changed, it's in the event.target.

Let's dissect the calculator. The <form> has two <input type="range"> (height, weight) and three <output>-tags (height info, weight info, bmi result).

Excerpt:

<input type="range" name="h" min="150" max="230" step="0.5" value="180" />
<output name="ho"><output>
Enter fullscreen mode Exit fullscreen mode

The un-minified JavaScript-code looks like this:

function B() {
  const groups = [[0,18.49], [18.5,24.99], [25,29.99], [30,34.99], [35,39.99], [40,100]];
  const height = this.h.valueAsNumber;
  const weight = this.w.valueAsNumber;
  const bmi = parseFloat(weight / ((height / 100) ** 2)).toFixed(2);
  const index = groups.findIndex(arr => arr[0] <= bmi && bmi < arr[1]);
  let inches = (height*0.393700787).toFixed(0);
  this.ho.value = `${height} cm / ${Math.floor(inches / 12)}' ${inches %= 12}"`;
  this.wo.value = `${weight} kg / ${(weight*2.2046).toFixed(2)} lb`;
  this.g[index].checked = true;
  this.r.value = bmi;
}
Enter fullscreen mode Exit fullscreen mode

groups is an array of BMI-ranges, corresponding to the six BMI-groups (underweight, normal weight etc.).

height and weight are references to the range-input values.

bmi is the formula for calculating a BMI using height and weight.

index finds the index of the BMI-group, in which range the current bmi is found. This value is later used to set the current BMI-group (a radio-button-group):

this.g[index].checked = true;
Enter fullscreen mode Exit fullscreen mode

An <output>-tag can either be set using .innerText or .value. I prefer the latter, and that's how the labels are set, as an example:

this.r.value = bmi;
Enter fullscreen mode Exit fullscreen mode

And the result:

The code itself is 381 bytes, gzipped approx. 275 bytes. However, if your modules are so small, there's no benefit in gzipping them, as the "un-gzipping" will take longer than the benefit of the smaller file-size.

Thanks for reading, and happy coding!

Discussion (4)

Collapse
ravenxt profile image
Alberthor Inasuit

Looks Awesome. You mind if we use it on our site?

Collapse
madsstoumann profile image
Mads Stoumann Author

Thanks! You’re welcome to use it - will you share the url?

Collapse
ravenxt profile image
Collapse
madza profile image
Madza

nice colors in weight categories 🎨

Forem Open with the Forem app