Inspired by Luke Wroblewski's How to Reduce E-Mail Input Errors, this tutorial applies advanced email validation using Mailgun and Kabu. Along the way we'll add several enhancements to improve the form process and feedback.

1. Create a navbar

Start by creating a navbar. Let's add links to Sign in and Sign up and give it a background-fill of .fill-denim. In our example we'll only focus on Sign up.

<div class='navbar fill-denim keyline-bottom col-sm-12 animate clearfix round'>
  <div class='container-fluid contain'>
    <nav class='col-sm-12 text-right pad1y contain clearfix noprint'>
      <a class='logo pad1y pull-left text-left' href='#fakelink'>Kabu</a>
      <div class='primary small strong row2'>
        <a href='#fakelink' class='hidden-xs quiet animate round pad1 truncate inline dark'>Sign in</a>
        <a href='#fakelink' class='hidden-xs quiet animate round pad1 truncate inline dark'>Sign up</a>
        <a href='#dropdown' class='visible-xs authmenu keyline-all droplink 
          quiet round animate pull-right center dark'>
          <i class='icon icon-list'></i>
        </a>
        <div class='dropdown fill-white keyline-all round animate'>
          <div class='visible-xs keyline-bottom pad1'>
            <a href='#fakelink'>Sign in</a>
            <a href='#fakelink'>Sign up</a>
          </div>
        </div>
      </div>
    </nav>
  </div>
</div>

2. Create a Sign up modal

Instead of navigating away to a separate sign up page, we'll use a modal that lets users sign up from anywhere on the site. Let's connect our Sign up link to a modal.

<div class='navbar fill-denim keyline-bottom col-sm-12 animate clearfix round'>
  <div class='container-fluid contain'>
    <nav class='col-sm-12 text-right pad1y contain clearfix noprint'>
      <a class='logo pad1y pull-left text-left' href='#fakelink'>Kabu</a>
      <div class='primary small strong row2'>
        <a href='#fakelink' class='hidden-xs quiet animate round pad1 truncate inline dark' data-toggle='modal' data-target='#signin'>Sign in</a>
        <a href='#fakelink' class='hidden-xs quiet animate round pad1 truncate inline dark' data-toggle='modal' data-target='#signup'>Sign up</a>
        <a href='#dropdown' class='visible-xs authmenu keyline-all droplink 
          quiet round animate pull-right center dark'>
          <i class='icon icon-list'></i>
        </a>
        <div class='dropdown fill-white keyline-all round animate'>
          <div class='visible-xs keyline-bottom pad1'>
            <a href='#fakelink' data-toggle='modal' data-target='#signin'>Sign in</a>
            <a href='#signup' data-toggle='modal' data-target='#signup'>Sign up</a>
          </div>
        </div>
      </div>
    </nav>
  </div>
</div>

<div id='signup' class='animate modal'>
  <div class='modal-dialog'>
    <form method='post' class='container-fluid'>
      <div class='col-sm-6 col-xs-12 fill-white modal-content contain'>
        <a href='#fakelink' class='quiet pin-right close' data-dismiss='modal'>
          <i class='icon icon-remove'></i>
        </a>
        <div class='pad2y pad4x center'>
          <h3>Heading goes here...</h3>
        </div>
        <div class='space-bottom2 pad4x'>
          content goes here...
        </div>
        <div class='modal-actions fill-gray pad2y pad4x clearfix'>
          <a href='#fakelink' class='btn btn-primary' data-dismiss='modal'>.btn-primary</a>
          <a href='#fakelink' class='btn btn-default' data-dismiss='modal'>.btn-default</a>
        </div>
      </div>
    </form>
  </div>
</div>

3. Create a Sign up form

Now that we have our modal let's create a sign up form. We'll take several easy steps to make email inputs easier on mobile devices like turning autocapitalize and autocorrect off and setting input type to email.

Our sign up form also needs to stand out so we'll apply a .fill-blue background and .fancy heading. Little touches like Terms of Service and Privacy Policy can make all the difference in creating a positive impression on users.

<div class='navbar fill-denim keyline-bottom col-sm-12 animate clearfix round'>
  ...
</div>

