├── README.md ├── assets ├── css │ └── styles.css ├── js │ └── main.js └── scss │ ├── base │ └── _base.scss │ ├── components │ └── _input.scss │ ├── config │ └── _variables.scss │ └── styles.scss ├── index.html └── preview.png /README.md: -------------------------------------------------------------------------------- 1 | # Email Validation In JavaScript 2 | ## [Watch it on youtube](https://youtu.be/_bcll8SR0Bc) 3 | ### Email Validation In JavaScript 4 | 5 | - Email Validation in HTML CSS & JavaScript 6 | - It contains four color states (default, focused, completed & error). 7 | - Developed first with the Mobile First methodology, then for desktop. 8 | - Compatible with all mobile devices and with a beautiful and pleasant user interface. 9 | 10 | 💙 Join the channel to see more videos like this. [Bedimcode](https://www.youtube.com/@Bedimcode) 11 | 12 |  13 | -------------------------------------------------------------------------------- /assets/css/styles.css: -------------------------------------------------------------------------------- 1 | /*=============== GOOGLE FONTS ===============*/ 2 | @import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&display=swap"); 3 | 4 | /*=============== VARIABLES CSS ===============*/ 5 | :root { 6 | /*========== Colors ==========*/ 7 | /*Color mode HSL(hue, saturation, lightness)*/ 8 | --default-color: hsl(200, 4%, 60%); 9 | --active-color: hsl(200, 70%, 56%); 10 | --error-color: hsl(353, 64%, 53%); 11 | --border-color: hsl(200, 4%, 64%); 12 | --text-color: hsl(200, 4%, 24%); 13 | --body-color: hsl(0, 0%, 100%); 14 | 15 | /*========== Font and typography ==========*/ 16 | /*.5rem = 8px | 1rem = 16px ...*/ 17 | --body-font: "Montserrat", sans-serif; 18 | --normal-font-size: 1rem; 19 | --small-font-size: .813rem; 20 | --smaller-font-size: .75rem; 21 | } 22 | 23 | /*=============== BASE ===============*/ 24 | * { 25 | box-sizing: border-box; 26 | padding: 0; 27 | margin: 0; 28 | } 29 | 30 | body, 31 | input { 32 | font-size: var(--normal-font-size); 33 | font-family: var(--body-font); 34 | color: var(--text-color); 35 | } 36 | 37 | body { 38 | background-color: var(--body-color); 39 | } 40 | 41 | /*=============== INPUT FIELD ===============*/ 42 | .container { 43 | height: 100vh; 44 | margin-inline: 1.5rem; 45 | display: grid; 46 | place-items: center; 47 | } 48 | 49 | .form { 50 | width: 100%; 51 | max-width: 340px; 52 | } 53 | 54 | .form__field { 55 | position: relative; 56 | } 57 | 58 | .form__input { 59 | width: 100%; 60 | border: 3px solid var(--default-color); 61 | padding: 1.4rem 1.4rem 1.4rem 4.5rem; 62 | border-radius: 4rem; 63 | outline: none; 64 | font-weight: 500; 65 | transition: border-color .4s, box-shadow .4s; 66 | } 67 | 68 | .form__input::placeholder { 69 | color: var(--text-color); 70 | } 71 | 72 | .form__label { 73 | position: absolute; 74 | left: 1.5rem; 75 | top: -.65rem; 76 | background-color: var(--body-color); 77 | padding: 2px; 78 | font-size: var(--small-font-size); 79 | font-weight: 500; 80 | } 81 | 82 | .form__icon { 83 | height: max-content; 84 | font-size: 1.5rem; 85 | position: absolute; 86 | left: 1.5rem; 87 | top: 0; 88 | bottom: 0; 89 | margin-block: auto; 90 | } 91 | 92 | .form__field::after { 93 | content: ""; 94 | position: absolute; 95 | height: 28px; 96 | border: 1px solid var(--border-color); 97 | left: 3.75rem; 98 | top: 0; 99 | bottom: 0; 100 | margin-block: auto; 101 | } 102 | 103 | .form__error { 104 | position: absolute; 105 | left: 1.5rem; 106 | bottom: -1.5rem; 107 | display: flex; 108 | align-items: center; 109 | column-gap: .25rem; 110 | color: var(--error-color); 111 | opacity: 0; 112 | pointer-events: none; 113 | transition: opacity .4s; 114 | } 115 | 116 | .form__error i { 117 | font-size: 1rem; 118 | } 119 | 120 | .form__error span { 121 | font-size: var(--smaller-font-size); 122 | font-weight: 500; 123 | } 124 | 125 | /* Active focus & valid field color */ 126 | .form__input:focus, 127 | .valid .form__input { 128 | border-color: var(--active-color); 129 | box-shadow: 0 8px 24px hsla(200, 70%, 56%, .3); 130 | } 131 | 132 | /* Invalid field color */ 133 | .invalid .form__input { 134 | border-color: var(--error-color); 135 | box-shadow: 0 8px 24px hsla(353, 64%, 53%, .3); 136 | } 137 | 138 | .invalid .form__error { 139 | opacity: 1; 140 | } 141 | -------------------------------------------------------------------------------- /assets/js/main.js: -------------------------------------------------------------------------------- 1 | /*=============== EMAIL VALIDATION ===============*/ 2 | const form = document.getElementById('form'), 3 | email = document.getElementById('email'), 4 | pattern = /^[^ ]+@[^ ]+\.[a-z]{2,3}$/ 5 | 6 | email.addEventListener('input', () => { 7 | 8 | // Evaluates if it matches the pattern values 9 | if (email.value.match(pattern)) { 10 | form.classList.add('valid') 11 | form.classList.remove('invalid') 12 | } else { 13 | form.classList.add('invalid') 14 | form.classList.remove('valid') 15 | } 16 | 17 | // If the input field is empty, delete classes 18 | if (email.value == '') { 19 | form.classList.remove('invalid') 20 | form.classList.remove('valid') 21 | } 22 | }) 23 | -------------------------------------------------------------------------------- /assets/scss/base/_base.scss: -------------------------------------------------------------------------------- 1 | /*=============== BASE ===============*/ 2 | *{ 3 | box-sizing: border-box; 4 | padding: 0; 5 | margin: 0; 6 | } 7 | 8 | body, 9 | input{ 10 | font-size: var(--normal-font-size); 11 | font-family: var(--body-font); 12 | color: var(--text-color); 13 | } 14 | 15 | body{ 16 | background-color: var(--body-color); 17 | } 18 | -------------------------------------------------------------------------------- /assets/scss/components/_input.scss: -------------------------------------------------------------------------------- 1 | /*=============== INPUT FIELD ===============*/ 2 | .container{ 3 | height: 100vh; 4 | margin-inline: 1.5rem; 5 | display: grid; 6 | place-items: center; 7 | } 8 | 9 | .form{ 10 | width: 100%; 11 | max-width: 340px; 12 | 13 | &__field{ 14 | position: relative; 15 | } 16 | &__input{ 17 | width: 100%; 18 | border: 3px solid var(--default-color); 19 | padding: 1.40rem 1.40rem 1.40rem 4.5rem; 20 | border-radius: 4rem; 21 | outline: none; 22 | font-weight: 500; 23 | transition: border-color .4s, box-shadow .4s; 24 | 25 | &::placeholder{ 26 | color: var(--text-color); 27 | } 28 | } 29 | &__label{ 30 | position: absolute; 31 | left: 1.5rem; 32 | top: -.65rem; 33 | background-color: var(--body-color); 34 | padding: 2px; 35 | font-size: var(--small-font-size); 36 | font-weight: 500; 37 | } 38 | &__icon{ 39 | height: max-content; 40 | font-size: 1.5rem; 41 | position: absolute; 42 | left: 1.5rem; 43 | top: 0; 44 | bottom: 0; 45 | margin-block: auto; 46 | } 47 | &__field::after{ 48 | content: ''; 49 | position: absolute; 50 | height: 28px; 51 | border: 1px solid var(--border-color); 52 | left: 3.75rem; 53 | top: 0; 54 | bottom: 0; 55 | margin-block: auto; 56 | } 57 | &__error{ 58 | position: absolute; 59 | left: 1.5rem; 60 | bottom: -1.5rem; 61 | display: flex; 62 | align-items: center; 63 | column-gap: .25rem; 64 | color: var(--error-color); 65 | opacity: 0; 66 | pointer-events: none; 67 | transition: opacity .4s; 68 | 69 | & i{ 70 | font-size: 1rem; 71 | } 72 | & span{ 73 | font-size: var(--smaller-font-size); 74 | font-weight: 500; 75 | } 76 | } 77 | } 78 | 79 | // Active focus & valid field color 80 | .form__input:focus, 81 | .valid .form__input{ 82 | border-color: var(--active-color); 83 | box-shadow: 0 8px 24px hsla(200, 70%, 56%, .3); 84 | } 85 | 86 | // Invalid field color 87 | .invalid .form__input{ 88 | border-color: var(--error-color); 89 | box-shadow: 0 8px 24px hsla(353, 64%, 53%, .3); 90 | } 91 | 92 | .invalid .form__error{ 93 | opacity: 1; 94 | } -------------------------------------------------------------------------------- /assets/scss/config/_variables.scss: -------------------------------------------------------------------------------- 1 | /*=============== GOOGLE FONTS ===============*/ 2 | @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&display=swap'); 3 | 4 | /*=============== VARIABLES CSS ===============*/ 5 | :root{ 6 | /*========== Colors ==========*/ 7 | /*Color mode HSL(hue, saturation, lightness)*/ 8 | --default-color: hsl(200, 4%, 60%); 9 | --active-color: hsl(200, 70%, 56%); 10 | --error-color: hsl(353, 64%, 53%); 11 | --border-color: hsl(200, 4%, 64%); 12 | --text-color: hsl(200, 4%, 24%); 13 | --body-color: hsl(0, 0%, 100%); 14 | 15 | /*========== Font and typography ==========*/ 16 | /*.5rem = 8px | 1rem = 16px ...*/ 17 | --body-font: 'Montserrat', sans-serif; 18 | --normal-font-size: 1rem; 19 | --small-font-size: .813rem; 20 | --smaller-font-size: .75rem; 21 | } 22 | -------------------------------------------------------------------------------- /assets/scss/styles.scss: -------------------------------------------------------------------------------- 1 | @import 'config/variables'; 2 | @import 'base/base'; 3 | @import 'components/input'; 4 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |