test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Animation</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css"
integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<form>
<div class="field-name">
<i class="fas fa-user"></i>
<input type="text" placeholder="Username" required />
<i class="fas fa-arrow-down"></i>
</div>
<div class="field-email innactive">
<i class="fas fa-arrow-down"></i>
<input type="email" placeholder="Email" required />
<i class="fas fa-arrow-down"></i>
</div>
<div class="field-password innactive">
<i class="fas fa-key"></i>
<input type="password" placeholder="Password" required />
<i class="fas fa-arrow-down"></i>
</div>
<div class="field-finish innactive">
<i class="fas fa-heart"></i>
<p>Thank you!</p>
<i class="fas fa-heart"></i>
</div>
</form>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
.css
*{
margin:0;
box-sizing: border-box;
padding: 0;
}
body{
height:100vh;
/* 열로 정렬된 속성들을 가로행으로 바꾸다 */
display: flex;
background-color: rgb(87,189,130);
transition:background 0.5s ease;
position:relative;
}
.field-name,
.field-email,
.field-password,
.field-finish
{
/* 조상을 기준으로 움직이다, absolute만 있다면 body를 기준으로 가장 왼족, 위에 가다 */
position:absolute;
top:50%;
left: 50%;
transform:translate(-50%,-50%);
background:white;
height:50px;
width:400px;
/* div 안에 fontawesome과 input tag가 있다, space-between 으로 양끝 정렬, align-item으로 가로정렬 */
display:flex;
justify-content:space-between;
align-items:center;
border-radius: 5px;
transition: all 0.5s ease;
}
.field-name i,
.field-email i,
.field-password i,
.field-finish i{
padding:10px;
cursor:pointer;
}
.field-name input,
.field-email input,
.field-password input{
background:none;
border:none;
/* 양쪽 fontawesome 들은 기본값을 가지고 flex 1 인 input 은 최대로 늘어나다 */
flex:1;
height:100%;
outline:none;
}
/* 위치변경 */
div.innactive{
opacity:0;
pointer-events:none;
transform:translate(-50%,50%);
}
div.active{
opacity:1;
pointer-events:all;
transform:translate(-50%,-50%);
}
@keyframes shake{
0%{
transform:translate(-50%,-50%) rotate(0deg);
}
50%{
transform:translate(-50%,-50%) rotate(10deg);
}
100%{
transform:translate(-50%,-50%) rotate(0deg);
}
}
.js
function animatedForm() {
const arrows = document.querySelectorAll(".fa-arrow-down"); //fontAwesome 태그를 담습니다
console.log(arrows); //모든 fa-arrow-down 태그들이 담깁니다
arrows.forEach(arrow => {
arrow.addEventListener('click', () => {//각 화살표가 클릭이 되면 실행됩니다.
const input = arrow.previousElementSibling;//바로 전 태그를 반환하다
const parent = arrow.parentElement;//arrow의 부모태그의 정보를 담습니다
const nextForm = parent.nextElementSibling;//현재 가장위에 있는 태그의 다음 형제 태그를 담습니다 -> div email 태그
console.log(input);
console.log(parent);
console.log(nextForm);
//Check for validation
if (input.type === "text" && validateUser(input)) {//input 속성중 type 이 text 이고 validateUser(input)을 던져 true 가 나오면 실행 input 에는 화살표 전 태그입돠
nextSlide(parent, nextForm); //nextSlide 함수 실행(parent,nextForm) parent arrow의 부모태그 -> div, nextForm 은 div username에서 div email 로 넘어갑니다
} else if (input.type === 'email' && validateEmail(input)) {
nextSlide(parent, nextForm);
} else if (input.type === 'password' && validateUser(input)) {
nextSlide(parent, nextForm);
} else {
parent.style.animation = "shake 0.5s ease";
}
parent.addEventListener("animationend", () => {
parent.style.animation = "";
})
});
});
}
function validateUser(user) { //input 태그가 왔습니다. type = text임돠
if (user.value.length < 6) {//input 태그의 값 길이가 6보다 작으면 실행
console.log("not enough characters");
error('rgb(189,87,87)'); //에러 색상
} else {
error('rgb(87,189,130)'); //통과 색상
return true;
}
}
function validateEmail(email) {
const validation = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (validation.test(email.value)) {
error('rgb(87,189,130)'); //통과 색상
return true;
} else {
error('rgb(189,87,87)'); //에러 색상
}
}
function nextSlide(parent, nextForm) {
parent.classList.add('innactive');//화살표를 누르면 username 태그에 innactive 가 붙어요 -> opacity :0 50% 아래로 내려갑니다
parent.classList.remove('active');//username에 active 태그는 없어지고,
nextForm.classList.add('active');//다음 태그인 email 에 innactive 있고, active가 붙습니다 태그에 innactive가 붙어서 50%내려가 있었는데, -50%가 active에 있어서 올라 옵니다
}
function error(color) {
document.body.style.backgroundColor = color;
}
animatedForm();