<div id='signup' class='animate modal'>
  <div class='modal-dialog'>
    <form method='post' class='container-fluid'>
      <div class='col-sm-6 col-xs-12 fill-blue modal-content contain'>
        <div class='dark'>          
          <a href='#fakelink' class='quiet pin-right close' data-dismiss='modal'>
            <i class='icon icon-remove'></i>
          </a>
          <header class='pad2y pad4x center'>
            <h3 class='fancy'>Sign up for Kabu</h3>
            <p class='quiet'>
              Bacon ipsum dolor amet short ribs ribeye hamburger.
            </p>
          </header>
          <div class='space-bottom2 pad4x'>
            <fieldset>
              <label for='username'>Username or email</label>
              <input id='username' type='email' autocorrect='off' autocapitalize='off' class='stretch'>
            </fieldset>
            <fieldset>
              <label for='password'>Password</label>
              <input id='password' type='password' class='stretch'>
            </fieldset>
            <p class='quiet small'>
              You agree to the Kabu <a href='#fakelink'>Terms of Service</a> and <a href='#fakelink'>Privacy Policy</a>.
            </p>
          </div>
        </div>
        <div class='modal-actions fill-gray pad2y pad4x clearfix'>
          <div class='col-xs-6'>
            <a href='#fakelink' class='btn btn-primary btn-block' data-dismiss='modal'>Sign up</a>
          </div>
          <small class='col-xs-6 pad1y center'>
            <a class='quiet' href='#fakelink'>Already a Kabu member?<i class='icon icon-arrow-right icon-sm'></i></a>
          </small>
        </div>
      </div>      
    </form>
  </div>
</div>

4. Creating feedback

One of the great features of Mailgun is that it returns suggestions in case the email was mistyped. We'll be integrating with Mailgun shortly but before that let's design the look and feel of feedback when an email has suggestions.

To associate feedback with the input it belongs to we'll position the suggestion below Username and darken its background with a subtle .fill-darken. Notice the use of plain english in asking the user if they meant to use another email. Later we'll add javascript so clicking this suggestion updates the email.

<div class='navbar fill-denim keyline-bottom col-sm-12 animate clearfix round'>
  ...
</div>

<div id='signup' class='animate modal'>
  <div class='modal-dialog'>
    <form method='post' class='container-fluid'>
      <div class='col-sm-6 col-xs-12 fill-blue modal-content contain'>
        <div class='dark'>          
          <a href='#fakelink' class='quiet pin-right close' data-dismiss='modal'>
            <i class='icon icon-remove'></i>
          </a>
          <header class='pad2y pad4x center'>
            <h3 class='fancy'>Sign up for Kabu</h3>
            <p class='quiet'>
              Bacon ipsum dolor amet short ribs ribeye hamburger.
            </p>
          </header>
          <div class='space-bottom2 pad4x'>
            <fieldset>
              <label for='username'>Username or email</label>
              <input id='username' type='email' autocorrect='off' autocapitalize='off' class='stretch'>
              <div class='fill-darken0 dark pad1'>
                <p class='small'>
                  <i class='icon icon-question-sign pad0r'></i>
                  Did you mean <a href='#fakelink' class='animate' tabindex='-1'>zwelch@gmail.com</a>?
                </p>
              </div>
            </fieldset>
            <fieldset>
              <label for='password'>Password</label>
              <input id='password' type='password' class='stretch'>
            </fieldset>
            <p class='quiet small'>
              You agree to the Kabu <a href='#fakelink'>Terms of Service</a> and <a href='#fakelink'>Privacy Policy</a>.
            </p>
          </div>
        </div>
        <div class='modal-actions fill-gray pad2y pad4x clearfix'>
          <div class='col-xs-6'>
            <a href='#fakelink' class='btn btn-primary btn-block' data-dismiss='modal'>Sign up</a>
          </div>
          <small class='col-xs-6 pad1y center'>
            <a class='quiet' href='#fakelink'>Already a Kabu member?<i class='icon icon-arrow-right icon-sm'></i></a>
          </small>
        </div>
      </div>      
    </form>
  </div>
</div>

5. Integrating with Mailgun

Mailgun is a powerful email service for developers and used at large companies such as GitHub, Lyft, Stripe and Heroku. We'll use their open-source jQuery plugin to validate emails on our sign up form.

Each request to mailgun returns an is_valid boolean. Mailgun also returns suggestions for mistyped emails. We'll use our feedback markup from Step 4 and add it dynamically when there's a suggestion. Try typing in example@gnail.com and observe how clicking the suggestion updates Username.

<div class='navbar fill-denim keyline-bottom col-sm-12 animate clearfix round'>
  ...
</div>

