Have you ever seen foldable login form ?
Tags: uiweekly, ux, css, webdev
Published: 2021-05-08 12:19:15

#Demo

{% codesandbox nostalgic-shirley-ir95j %}

>This is not responsive so I suggest you to view Demo in full new window. Click on the top right most button to view in full window.

#Video Tutorial

{% youtube PvW4IOWV4-E %}

> If you find this tutorial helpful please subscribe to my youtube channel. Thanks

#Let's Code this

To code this we will use HTML, CSS, and JS (to create animation). So first make files named `index.html`, `style.css`, `app.js` and write basic structure of HTML also add css, js file to `index.html`.

When you are done with this. Inside `<body>` tag make a `<div>` with class `.form-container` this will be our parent of both forms. Now inside of that `<div>` make another `<div>` with class `.bg-container` and this will contain 3 span which we use as a fake background for our Forms. Now inside of `.bg-container` make a `<span>` and give it class `.bg` plus give it `.top` class also. Now make two more copies of this span but change their `.top` class to `.middle` and `.bottom` respectively.

This should look like this 

```HTML
<div class="form-container">
     <div class="bg-container">
          <span class="bg top"></span>
          <span class="bg middle"></span>
          <span class="bg bottom"></span>
     </div>
</div>
```

Now style this.Add this CSS.
```CSS
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

*:focus{
    outline: none;
}

body{
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background-image: url(bg.jpg);
    background-size: cover;
    perspective: 1000px;
}

.form-container{
    width: 320px;
    height: 500px;
    position: relative;
    transition: 1s;
    display: flex;
    justify-content: center;
    align-items: center;
}

.bg-container{
    width: 100%;
    height: 100%;
    position: absolute;
    perspective: 1000px;
    transition: 1s;
    top: 0;
}

.bg{
    position: absolute;
    left: 0;
    background: #fff;
    width: 100%;
    height: calc(100% / 3);
    transition: 1s;
}

.bg.top{
    top: 0;
    transform-origin: bottom;
}

.bg.middle{
    top: calc(100% / 3);
}

.bg.bottom{
    bottom: 0;
    transform-origin: top;
}
```
This css is very easy to understand as we what we did is we set a background image to body and aligning our form in center with flex box. And we also style out span and gave them different top, bottom values. So that they look like background of our forms.

Now create form. Inside `.form-container` element make a `<form>` and give class `.form` (yeah! very unique class name).Now inside of form make an `h1` element and give class `.form-title` and type in `login form` and then add labels and inputs for our email and password. After that add `<a>` (anchor tag) with class `.btn` and a `<p>` tag with class `.link`. And copy this structure to make register form. Do some changes and your structure should look like this.

```html
 <form class="form active" id="login-form">
       <h1 class="form-title">login</h1>
       <label for="email">e-mail</label>
       <input type="email" id="email" autocomplete="off">
       <label for="pass">password</label>
       <input type="password" id="pass">

       <a href="#" type="submit" class="btn">log in</a>

       <p href="#" class="link">new here ? sign up now</p>

</form>

<form class="form" id="register-form">
      <h1 class="form-title">sign up</h1>
      <label for="name">name</label>
      <input type="text" id="name" autocomplete="off">
      <label for="email">e-mail</label>
      <input type="email" id="email" autocomplete="off">
      <label for="pass">password</label>
      <input type="password" id="pass">

      <a href="#" type="submit" class="btn">sign up</a>

      <p href="#" class="link">already have an account ?</p>

</form>
```

Now Style this also.

```css
.form{
    width: 90%;
    height: 100%;
    position: absolute;
    padding: 40px 20px;
    font-family: roboto, sans-serif;
    transition: 1s;
    opacity: 0;
    pointer-events: none;
}

.form.active{
    opacity: 1;
    pointer-events: all;
}

.form-title{
    font-size: 40px;
    text-transform: capitalize;
    text-align: center;
    margin-bottom: 50px;
    font-weight: 400;
}

label{
    display: block;
    text-transform: capitalize;
}

input{
    border: none;
    width: 100%;
    margin-bottom: 30px;
    height: 30px;
    background: none;
    border-bottom: 1px solid #000;
}

.btn{
    text-decoration: none;
    color: #fff;
    background: #000;
    text-align: center;
    width: 100px;
    display: block;
    margin: 20px auto;
    padding: 10px 0;
    text-transform: capitalize;
    border-radius: 50px;
}

.link{
    color: #000;
    text-transform: capitalize;
    display: block;
    margin: auto;
    width: fit-content;
    text-decoration: underline;
    cursor: pointer;
}

#register-form{
    padding: 30px 20px;
}

#register-form .form-title{
    margin-bottom: 30px;
}
```

By now we are done with our styling and we gave basic styling not that good. But it's time to create that effect. Open `app.js`
and write this.
```JS
const topSpan = document.querySelector('.bg.top');
const bottomSpan = document.querySelector('.bg.bottom');
const bgContainer = document.querySelector('.bg-container');

// select forms
const loginForm = document.querySelector('#login-form');
const registerForm = document.querySelector('#register-form');

// select links
const registerUrl = document.querySelector('#login-form .link');
const loginUrl = document.querySelector('#register-form .link');

let rotateVal = 1;

const toggleFormAnim = () => {
    topSpan.style.transform = `rotateX(-180deg)`;
    setTimeout(() => {
        bottomSpan.style.transform = `rotateX(180deg)`;
        setTimeout(() => {
            bgContainer.style.transform = `rotateY(${rotateVal * 180}deg)`;
            setTimeout(() => {
                bottomSpan.style.transform = `rotateX(0)`;
                setTimeout(() => {
                    topSpan.style.transform = `rotateX(0)`;
                    rotateVal++;
                }, 1000);
            }, 1000);
        }, 1000);
    }, 1000);
}

registerUrl.addEventListener('click', () => {
    loginForm.classList.remove('active');
    setTimeout(() => {
        toggleFormAnim();
        setTimeout(() => {
            registerForm.classList.add('active');
        }, 5000);
    }, 500);
})

loginUrl.addEventListener('click', () => {
    registerForm.classList.remove('active');
    setTimeout(() => {
        toggleFormAnim();
        setTimeout(() => {
            loginForm.classList.add('active');
        }, 5000);
    }, 500);
})
```

Now let's understand what we did in JS. First we select our two spans one `topSpan` and second `bottomSpan`. after that we select our two forms first `loginForm` and second `registerForm` after that we select our two links first `registerUrl` and second `loginUrl`.Then we create a variable called `rotateVal` this variable is very important to keep track of our form rotation.
Then we declared a function `toggleFormAnim` which is setting up our `topSpan` rotateX to `-180deg` and after 1s setting up `bottomSpan` rotateX to `180deg` and then wait for a second to execute other command. After that we added click event to those links where we are remove `.active` class from undesired form and adding `.active` class to the desire one. Plus we also calling out `toggleFormAnim` function.

So I hope you understand each and everything. If I made any mistake or you don't understand anything feel free to ask in comment.

Thanks for visiting : )