How to apply style if an input field is empty just only using CSS?

96 views Asked by At

I have an input element and a sibling label element. Upon page load, the label overlaps the input element, serving as a placeholder. When the input is focused and contains a valid value, the label moves to the top of the input.

However, this behavior doesn't apply to email type inputs because the label should only leave when a valid email value is entered and the input loses focus.

Additionally, if an input is not required, the style will be applied even if it not focused.

I want to prevent that. Below is my current CSS for achieving this:

.label-animated {
    position: absolute;
    left: 1.6rem;
    top: 1rem;
    cursor: text;
    font-size: medium;
    transition: .5s ease;
    background-color: var(--bg-100) !important;
}

.input.input-form {
    width: 100%;
    font-size: medium;
    padding: 1rem;
    padding-bottom: .5rem;
    border: .0625rem solid var(--border-200);
    border-radius: 30rem; /*max border*/
    outline: none;
    background-color: transparent;
}

.input.input-form:focus~.label-animated,
.input.input-form:valid~.label-animated {
    top: -.72rem !important;
    left: 2rem;
    color: var(--accent-500);
}

Despite extensive searching for a solution, I have been unable to find any resources or guidance regarding this issue. It appears that there is currently no available information or solutions that address this specific problem. I can select an input that has no value input[value=""] but that has value, I don't really know. Can I fix this problem by just only using CSS?

2

There are 2 answers

0
imhvost On BEST ANSWER

You do not provide your html code, so fair enough if I use mine for the answer. But the point line is that, as already rejoiced, you should use pseudo-class :placeholder-shown.
And you also need to consider :autofill.
Here is a simple example:

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.fields {
  display:grid;
  max-width: 280px;
  gap: 24px;
  padding: 24px;
}

label {
  --padding: 12px;
  --height: 40px;
  --bg: white;
  display: inline-block;
  position: relative;
}

label:before {
  --left: calc(.5 * var(--padding));
  content: attr(aria-label);
  position: absolute;
  top: calc(.5 * var(--height) - .5lh);
  left: var(--left);
  max-width: calc(100% - 2 * var(--left));
  transition: transform .4s;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 calc(.5 * var(--padding));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  transform-origin: left;
  background-color: var(--bg);
}

input {
  display: block;
  padding: 0 var(--padding);
  height: var(--height);
  width: 100%;
  background: var(--bg);
}

input:autofill {
  box-shadow: inset 0 0 0 666vw var(--bg);
}

input::placeholder {
  color: transparent;
}

label:has(input:focus):before,
label:has(input:autofill):before,
label:has(:not(input:placeholder-shown)):before {
  transform: translateY(calc(-.5 * var(--height))) scale(.8);
}
<div class="fields">
  <label aria-label="Name">
    <input type="text" placeholder="Name" name="name">
  </label>
  <label aria-label="Email">
    <input type="email" placeholder="Email" name="email" required>
  </label>
  <label aria-label="Password">
    <input type="password" placeholder="Password" name="password" required>
  </label>
</div>

1
Pon Krishnan On

You can apply styles to an input field based on whether it is empty or not using CSS alone by utilizing the :placeholder-shown pseudo-class along with the adjacent sibling combinator (+). Here's an The input:not(:placeholder-shown) selector applies styles to the input field when it's not empty. You can modify these styles as needed. The input:placeholder-shown + .error-message selector targets the adjacent .error-message element when the input field is empty. You can use this to display an error message or apply any other styling as needed.