I'd suggest:
$("input").on({
// using an Object with event-names as the
// keys, linking to the functions
// to handle those events:
'focus': function() {
$(this).siblings().animate({
'top': '-20',
}, 70);
},
// handling the 'blur' event on the input:
'blur': function() {
// if the value of the <input> element, with
// leading and trailing white-space removed,
// is equal to the default value of the <input>
// (the value it held on page-load)
// we animate the 'top' CSS property back to 0:
if (this.value.trim() == this.defaultValue) {
$(this).siblings().animate({
'top': 0
}, 70);
}
}
});
$("input").on({
'focus': function() {
$(this).siblings().animate({
'top': '-20px',
}, 70);
},
'blur': function() {
if (this.value.trim() == this.defaultValue) {
$(this).siblings().animate({
'top': 0
}, 70);
}
}
});
div {
margin: 1em;
padding: 0;
border-radius: 1em;
position: relative;
}
label {
position: absolute;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="">
<fieldset>
<div>
<label for="input1">input 1</label>
<input type="text" id="input1">
</div>
<div>
<label for="input2">input 2</label>
<input type="text" id="input2">
</div>
<div>
<label for="input3">input 3</label>
<input type="text" id="input3">
</div>
<div>
<label for="input4">input 4</label>
<input type="text" id="input4">
</div>
<div>
<label for="input5">input 5</label>
<input type="text" id="input5">
</div>
</fieldset>
</form>
JS Fiddle demo.
The reason for checking if the current value is equal to the default-value (this.value.trim() === this.defaultValue) is to ensure that the <label> returns to its original position if the user entered no value, and we trim that string (removing leading and trailing white-space) as a check against users entering only white-space in that field.
With some restrictions this can be partially achieved using pure CSS; the caveats for this are:
- the
<input> elements must precede the <label> element in the mark-up,
- the
<input> elements must have both a required attribute and an attribute, such as minlength, maxlength or pattern in order to identify a 'valid' entry
With those restrictions in mind, though, the following is possible:
<form action="">
<fieldset>
<div>
<!-- the <input> here precedes the <label> in order that
the <label> can be styled based on the state of the
<input> element.
Also the 'minlength' attribute is present, to allow
CSS to determine whether the entered value is
valid or invalid, with the required attribute -->
<input type="text" id="input1" required minlength="5" />
<label for="input1">input 1</label>
</div>
<!-- repeated elements removed for brevity -->
</fieldset>
</form>
/* Here we style the <label> element's default state,
and the state when it follows an invalid <input>: */
label,
input:invalid + label {
position: absolute;
top: 1px;
left: 0.5em;
/* we set the transition for the element, to work on
the 'top' property, to take effect over 0.7 seconds
with a linear progression from start to end: */
transition: top 0.7s linear;
background-color: #fff;
}
/* Here we set the styles for the <label> when the preceding
<input> has focus, and when it has a valid entry, and is
positioned above its preceding <input>: */
input:focus + label,
input:valid + label {
top: -20px;
}
div {
margin: 1em;
padding: 0;
border-radius: 1em;
position: relative;
}
label,
input:invalid + label {
position: absolute;
top: 1px;
left: 0.5em;
transition: top 0.7s linear;
background-color: #fff;
box-sizing: content-box;
padding: 0;
}
input:focus + label,
input:valid + label {
top: -20px;
}
<form action="#">
<fieldset>
<div>
<input type="text" id="input1" required minlength="5" />
<label for="input1">input 1</label>
</div>
<div>
<input type="text" id="input2" required minlength="5" />
<label for="input2">input 2</label>
</div>
<div>
<input type="text" id="input3" required minlength="5" />
<label for="input3">input 3</label>
</div>
<div>
<input type="text" id="input4" required minlength="5" />
<label for="input4">input 4</label>
</div>
<div>
<input type="text" id="input5" required minlength="5" />
<label for="input5">input 5</label>
</div>
</fieldset>
</form>
JS Fiddle demo.
References: