JSFiddle - React, Tailwind, and code Playground

HTML

<label for="edQuantity">Quantity:</label>
<input id="edQuantity" type="number" min="2" max="10" step="3" required 
    onchange="edQuantityChange(this, event)" 
    onkeyup="edQuantityChange(this, event)">
<ul>
    <li>edQuantity.value = <span id="lblValue"></span></li>
    <li>edQuantity.validity = <span id="lblValidity"></span></li>
    <li>edQuantity.validity.valid = <span id="lblValidityValid"></span></li>
    <li>edQuantity.validity.badInput = <span id="lblValidityBadInput"></span></li>
    <li>edQuantity.validity.rangeUnderflow = <span id="lblValidityRangeUnderflow"></span></li>
    <li>edQuantity.validity.rangeOverflow = <span id="lblValidityRangeOverflow"></span></li>
    <li>edQuantity.validity.patternMismatch = <span id="lblValidityPatternMismatch"></span></li>
    <li>edQuantity.validity.stepMismatch = <span id="lblValidityStepMismatch"></span></li>
</ul>
    <p><input type="submit"></p>

CSS

:invalid {
    background-color: #FFCCCC;
}

JavaScript

function edQuantityChange(sender, event) {
    var value = sender.value;

    document.getElementById("lblValue").innerText = value;

    document.getElementById("lblValidity").innerText = sender.validity;
    if (sender.validity !== null)
    {
        document.getElementById("lblValidityValid").textContent = sender.validity.valid;
        document.getElementById("lblValidityBadInput").textContent = sender.validity.badInput;
        document.getElementById("lblValidityRangeUnderflow").textContent = sender.validity.rangeUnderflow;
        document.getElementById("lblValidityRangeOverflow").textContent = sender.validity.rangeOverflow;
        document.getElementById("lblValidityPatternMismatch").textContent = sender.validity.patternMismatch;
        document.getElementById("lblValidityStepMismatch").textContent = sender.validity.stepMismatch;
    }
}