JSFiddle - React, Tailwind, and code Playground

HTML

<form action="register" method="post" id="myform"><input type="hidden" name="redirect" value=""><table><thead><tr><td colspan="2"><h2>Register</h2></td></tr></thead><tbody><tr><td><label for="username">Username:</label></td><td><input id="username" type="text" name="username" data-valid="false" data-validate="^\w[\w_]{2,}"><div data-info="Invalid username." class="indicator"></div></td></tr><tr><td><label for="email">E-Mail:</label></td><td><input id="email" type="text" name="email" data-valid="false" data-validate="^\w[\w_+\.-]{2,}@\w(\-?\w)*\.[a-zA-Z]{2,}"><div data-info="Invalid e-mail address." class="indicator"></div></td></tr><tr><td><label for="password">Password:</label></td><td><input id="password" type="password" name="password" data-valid="false" data-validate="\S{6,}"><div data-info="Passsword must be at least 6 letters long." class="indicator"></div></td></tr><tr><td><label for="password_confirm">Confirm Password:</label></td><td><input id="confirm" type="password" data-valid="true" data-confirm="password"><div data-info="Both password need to match." class="indicator"></div></td></tr></tbody><tfoot><tr><td colspan="2"><input type="submit" value="Register"></td></tr></tfoot></table></form>

CSS

div.indicator{width:16px;height:16px;margin:0 2px;display:inline-block;vertical-align:middle;position:relative;}
div.indicator.ok,input[data-valid="true"]+div.indicator{background:green}
div.indicator.fail,input[data-valid="false"]+div.indicator{background:red}
div.indicator.fail:hover:after,input[data-valid="false"]:focus+div.indicator:after{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;display:block;position:absolute;z-index:1;background-color:#fff;color:#333;text-shadow:none;border:1px solid #000;content:attr(data-info);font:11px sans-serif;padding:0 2px;width:200px;right:-35px;top:1.8em}

JavaScript

(function (ns, $) {

    function validateInput() {
        var input = $(this);
        input.attr('data-valid', (input.val().search(input.attr('data-validate')) >= 0).toString());
        console.log('validating input on ',  input);
    }

    function confirmInput() {
        var input = $(this);
        input.attr('data-valid', (input.val() === $('#'+input.attr('data-confirm')).val()).toString());
        console.log('confirming input on ', input);
    }

    var Validator = ns.Validator = function (form) {
        var self = this;
        this.form = $(form).bind('submit', function (e) {
            var invalidInputs = self.form.find('input[data-valid=false]');
            if (invalidInputs.length > 0) {
                console.log('prevent!');
                invalidInputs.eq(0).focus();
                e.preventDefault();
            }
        });

        this.form.find('input[data-validate]').each(validateInput).keyup(validateInput);
        this.form.find('input[data-confirm]').each(function () {
            var that = this;
            confirmInput.apply(this);
            console.log(this);
            $('#'+$(this).attr('data-confirm')).keyup(function () {
                console.log($(this).val());
                confirmInput.apply(that);
            });
        }).keyup(confirmInput);
    };
    return ns;
})(window, jQuery);

new Validator('#myform');