Home > Mobile >  How to create an animated email input when user clicks on it using CSS
How to create an animated email input when user clicks on it using CSS

Time:11-09

I want to create a cool animation that when the user clicks on the email input or the password the label of the input will go up and have a nice transition in the bottom border.

This is what I have:

This is what I have

And this is what I want to create:

This is what I want to create

My code:

.form {
  position: relative;
  display: flex;
  flex-direction: column;
  margin-bottom: 1rem;
}

.input {
  background: none;
  color: #c6c6c6;
  font-size: 1.8rem;
  padding: 1.6rem;
  display: block;
  border: none;
  border-bottom: 1px solid #c6c6c6;
  width: 100%;
}

.label {
  position: absolute;
  color: #c6c6c6;
  font-size: 1.6rem;
  left: 0.5rem;
  top: 1rem;
}
<div >
    <input  type="email" name="email" />
    <label  for="email">Email Address</label>
</div>
<div >
    <input  type="password" name="password" />
    <label  for="password">Password</label>
</div>

I've searched a lot but every code example I found was with SCCS, SASS and I don't understand it. So please help me with plain CSS. Any help would be greatly appreciated!

CodePudding user response:

I created an animated demo using HTML and CSS.

.main {
    width: 500px;
    margin: 50px 100px;
    ;
}

.form-group {
    position: relative;
    margin-bottom: 45px;
}

input {
    display: block;
    width: 300px;
    font-size: 14pt;
    padding: 10px;
    border: none;
    border-bottom: 1px solid #ccc;
}

input:focus {
    outline: none;
}

label {
    position: absolute;
    top: 10px;
    left: 5px;
    color: #999;
    font-size: 14pt;
    font-weight: normal;
    pointer-events: none;
    transition: all 0.2s ease;
}

input:focus ~ label,
input:valid ~ label {
    top: -20px;
    font-size: 10pt;
    color: #5264AE;
}

.bar {
    display: block;
    position: relative;
    width: 320px;
}

.bar:before,
.bar:after {
    content: "";
    height: 2px;
    width: 0;
    bottom: 1px;
    position: absolute;
    background: #5264AE;
    transition: all 0.2s ease;
}

.bar:before {
    left: 50%;
}

.bar:after {
    right: 50%;
}

input:focus ~ .bar:before,
input:focus ~ .bar:after {
    width: 50%;
}
<div >
    <div >
        <input type="text" name="email" required />
        <span ></span>
        <span ></span>
        <label for="email">Email</label>
    </div>
    
    <div >
        <input type="password" name="password" required />
        <span ></span>
        <span ></span>
        <label for="password">Password</label>
    </div>
</div>

CodePudding user response:

I attached your code modified to work as intended, you can change any value to customize as you want but here's an explanation of how it works:

Input element

I added a z-index so that the user can click where the label is positioned and click the input instead of the label itself, also added a transition to make the animation smooth.

input:focus refers when input is active (user click or selected by pressing tab key).

And here's where the magic happens and the explanations of complex selectors:

.input:focus~.label,
.input:not([value=""]):not(:focus):invalid~.label,
.input.has-content~.label {
    font-size: .7rem;
    top: -.4rem;
    color: blue;
}

.input:focus ~ .label selects all input's element siblings with the class .label when input is focus so that when user focus in the input the label'll be above.

.input:not([value=""]):not(:focus):invalid~.label this selector'll catch when user unfocus the input but it got content, so the label don't goes down and overlap with the username. (as the password type input doesn't have value attribute I attach you a Js snippet that do the same trick for password element, simply adding the class has-content to the element)

Hope it helps you!

document.querySelector('.password').oninput = (e) => {
  e.target.value.length > 0 ?
    e.target.classList.add('has-content') :
    e.target.classList.remove('has-content')
}
.form {
  position: relative;
  display: flex;
  flex-direction: column;
  margin: 1rem;
}

.input {
  height: 20px;
  background: none;
  color: #c6c6c6;
  font-size: 1rem;
  padding: .5rem .7rem;
  display: block;
  border: none;
  border-bottom: 2px solid #c6c6c6;
  width: 100%;
  z-index: 2;
  transition: all .3s ease;
}

.input:focus {
  outline: transparent;
  border-color: blue;
}

.input:focus~.label,
.input:not([value=""]):not(:focus):invalid~.label,
.input.has-content~.label {
  font-size: .7rem;
  top: -.4rem;
  color: blue;
}

.label {
  position: absolute;
  color: #c6c6c6;
  font-size: 1rem;
  left: 0.5rem;
  top: .6rem;
  transition: all .3s ease;
}
<div >
  <input  type="email" name="email" />
  <label  for="email">Email Address</label>
</div>
<div >
  <input  type="password" name="password" />
  <label  for="password">Password</label>
</div>

  • Related