Vue

by zoomieos

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<div class="container" id="app">
  {{phone}}
  <div class="form-group">
    <div class="input-group">
      <span class="input-group-addon"><span>+7</span></span>
         <input type="tel" 
         v-model="phone"
         name="phone"
         id="phone"
         placeholder="(555) 555-55-55"
         autocomplete="tel"
         maxlength="14"
         class="form-control"
         v-phone
         pattern="[(][0-9]{3}[)] [0-9]{3}-[0-9]{2}-[0-9]{2}" required />
         
</div>
</div>
</div>

CSS

body {
  background-color: #5c4084;
  text-align: center;
  padding: 50px;
}

.container {
  padding: 40px 80px 15px 80px;
  background-color: #fff;
  border-radius: 8px;
}

.heading h1 {
  background: -webkit-linear-gradient(#fff, #999);
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  text-align: center;
  margin: 0 0 5px 0;
  font-weight: 900;
  font-size: 4rem;
  color: #fff;
}
.heading h4 {
  color: #a990cc;
  text-align: center;
  margin: 0 0 35px 0;
  font-weight: 400;
  font-size: 24px;
}

.form-group {
  margin-bottom: 25px;
}

Vue

Vue.directive('phone', {
  bind(el) {  
    el.oninput = function(e) {
      if (!e.isTrusted) {
        return;
      }

      let x = this.value.replace(/\D/g, '').match(/(\d{0,3})(\d{0,3})(\d{0,4})/);
      this.value = !x[2] ? x[1] : '(' + x[1] + ') ' + x[2] + (x[3] ? '-' + x[3] : '');
      el.dispatchEvent(new Event('input'));
    }
  }
});

new Vue({
  el: "#app",
  data: {
    phone: ''
  }
})