<div class="container">
<form class="form" method="post" action="https://jsonplaceholder.typicode.com/posts">
<div class="cover">
<div class="circle"></div>
</div>
<div class="wrapper">
<input type="text" id="name" placeholder='Full Name' required minlength="2">
<label for="name">Your name</label>
<span class="tip name-tip"></span>
</div>
<div class="wrapper">
<input type="email" id="email" placeholder='example@domain.eg' required>
<label for="email">E-mail</label>
<span class="tip email-tip"></span>
</div>
<div class="wrapper">
<textarea name="message" id="message" cols="30" rows="8" placeholder='What is your question?' maxlength="2500"></textarea>
<label for="message">Message</label>
</div>
<button type="button" class="button">Submit</button>
</form>
</div>
*,
::before,
::after {
box-sizing: border-box;
}
.cover {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
inset: -25px;
background-color: rgba(255, 255, 255, 0.5);
opacity: 0;
z-index: -100;
}
.cover--shown {
opacity: 1;
z-index: 200;
}
.circle {
width: 80px;
height: 80px;
background-color: transparent;
border: 20px dashed #ED1E79;
transition: all .3s ease;
animation-name: loading;
animation-timing-function: linear;
animation-duration: 5s;
animation-iteration-count: infinite;
}
.container {
background-color: #121212;
width: 480px;
margin: 0 auto;
padding: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.form {
position: relative;
width: 100%;
display: flex;
flex-direction: column;
gap: 25px;
}
.form--loading {
pointer-events: none;
}
input,
textarea {
width: 100%;
padding: 10px 10px 25px;
border: none;
border-bottom: 1px solid #fafafa;
background-color: transparent;
color: #fafafa;
font-size: 16px;
font-weight: 400;
}
textarea {
resize: none;
}
.wrapper {
position: relative;
}
label {
position: absolute;
top: 10px;
left: 10px;
font-family: sans-serif;
font-weight: 500;
color: #fafafa;
opacity: 0.6;
transition: all 0.5s ease;
}
.tip {
visibility: hidden;
display: inline-block;
width: 70%;
padding: 10px;
position: absolute;
z-index: 10;
transform: translateY(60px);
right: 0;
font-family: sans-serif;
font-size: 12px;
letter-spacing: .1em;
word-spacing: .5em;
color: #fafafa;
border: 2px solid #ED1E79;
background-color: #121212;
}
.tip--show {
visibility: visible;
}
.tip::before {
content: "";
display: block;
position: absolute;
top: -6.5px;
right: 6.5px;
width: 10px;
height: 10px;
background-color: #121212;
border-top: 2px solid #ED1E79;
border-right: 2px solid #ED1E79;
transform: rotate(-45deg);
}
.button {
padding: 15px 47px;
align-self: start;
font-family: sans-serif;
text-transform: uppercase;
font-weight: 500;
color: #fafafa;
background-color: #ED1E79;
border: none;
}
.button--shake {
animation: shake 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55) both;
}
input::placeholder,
textarea::placeholder {
opacity: 0;
transition: opacity .3s ease;
}
.valid {
border-bottom-color: green;
}
input:autofill,
input:autofill-selected,
input:autofill,
input:autofill:hover,
input:autofill:focus,
input:autofill:active
textarea:autofill,
textarea:autofill,
textarea:autofill:hover,
teaxtarea:autofill:focus,
texctarea:autofill:active {
background-color: transparent !important;
color: #fafafa !important;
}
input:focus ~ label, input:active ~ label,
input:not(:placeholder-shown) ~ label,
textarea:focus ~ label, textarea:active ~ label,
textarea:not(:placeholder-shown) ~ label{
font-size: 10px;
top: -15px;
left: 0;
}
input:focus::placeholder, input:active::placeholder,
textarea:focus::placeholder, textarea:active::placeholder {
opacity: 1;
}
input:focus, input:active,
textarea:focus, textarea:active {
outline: none;
border-bottom-color: #ED1E79;
}
input:autofill,
input:autofill:hover,
input:autofill:focus {
text-fill-color: #fafafa;
box-shadow: 0 0 0px 40rem #121212 inset;
}
input:required:focus {
}
@keyframes loading {
to {
transform: rotate(720deg);
}
}
@keyframes shake {
10%, 90% {
transform: translateX(-0.5px);
}
20%, 80% {
transform: translateX(1px);
}
30%, 50%, 70% {
transform: translateX(-2px);
}
40%, 60% {
transform: translateX(2px);
}
}
}
const userForm = document.querySelector('.form');
const nameField = document.getElementById('name');
const emailField = document.querySelector('#email');
const nameTip = document.querySelector('.name-tip');
const emailTip = document.querySelector('.email-tip');
const button = document.querySelector('.button');
const cover = document.querySelector('.cover');
// no sending yet, all af the behavior was simulated
const hideCover = () => {
button.textContent = 'submit';
cover.classList.remove('cover--shown');
userForm.classList.remove('form--loading');
userForm.reset();
nameField.classList.remove('valid');
emailField.classList.remove('valid');
};
const showCover = () => {
button.textContent = 'loading...';
cover.classList.add('cover--shown');
userForm.classList.add('form--loading');
setTimeout(function() {
hideCover();
}, 1200);
};
button.addEventListener('click', (e) => {
if (nameField.value !== '' && emailField.value !== '') {
if (nameField.classList.contains('valid') && emailField.classList.contains('valid')) {
showCover();
}
} else {
button.classList.add('button--shake');
setTimeout(function() {
button.classList.remove('button--shake');
}, 600);
}
});
// name validation
nameField.addEventListener("input", () => {
const re = /(?!\d)\w{2,40}/gi;
if (!re.test(nameField.value)) {
nameTip.textContent = 'Please check if your name is written with letters, and there are more than two of them';
nameTip.classList.add('tip--show');
} else {
nameTip.classList.remove('tip--show');
nameField.classList.add('valid');
}
})
// e-mail validation
emailField.addEventListener("input", () => {
const re = /^[A-Za-z0-9\_\.]{1,}\@[A-Za-z0-9]{2,}\.[A-Za-z]{2,}$/;
if (!re.test(emailField.value)) {
emailTip.textContent = 'Please check if your email is written correctly';
emailTip.classList.add('tip--show');
} else {
emailTip.classList.remove('tip--show');
emailField.classList.add('valid');
}
})
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.