<div id='signup' class='animate modal'>
  <div class='modal-dialog'>
    <form method='post' class='container-fluid'>
      <div class='col-sm-6 col-xs-12 fill-blue modal-content contain'>
        <div class='dark'>
          <a href='#fakelink' class='quiet pin-right close' data-dismiss='modal'>
            <i class='icon icon-remove'></i>
          </a>
          <header class='pad2y pad4x center'>
            <h3 class='fancy'>Sign up for Kabu</h3>
            <p class='quiet'>
              Bacon ipsum dolor amet short ribs ribeye hamburger.
            </p>
          </header>
          <div class='space-bottom2 pad4x'>
            <fieldset>
              <label for='username'>Username or email</label>
              <input id='username' type='email' autocorrect='off' autocapitalize='off' class='stretch'>
            </fieldset>
            <fieldset>
              <label for='password'>Password</label>
              <input id='password' type='password' class='stretch'>
            </fieldset>
            <p class='quiet small'>
              You agree to the Kabu <a href='#fakelink'>Terms of Service</a> and <a href='#fakelink'>Privacy Policy</a>.
            </p>
          </div>
        </div>
        <div class='modal-actions fill-gray pad2y pad4x clearfix'>
          <div class='col-xs-6'>
            <a href='#fakelink' class='btn btn-primary btn-block' data-dismiss='modal'>Sign up</a>
          </div>
          <small class='col-xs-6 pad1y center'>
            <a class='quiet' href='#fakelink'>Already a Kabu member?<i class='icon icon-arrow-right icon-sm'></i></a>
          </small>
        </div>
      </div>
    </form>
  </div>
</div>

$(function() {
  $('.mailgun').mailgun_validator({
    api_key: 'pubkey-48f4dfdf2e81bd0628a6331123947d12',
    in_progress: mailgun_progress,
    success: mailgun_success
  });

  function mailgun_progress() {
    $('.mailgun-feedback').remove();
  }

  function mailgun_success(data) {
    $field = $('.mailgun').closest('fieldset')
    $field.append(mailgun_suggestion(data['is_valid'], data['did_you_mean']));
  }

  function mailgun_suggestion(is_valid, alternate) {
    if (alternate) {
      $suggestion = $('<a href="#fakelink" class="animate" tabindex=-1>')
                    .text(alternate)
                    .click(function(e) {
                      suggestion = $(this).text();
                      $('.mailgun').val(suggestion);
                      $('.mailgun-feedback').remove();
                    });

      return  $('<div>')
              .addClass('mailgun-feedback fill-darken0 dark pad1')
              .append(
                $('<p class="small">')
                .append('<i class="icon icon-question-sign pad0r">')
                .append(document.createTextNode('Did you mean '))
                .append($suggestion)
                .append(document.createTextNode('?'))
              );
    } else if (!is_valid) {
      return  $('<small class="mailgun-feedback error-message">')
              .append('<i class="icon icon-warning-sign pad0r">')
              .append('Email is invalid');
    }
  }
});

6. One final touch

Our feedback is getting displayed but it's shown abruptly and feels unnatural. Let's use motion to build meaning and communicate the spatial relationship between our suggestion and Username. We'll add .slideDown and have our suggestion transition from behind the input, making it clear how the two are associated and communicating our intention.

<div class='navbar fill-denim keyline-bottom col-sm-12 animate clearfix round'>
  ...
</div>

<div id='signup' class='animate modal'>
  ...
</div>

$(function() {
  ...

  function mailgun_suggestion(is_valid, alternate) {
    if (alternate) {
      $suggestion = $('<a href="#fakelink" class="animate" tabindex=-1>')
                    .text(alternate)
                    .click(function(e) {
                      suggestion = $(this).text();
                      $('.mailgun').val(suggestion);
                      $('.mailgun-feedback').remove();
                    });

      return  $('<div>')
              .addClass('mailgun-feedback fill-darken0 dark pad1 slideDown')
              .append(
                $('<p class="small">')
                .append('<i class="icon icon-question-sign pad0r">')
                .append(document.createTextNode('Did you mean '))
                .append($suggestion)
                .append(document.createTextNode('?'))
              );
    } else if (!is_valid) {
      return  $('<small class="mailgun-feedback error-message slideDown">')
              .append('<i class="icon icon-warning-sign pad0r">')
              .append('Email is invalid');
    }
  }
});
Made with in Norcross by the UX Team.