The challenge was clear: ensure that each form field’s label is only visible when the user has entered information into the field, otherwise, display a placeholder.

This approach helps maintain a clean and minimalist form design, especially useful for forms with multiple fields.
The solution I found leverages the CSS :placeholder-shown pseudo-class combined with the adjacent sibling combinator (+).
This method requires no JavaScript, offering a purely CSS-based solution that’s both simple and effective.

Nehmen wir an, unser Formular-HTML sieht so aus

<form>
  <div>
      <label for="name">Name</label>
      <input type="text" id="name" name="name" placeholder="Name">
  </div>
  <div>
      <label for="email">E-mail</label>
      <input type="email" id="email" name="email" placeholder="E-mail">
  </div>
</form>

Lassen Sie uns Beschriftungen ausblenden. Das Formular sieht jetzt also so aus, es wird auf keinen Fall eine Beschriftung angezeigt.

<style>
  ...
  form label {
    display: none;
  }
  ...
</style>

Lassen Sie uns das beheben, indem wir Ihrem CSS etwas Magie hinzufügen. Jetzt wird die Beschriftung angezeigt, sobald der Eingabeplatzhalter verschwindet

<style>
  ...
  form label {
    display: none;
  }
  form div label:has(+input:not(:placeholder-shown))  {
    display: block;
  }
  ...
</style>

Lassen Sie uns aufschlüsseln, was div label:has(+input:not(:placeholder-shown)) { display: block; } bedeutetform:

form div label: Dieser Teil des Selektors zielt auf Beschriftungselemente ab, die Nachkommen eines Div sind, das selbst ein Nachkomme eines Formulars ist. Auf diese Weise können wir angeben, dass wir uns auf Beschriftungen in Formularen konzentrieren, die dieser speziellen Verschachtelungsstruktur folgen.

:has(+input:not(:placeholder-shown)): Hier geschieht die wahre Magie, die aus mehreren Teilen besteht:

  • :has(…): Die Pseudoklasse :has wird verwendet, um ein Element auszuwählen, wenn es der Bedingung in den Klammern entspricht. In diesem Fall bezieht sich die Bedingung auf ein gleichgeordnetes Eingabeelement.
  • +: Der benachbarte Geschwisterkombinator. Dies zielt auf ein Element ab, dem das vorherige Element unmittelbar vorangeht. label:has(+input) würde also nach einer Beschriftung suchen, auf die unmittelbar eine Eingabe folgt.
  • input:not(:placeholder-shown): Dadurch wird ein Eingabeelement ausgewählt, dessen Platzhalter nicht angezeigt wird. Die Pseudoklasse :not() egiert die darin enthaltene Bedingung und :placeholder-shown zielt auf Eingabefelder ab, die Platzhaltertext anzeigen. Gemeinsam wählen sie Eingabefelder aus, in die Inhalte eingegeben wurden oder mit denen so interagiert wurde, dass der Platzhalter nicht mehr angezeigt wird.
  • { display: block; }: Dieser CSS-Deklarationsblock wendet den display: block; Stil für die Beschriftungen, die den vom Selektor definierten Kriterien entsprechen. Im Wesentlichen bedeutet dies, dass, wenn das Etikett über ein gleichgeordnetes Eingabeelement verfügt, bei dem der Platzhalter nicht angezeigt wird (was anzeigt, dass der Benutzer mit dem Ausfüllen des Formulars begonnen hat), das Etikett als Element auf Blockebene angezeigt wird.

Ein animiertes Etikett erscheint nicht einfach; Es fällt ins Auge und lenkt die Aufmerksamkeit des Benutzers auf dynamischere und interaktivere Weise.

Lass uns das tun:

<style>
...
  form label {
    display: block;
    opacity: 0;
  }
  form div label:has(+input:not(:placeholder-shown))  {
    -webkit-animation: fadeInFromNone 0.5s ease-out forwards;
    -moz-animation: fadeInFromNone 0.5s ease-out forwards;
    -o-animation: fadeInFromNone 0.5s ease-out forwards;
    animation: fadeInFromNone 0.5s ease-out forwards;
  }

  @-webkit-keyframes fadeInFromNone {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @-moz-keyframes fadeInFromNone {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @-o-keyframes fadeInFromNone {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @keyframes fadeInFromNone {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }   
...
</style>