HTML5 Form Validation Message

How to implement your own version or speech bubble using default html5 messages.

HTML

<h1>WITH VALIDATION</H1>
<form name="login" id="loginForm" method="POST">
    <input type="email" name="username" placeholder="Email" required>
    <input type="password" name="password" placeholder="Password" required>
</form>
        
<h1>NO VALIDATION</H1>
        
<form name="login" id="loginForm" method="POST" novalidate>
    <input type="email" name="username" placeholder="Email">
    <input type="password" name="password" placeholder="Password">
    <input type="submit" value="LOG IN" class="hero left clearBoth">
</form>

CSS

form:not([novalidate]) input:required, form:not([novalidate]) textarea:required {
    background: orange;
}
form:not([novalidate]) input:required:valid, form:not([novalidate]) textarea:required:valid {
    background: green;
    -webkit-box-shadow: 0 0 5px #5cd053;
    box-shadow: 0 0 5px #5cd053;
    -o-box-shadow: 0 0 5px #5cd053;
    -moz-box-shadow: 0 0 5px #5cd053;
    border-color: #28921f
}
form:not([novalidate]) input:not(:focus):valid, form:not([novalidate]) textarea:not(:focus):valid {
    box-shadow: none;
    border: 1px solid #d2d2d2
}
form:not([novalidate]) input:focus:invalid, form:not([novalidate]) textarea:focus:invalid {
    background: red;
    -webkit-box-shadow: 0 0 5px #d45252;
    box-shadow: 0 0 5px #d45252;
    -o-box-shadow: 0 0 5px #d45252;
    -moz-box-shadow: 0 0 5px #d45252;
    border-color: #b03535
}
span.formHintBubble {
    position: absolute;
    background: #323232;
    margin-top: 50px;
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    -khtml-border-radius: 10px;
    border-radius: 10px;
    -o-border-radius: 10px;
    -webkit-background-clip: padding-box;
    -moz-background-clip: padding;
    background-clip: padding-box;
    padding: 5px 40px 5px 10px;
    color: white;
    filter: alpha(opactiy=90);
    -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opactiy=90)";
    -moz-opacity: 0.9;
    -khtml-opacity: 0.9;
    opacity: 0.9;
    zoom: 1;
    -webkit-box-shadow: 1px 1px 6px 1px rgba(0, 0, 0, 0.2);
    box-shadow: 1px 1px 6px 1px rgba(0, 0, 0, 0.2);
    -o-box-shadow: 1px 1px 6px 1px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 1px 1px 6px 1px rgba(0, 0, 0, 0.2)
}
span.formHintBubble:after {
    height: 0;
    width: 0;
    position: absolute;
    left: 50%;
    margin-left: -15px;
    bottom: 0px;
    z-index: 9;
    border-color: transparent;
    border-style: solid;
    border-width: 15px;
    border-bottom-color: #323232;
    content:" ";
    margin-bottom: 27px;
    left: 25px
}
span.formHintBubble...

JavaScript

var createAllErrors = function () {
       var form = $(this);
       var showAllErrorMessages = function () {
           if ($('.formHintBubble').length > 0) {
               $('.formHintBubble').remove();
               $('body').off('.formBubble');
           }
           //Add a close button to the speech bubble to remove it if nesscessary     
           $('body').on('click.formBubble', '.formHintBubble .cross', function () {
               $(this).closest('.formHintBubble').remove();
               $('body').off('.formBubble');
           });

           //Find all invalid fields within the form.                       
           var item = form.find(':invalid').first();
           var node = item.get(0);
           var pos = item.position();
           var message = node.validationMessage || 'Invalid value.'; //Opera does not fill the validationMessage property.
           var bubble = $('<span/>').html('<span class="formHintBubble" style="left: ' + pos.left + 'px; top:' + pos.top + 'px;">' + message + '<div class="cross">X</div></span>').contents();
           bubble.insertAfter(item);

       };

       $('input[type=submit]', form).on('click', showAllErrorMessages);
       $('input,textarea,select', form).on('keypress', function (e) {
           //keyCode 13 is Enter or tab
           if (e.keyCode == 13 || e.keyCode == 9) {
               showAllErrorMessages();
           }
       });
   };
   $('form').each(createAllErrors);