Reputation: 73
I have a few input fields and I want their labels to scale down and slide at the top on focus. I have managed to achieve this with CSS and JavaScript but it only animates the first label on the page.
The code JS below uses "querySelector" to target the labels. I've also tried using "getElementsByClassName" and "querySelectorAll". What that does is animate all the labels on the page when I focus on just one input field.
I'd like to only animate the label attached to input. Any help with this would be greatly appreciated.
document.addEventListener("change", function(event) {
if (event.target && event.target.matches(".js_form-input")) {
event.preventDefault();
var inputField = event.target;
var inputLabels = document.querySelector(".label-span");
if (inputField.value) {
inputLabels.style.top = "-1.5rem";
} else {
inputLabels.style.top = "0rem";
}
}
});
.input {
width: 100%;
border: 0;
border-bottom: solid 1px grey;
padding-left: 1rem;
margin-bottom: 2rem;
color: $c_pop;
padding-bottom: 0.7rem;
}
.input-label {
position: relative;
}
.label-span {
position: absolute;
top: 0;
left: 1rem;
transition: all 0.2s;
}
.input-label {
font-size: 0.9rem;
}
.input:focus+.label-span {
top: -1.5rem;
left: 0.5rem;
font-size: 0.7rem;
}
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text">
<span class="label-span">First Name</span>
</label>
</div>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text">
<span class="label-span">Surname</span>
</label>
</div>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text">
<span class="label-span">Email</span>
</label>
</div>
I've also tried this JS method:
var inputField = event.target;
var inputLabels = document.querySelectorAll(".label-span");
[].slice.call(inputLabels).forEach(function(label){
if (inputField.value) {
label.style.top = "-1.5rem";
} else {
label.style.top = "0rem";
}
});
Upvotes: 3
Views: 3778
Reputation: 738
Another trick to achieve same result without Javascript.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
}
.input-container {
padding: 20px;
}
.input {
width: 100%;
border: 0;
border-bottom: solid 1px grey;
padding-left: 1rem;
margin-bottom: 2rem;
color: #000;
padding-bottom: 0.7rem;
}
.input-label {
position: relative;
}
.label-span {
position: absolute;
top: 0;
left: 1rem;
transition: all 0.2s;
}
.input-label {
font-size: 0.9rem;
}
.input:focus + .label-span,
.input:valid + .label-span {
top: -1.5rem;
left: 0.5rem;
font-size: 0.9rem;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text" required />
<span class="label-span">First Name</span>
</label>
</div>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text" required/>
<span class="label-span">Surname</span>
</label>
</div>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text" required/>
<span class="label-span">Email</span>
</label>
</div>
</body>
</html>
Upvotes: 0
Reputation: 738
I hope, This will solve your problem.
var myform = document.querySelectorAll(".input-label");
Array.from(myform).map(x => {
x.addEventListener('change', (e) => {
var el = e.target.parentNode.children[1];
if (e.target.value !== "") {
el.style.top = "-1.5rem";
} else {
el.style.top = "0rem";
}
});
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
}
.input-container {
padding: 20px;
}
.input {
width: 100%;
border: 0;
border-bottom: solid 1px grey;
padding-left: 1rem;
margin-bottom: 2rem;
color: #000;
padding-bottom: 0.7rem;
}
.input-label {
position: relative;
}
.label-span {
position: absolute;
top: 0;
left: 1rem;
transition: all 0.2s;
}
.input-label {
font-size: 0.9rem;
}
.input:focus+.label-span {
top: -1.5rem;
left: 0.5rem;
font-size: 0.7rem;
}
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text" />
<span class="label-span">First Name</span>
</label>
</div>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text" />
<span class="label-span">Surname</span>
</label>
</div>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text" />
<span class="label-span">Email</span>
</label>
</div>
Upvotes: 1
Reputation: 12919
Your CSS is sufficient to get the affect you are after, just remove the javascript. The only problem that I fixed is adding pointer-events: none;
to the .label-span
elements as they were blocking focus when clicking on them.
Edited to include a check on blur for whether the input is empty or not and maintain the label position if it is full.
const inputs = document.querySelectorAll('.js_form-input');
inputs.forEach(input => {
input.addEventListener('blur', (event) => {
if (event.target.value.length) {
event.target.classList.add("full");
} else {
event.target.classList.remove("full");
}
});
})
#container {
padding: 2rem 0;
}
.input {
width: 100%;
border: 0;
border-bottom: solid 1px grey;
padding-left: 1rem;
margin-bottom: 2rem;
color: $c_pop;
padding-bottom: 0.7rem;
}
.input-label {
position: relative;
}
.label-span {
position: absolute;
top: 0;
left: 1rem;
transition: all 0.2s;
pointer-events: none;
}
.input-label {
font-size: 0.9rem;
}
.input:focus+.label-span, .input.full+.label-span {
top: -1.5rem;
left: 0.5rem;
font-size: 0.7rem;
}
<div id="container">
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text">
<span class="label-span">First Name</span>
</label>
</div>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text">
<span class="label-span">Surname</span>
</label>
</div>
<div class="input-container">
<label class="input-label" for="#">
<input class="input js_form-input" type="text">
<span class="label-span">Email</span>
</label>
</div>
</div>
Upvotes: 2