CSS change style if input has value or not

Viewed 842

I have a input element with a placeholder which should appear always

.wrapper {
  position: relative;
}

input {
  font-size: 14px;
  height: 40px;
}

.placeholder {
  position: absolute;
  font-size: 16px;
  pointer-events: none;
  left: 1px;
  top: 2px;
  transition: 0.1s ease all;
}

input:focus~.placeholder {
  top: -1px;
  font-size: 11px;
}

input[value=""]~.placeholder {
  top: -1px;
  font-size: 11px;
}
<div class="wrapper">
  <input type="text">
  <span class="placeholder">E-Mail</span>
</div>

And I want the pseudo placeholder to remain small if there is any text in the input field. There must be something wrong with the input[value=""] ~ .placeholder selector but I have no idea.

2 Answers

Use :placeholder-shown but you will need to have at least an empty placeholder

.wrapper{
  position: relative;
}

input {
  font-size: 14px;
  height: 40px;
}

.placeholder {
  position: absolute;
  font-size:16px;
  pointer-events: none;
  left: 1px;
  top: 2px;
  transition: 0.1s ease all;
}

input:focus ~ .placeholder{
  top: -1px;
  font-size: 11px;
}

input:not(:placeholder-shown) ~ .placeholder{
  top: -1px;
  font-size: 11px;
}
<div class="wrapper">
  <input type="text" placeholder=" ">
  <span class="placeholder">E-Mail</span>
</div>

You won't be able to catch this with the value attribute as it will only apply the value on page load. Either you use the placeholder-shown as Temani Afif answered, or if you want to support edge as well, you can use a :valid selector on a required field

.wrapper {
  position: relative;
}

input {
  font-size: 14px;
  height: 40px;
}

.placeholder {
  position: absolute;
  font-size: 16px;
  pointer-events: none;
  left: 1px;
  top: 2px;
  transition: 0.1s ease all;
}

input:focus~.placeholder {
  top: -1px;
  font-size: 11px;
}

input:valid~.placeholder {
  top: -1px;
  font-size: 11px;
}
<div class="wrapper">
  <input type="text" required>
  <span class="placeholder">E-Mail</span>
</div>

Related