rndm rndm - 2 months ago 10
CSS Question

Both events on focus, is JS needed?

I can't figure out how to get both of these effects (see code snippet below) on inputs using focus. I noticed that the focus works only for this element which is first in line. Can someone tell me why? And is it possible to get both effects on focus without using JavaScript?



form {
margin: 30px;
font-family: Arial;
}

.expand {
display: block;
position: relative;
margin-top: 20px;
width: 300px;
}

input[type="text"],
input[type="email"] {
border: none;
background-color: #eee;
padding: 10px;
width: 280px;
}

.border {
position: absolute;
display: block;
height: 3px;
width: 100%;
top: 100%;
background: red;
transform: scaleX(0);
transition: transform 0.5s;
transform-origin: 0 50%;
}

label {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
color: #999;
pointer-events: none;
transition: 0.2s;
margin-left: 10px;
}

input[type="text"]:focus + .border,
input[type="email"]:focus + .border {
transform: scaleX(1);
}

input[type="text"]:focus + label,
input[type="email"]:focus + label {
top: -10px;
font-size: 12px;
color: red;
font-weight: bold;
margin: 0;
}

<form action="">
<div class="expand">
<input type="text" name="" id="">
<!-- border before label -->
<div class="border"></div>
<label for="">Here works border effect</label>
</div>

<div class="expand">
<input type="email" name="" id="">
<!-- border after label -->
<label for="">Here works label effect</label>
<div class="border"></div>
</div>
</form>




Answer

If using the + selector only the direct sibling will be affected, instead use ~

form {
  margin: 30px;
  font-family: Arial;
}

.expand {
  display: block;
  position: relative;
  margin-top: 20px;
  width: 300px;
}

input[type="text"],
input[type="email"],
textarea {
  border: none;
  background-color: #eee;
  padding: 10px;
  width: 280px;
}

textarea {
  resize: none;
  margin-bottom: -1px;
}

.border {
  position: absolute;
  display: block;
  height: 3px;
  width: 100%;
  top: 100%;
  background: red;
  transform: scaleX(0);
  transition: transform 0.5s;
  transform-origin: 0 50%;
}

label {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  color: #999;
  pointer-events: none;
  transition: 0.2s;
  margin-left: 10px;
}

input[type="text"]:focus ~ .border,
input[type="email"]:focus ~ .border,
textarea:focus ~ .border {
  transform: scaleX(1);
}

input[type="text"]:focus ~ label,
input[type="email"]:focus ~ label,
textarea:focus ~ label {
  top: -10px;
  font-size: 12px;
  color: red;
  font-weight: bold;
  margin: 0;
}
<form action="">
  <div class="expand">
    <input type="text" name="" id="">
    <!-- border before label -->
    <div class="border"></div>
    <label for="">Here works border effect</label>
  </div>
  
  <div class="expand">
    <input type="email" name="" id="">
    <!-- border after label -->
    <label for="">Here works label effect</label>
    <div class="border"></div>
  </div>
</form>