<main>
  <section class='form-container'>
    <h1>Grades</h1>
    <form id='grades'>
      <div class='entry'>
        <label for='maths'>Maths</label>
        <input id='maths' type='number' value='0' min='0' max='100'>
        <span>%</span>
      </div>
      <div class='entry'>
        <label for='english'>English</label>
        <input id='english' type='number' value='0' min='0' max='100'>
        <span>%</span>
      </div>
      <div class='entry'>
        <label for='physics'>Physics</label>
        <input id='physics' type='number' value='0' min='0' max='100'>
        <span>%</span>
      </div>
      <div class='entry'>
        <label for='chemistry'>Chemistry</label>
        <input id='chemistry' type='number' value='0' min='0' max='100'>
        <span>%</span>
      </div>
      <div class='entry'>
        <label for='biology'>Biology</label>
        <input id='biology' type='number' value='0' min='0' max='100'>
        <span>%</span>
      </div>
      <div class='entry'>
        <label for='history'>History</label>
        <input id='history' type='number' value='0' min='0' max='100'>
        <span>%</span>
      </div>
      <div class='entry'>
        <label for='geography'>Geography</label>
        <input id='geography' type='number' value='0' min='0' max='100'>
        <span>%</span>
      </div>
      <button id='calculate' type='submit'>Calculate</button>
    </form>
    <h2 id='total'></h2>
  </section>
</main>
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap');

*, *:before, *:after {
  box-sizing: border-box;
}

body {
  font-family: 'Lato', sans-serif;
  font-weight: 400;
}

main {
  display: grid;
  place-items: center;
  padding: 2rem 0;
}

.form-container {
  width: 250px;
}

.form-container h1, h2{
  font-weight: 700;
  text-align: center;
}

.entry {
  position: relative;
  width: 100%;
  display: grid;
  grid-template-columns: 100px 1fr;
  margin-bottom: 1rem;
  align-items: center;
}

.entry input {
  padding: .5rem;
  width: 100%;
}

.entry span {
  position: absolute;
  right: -25px;
}

button {
  margin: 1rem 0;
  padding: .5rem 1rem;
  cursor: pointer;
}

input:invalid {
  color: red;
}

input:valid {
  color: black;
}
// Here we wrap the code in a function that will be called when
// all the content has been drawn/written to the page. DOM = Document Object Model.
// This has the added benefit of containing your code, keeping it out of the
// Global Namespace, so that it can't be overwritten or conflict with code elsewhere.
window.addEventListener('DOMContentLoaded', function(event) {

  // Note: I have opted for separate shorter functions
  // This makes them easier to debug, test and makes them re-usable.
  // We can re-use clampScore, or displayScore elsewhere if needed.
  // The code isn't hidden in the middle of one long function.

  // In the clamp function below max = 15, min = 0 are default values
  // and are optional e.g.
  // clampScore(17) -> 15
  // clampScore(-5) -> 0
  // clampScore(22, 20, 5) -> 20 (here we set max to 20, and min to 5)
  // clampScore(1, 20, 5) -> 5
  function clampScore(score, max = 15, min = 0) {
    return Math.max(Math.min(max, score), min);
  }

  function calculateScore(score) {
    /* Courtesy of Archibald */
    return clampScore(2 * Math.floor(score / 10) - 3);
  }

  function sumInputValues(inputs) {
    let total = 0;

    inputs.forEach(function(input) {
      // inputs values by default are strings 
      // So '10' + '13' = '1013' - no good!
      // convert the string to a number first
      // 10 + 13 = 23 - better!
      const inputValue = Number(input.value);

      total += calculateScore(inputValue);
    })

    return total;
  }

  function displayScore(score) {
    const displayScore = document.getElementById('total');
    
    displayScore.textContent = 'Score: ' + score;
  }

  // the event object is passed to a handler by default when an event is fired.
  function calculateScores(event) {
    // press F12(chrome) to bring up your console
    // click on the 'Calculate' button in the preview window and check your console.
    // click on SubmitEvent and have a look at the properties.
    console.dir(event);
    
    event.preventDefault(); // stop the form submitting to a url
    
    // We added an EventListener to the form below
    // the target property on the event object is the form element.
    // You can see this in the console as pointed out above.
    const form = event.target;
    // find the inputs using the form as the root to search from
    const inputs = form.querySelectorAll('input'); 
    const total = sumInputValues(inputs);

    displayScore(total);
  }

  const form = document.querySelector('#grades'); // get the form element
  form.addEventListener('submit', calculateScores); // add a submit listener
})

Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.