My take on floating labels with ParsleyJS form validation baked-in
A Pen by Zach Schnackel on CodePen.
My take on floating labels with ParsleyJS form validation baked-in
A Pen by Zach Schnackel on CodePen.
| <div class="bt-form__wrapper"> | |
| <form class="uk-form bt-flabels js-flabels" data-parsley-validate data-parsley-errors-messages-disabled> | |
| <div class="uk-grid uk-grid-collapse"> | |
| <div class="uk-width-1-2"> | |
| <div class="bt-flabels__wrapper"> | |
| <label>First Name</label> | |
| <input type="text" name="first_name" placeholder="First Name" autocomplete="off" data-parsley-required /> | |
| <span class="bt-flabels__error-desc">Required</span> | |
| </div> | |
| </div> | |
| <div class="uk-width-1-2"> | |
| <div class="bt-flabels__wrapper bt-flabels--right"> | |
| <label>Last Name</label> | |
| <input type="text" name="last_name" autocomplete="off" placeholder="Last Name" data-parsley-required /> | |
| <span class="bt-flabels__error-desc">Required</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bt-flabels__wrapper"> | |
| <label>Email</label> | |
| <input type="text" name="email" placeholder="name@website.com" data-parsley-required data-parsley-type="email" autocomplete="off" /> | |
| <span class="bt-flabels__error-desc">Required/Invalid Email</span> | |
| </div> | |
| <div class="bt-flabels__wrapper"> | |
| <label>Phone (# used as password)</label> | |
| <input type="text" name="phone" data-parsley-required placeholder="Phone (# used as password)" autocomplete="off" /> | |
| <span class="bt-flabels__error-desc">Required/Invalid Phone</span> | |
| </div> | |
| <div class="uk-text-center uk-margin-top"> | |
| <button type="submit" class="uk-button uk-button-primary uk-button-large js-submit">Submit</button> | |
| </div> | |
| </form> | |
| </div> |
| (($) -> | |
| 'use strict' | |
| floatingLabel = (onload) -> | |
| $input = $(this) | |
| # Check for value onload | |
| if onload | |
| $.each $('.bt-flabels__wrapper input'), (index, value) -> | |
| $current_input = $(value) | |
| if $current_input.val() | |
| $current_input.closest('.bt-flabels__wrapper').addClass 'bt-flabel__float' | |
| return | |
| setTimeout (-> | |
| if $input.val() | |
| $input.closest('.bt-flabels__wrapper').addClass 'bt-flabel__float' | |
| else | |
| $input.closest('.bt-flabels__wrapper').removeClass 'bt-flabel__float' | |
| return | |
| ), 1 | |
| return | |
| $('.bt-flabels__wrapper input').keydown floatingLabel | |
| $('.bt-flabels__wrapper input').change floatingLabel | |
| window.addEventListener 'load', floatingLabel(true), false | |
| # Parsley | |
| $('.js-flabels').parsley().on 'form:error', -> | |
| $.each this.fields, (key, field) -> | |
| if field.validationResult isnt true | |
| field.$element.closest('.bt-flabels__wrapper').addClass 'bt-flabels__error' | |
| return | |
| return | |
| $('.js-flabels').parsley().on 'field:validated', -> | |
| if this.validationResult is true | |
| this.$element.closest('.bt-flabels__wrapper').removeClass 'bt-flabels__error' | |
| return | |
| else | |
| this.$element.closest('.bt-flabels__wrapper').addClass 'bt-flabels__error' | |
| return | |
| return | |
| ) jQuery |
| <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/parsley.js/2.1.2/parsley.min.js"></script> |
| @border-color: #c8c8c8; | |
| @active-bg: #f5f8fc; | |
| @active-color: #52a6e1; | |
| @anim: cubic-bezier(0.215, 0.610, 0.355, 1.00); | |
| @error-bg: #feeeee; | |
| @error-color: darken(@error-bg, 35); | |
| .bt-form__wrapper { | |
| margin: 30px auto; | |
| max-width: 500px; | |
| } | |
| .bt-flabels { | |
| input[type] { | |
| position: relative; | |
| width: 100%; | |
| height: 50px; | |
| border: none; | |
| border-radius: 0; | |
| z-index: 1; | |
| transition: background 0.3s @anim, border-color 0.3s @anim; | |
| &:focus { | |
| background: @active-bg; | |
| } | |
| } | |
| label { | |
| pointer-events: none; | |
| position: absolute; | |
| opacity: 0; | |
| top: 0; | |
| transform: translateY(15%); | |
| z-index: 2; | |
| font-weight: bold; | |
| font-size: 10px; | |
| text-transform: uppercase; | |
| padding-left: 6px; | |
| color: @active-color; | |
| transition: transform 0.3s @anim, opacity 0.3s @anim; | |
| } | |
| >*:not(:first-child) { | |
| &.bt-flabels__wrapper, .bt-flabels__wrapper { | |
| border-top: none; | |
| } | |
| } | |
| } | |
| .bt-flabels__wrapper { | |
| position: relative; | |
| border: 1px solid @border-color; | |
| } | |
| .bt-flabels__error-desc { | |
| position: absolute; | |
| top: 0; | |
| right: 6px; | |
| opacity: 0; | |
| font-weight: bold; | |
| color: @error-color; | |
| font-size: 10px; | |
| text-transform: uppercase; | |
| z-index: 3; | |
| pointer-events: none; | |
| } | |
| .bt-flabels__error { | |
| input[type] { | |
| background: @error-bg; | |
| &:focus { | |
| background: @error-bg; | |
| } | |
| } | |
| .bt-flabels__error-desc { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .bt-flabels--right { | |
| border-left: none; | |
| } | |
| .bt-flabel__float { | |
| label { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| input[type] { | |
| padding-top: 9px; | |
| } | |
| } |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.21.0/css/uikit.almost-flat.min.css" rel="stylesheet" /> |