: not (: vide) Le sélecteur CSS ne fonctionne pas?

93

Je passe un sacré moment avec ce sélecteur CSS particulier qui ne veut pas fonctionner lorsque j'y ajoute :not(:empty). Cela semble fonctionner correctement avec n'importe quelle combinaison des autres sélecteurs:

input:not(:empty):not(:focus):invalid { border-color: #A22; box-shadow: none }

Si je retire la :not(:empty)pièce, cela fonctionne très bien. Même si je change le sélecteur, input:not(:empty)je ne sélectionnerai toujours pas les champs de saisie contenant du texte. Est-ce cassé ou ne suis-je tout simplement pas autorisé à l'utiliser :emptydans un :not()sélecteur?

La seule autre chose à laquelle je peux penser est que les navigateurs disent toujours que l'élément est vide parce qu'il n'a pas d'enfants, juste une "valeur" par exemple. Est-ce que le:empty sélecteur n'a- pas de fonctionnalité distincte pour un élément d'entrée par rapport à un élément normal? Cela ne semble pas probable car utiliser :emptysur un champ et taper quelque chose dedans fera disparaître les effets alternatifs (car il n'est plus vide).

Testé dans Firefox 8 et Chrome.

animuson
la source
Pouvez-vous publier le code correspondant?
Virendra du
2
Puis - je vous citer une partie de la référence de l' API pour le :emptysélecteur : « D'autres éléments, d'autre part, sont vides (c. -à- n'a pas d' enfant) par définition: <input>, <img>, <br>et <hr>, par exemple. »
David dit de réintégrer Monica
@Virendra: C'est le code pertinent, mais j'y ai ajouté les règles CSS réelles. Si je supprime le :not(:empty), la bordure rouge fonctionne comme prévu pour une entrée qui n'est pas au point mais qui n'est pas valide.
animuson

Réponses:

151

Étant un élément void , un <input>élément est considéré comme vide par la définition HTML de "vide", puisque le modèle de contenu de tous les éléments void est toujours vide . Ainsi, ils correspondront toujours à la :emptypseudo-classe, qu'ils aient ou non une valeur. C'est également pourquoi leur valeur est représentée par un attribut dans la balise de début, plutôt que par un contenu textuel dans les balises de début et de fin.

Aussi, à partir de la spécification des sélecteurs :

La :emptypseudo-classe représente un élément qui n'a aucun enfant. En termes d'arborescence de documents, seuls les nœuds d'élément et les nœuds de contenu (tels que les nœuds de texte DOM, les nœuds CDATA et les références d'entité) dont les données ont une longueur non nulle doivent être considérés comme affectant la vacuité;

Par conséquent, input:not(:empty)ne correspondra jamais à rien dans un document HTML approprié. (Cela fonctionnerait toujours dans un document XML hypothétique qui définit un <input>élément qui peut accepter du texte ou des éléments enfants.)

Je ne pense pas que vous puissiez styliser les <input>champs vides de manière dynamique en utilisant uniquement du CSS (c'est-à-dire des règles qui s'appliquent chaque fois qu'un champ est vide, et pas une fois le texte entré). Vous pouvez sélectionner des champs initialement vides s'ils ont un valueattribut vide ( input[value=""]) ou s'ils manquent complètement de l'attribut ( input:not([value])), mais c'est à peu près tout.

BoltClock
la source
Hmm, je ne me souviens pas de ce que j'ai fait pour que les effets disparaissent avec juste le input:empty. Peut-être ai-je tapé quelque chose de mal, qui sait.
animuson
9
Concernant le dernier paragraphe de la réponse, les inputéléments peuvent être stylisés dynamiquement (dans des navigateurs suffisamment modernes) si vous pouvez utiliser l' requiredattribut dans le balisage HTML. Ensuite, vous pouvez utiliser :validet :invaliddans CSS pour tester la valeur non vide ou vide du contrôle. Voir stackoverflow.com/questions/16952526/…
Jukka K. Korpela
1
@ JukkaK.Korpela sauf si vous utilisez également l'attribut pattern.
WORMSS
2
input: not ([value = '']) sélectionnera une entrée avec une valeur;)
Chris Love
@Chris Love: entrées avec une valeur initiale (au chargement de la page).
BoltClock
43

C'est possible avec javascript en ligne onkeyup="this.setAttribute('value', this.value);"etinput:not([value=""]):not(:focus):invalid

Démo: http://jsfiddle.net/mhsyfvv9/

input:not([value=""]):not(:focus):invalid{
  background-color: tomato;
}
<input 
  type="email" 
  value="" 
  placeholder="valid mail" 
  onchange="this.setAttribute('value', this.value);" />

Mo.
la source
L' onchangeévénement n'est-il pas meilleur dans ce cas? Puisque vous pouvez également modifier les valeurs d'entrée avec Right click > Cut(par exemple). Testé: fonctionne très bien.
Derk Jan Speelman
40

Vous pouvez essayer d'utiliser: placeholder-shown ...

input {
  padding: 10px 15px;
  font-size: 16px;
  border-radius: 5px;
  border: 2px solid lightblue;
  outline: 0;
  font-weight:bold;
  transition: border-color 200ms;
  font-family: sans-serif;
}

.validation {
  opacity: 0;
  font-size: 12px;
  font-family: sans-serif;
  color: crimson;
  transition: opacity;
}

input:required:valid {
  border-color: forestgreen;
}

input:required:invalid:not(:placeholder-shown) {
  border-color: crimson;
}

input:required:invalid:not(:placeholder-shown) + .validation {
  opacity: 1;
}

  
<input type="email" placeholder="e-mail" required>
<div class="validation">Not valid</span>

pas de grand support cependant ... caniuse

Gijs Erenstein
la source
2
assez bon support cependant ... caniuse
Reggie Pinkham
Bon vieux Internet Explorer (Y)
rorymorris89
@ rorymorris89 même la dernière version d'EDGE ne prend pas en charge :-(
Lun
12

.floating-label-input {
  position: relative;
  height:60px;
}
.floating-label-input input {
  width: 100%;
  height: 100%;
  position: relative;
  background: transparent;
  border: 0 none;
  outline: none;
  vertical-align: middle;
  font-size: 20px;
  font-weight: bold;
  padding-top: 10px;
}
.floating-label-input label {
  position: absolute;
  top: calc(50% - 5px);
  font-size: 22px;
  left: 0;
  color: #000;
  transition: all 0.3s;
}
.floating-label-input input:focus ~ label, .floating-label-input input:focus ~ label, .floating-label-input input:valid ~ label {
  top: 0;
  font-size: 15px;
  color: #33bb55;
}
.floating-label-input .line {
  position: absolute;
  height: 1px;
  width: 100%;
  bottom: 0;
  background: #000;
  left: 0;
}
.floating-label-input .line:after {
  content: "";
  display: block;
  width: 0;
  background: #33bb55;
  height: 1px;
  transition: all 0.5s;
}
.floating-label-input input:focus ~ .line:after, .floating-label-input input:focus ~ .line:after, .floating-label-input input:valid ~ .line:after {
  width: 100%;
}
<div class="floating-label-input">
      <input type="text" id="id" required/>
      <label for="id" >User ID</label>
      <span class="line"></span>
</div>

Amit
la source
7

Vous pouvez aborder cela différemment; omettez l'utilisation de la :emptypseudo-classe et utilisez les inputévénements pour détecter une valeur significative dans le <input>champ et le styliser en conséquence:

var inputs = document.getElementsByTagName('input');

for (var i = 0; i < inputs.length; i++) {
  var input = inputs[i];
  input.addEventListener('input', function() {
    var bg = this.value ? 'green' : 'red';
    this.style.backgroundColor = bg;
  });
}
body {
  padding: 40px;
}
#inputList li {
  list-style-type: none;
  padding-bottom: 1.5em;
}
#inputList li input,
#inputList li label {
  float: left;
  width: 10em;
}
#inputList li input {
  color: white;
  background-color: red;
}
#inputList li label {
  text-align: right;
  padding-right: 1em;
}
<ul id="inputList">
  <li>
    <label for="username">Enter User Name:</label>
    <input type="text" id="username" />
  </li>
  <li>
    <label for="password">Enter Password:</label>
    <input type="password" id="password" />
  </li>
</ul>

en relation


Avertissement: notez que les inputévénements sont actuellement expérimentaux , et probablement pas largement pris en charge.

Eliran Malka
la source
3

Puisque l'espace réservé disparaît en entrée, vous pouvez utiliser:

input:placeholder-shown{
    //rules for not empty input
}
Luca C.
la source
2

solution pure css

input::-webkit-input-placeholder {
    opacity: 1;
    -webkit-transition: opacity 0s;
    transition: opacity 0s;
    text-align: right;
}
/* Chrome <=56, Safari < 10 */
input:-moz-placeholder {
    opacity: 1;
    -moz-transition: opacity 0s;
    transition: opacity 0s;
    text-align: right;
}
/* FF 4-18 */
input::-moz-placeholder {
    opacity: 1;
    -moz-transition: opacity 0s;
    transition: opacity 0s;
    text-align: right;
}
/* FF 19-51 */
input:-ms-input-placeholder {
    opacity: 1;
    -ms-transition: opacity 0s;
    transition: opacity 0s;
    text-align: right;
}
/* IE 10+ */
input::placeholder {
    opacity: 1;
    transition: opacity 0s;
    text-align: right;
}
/* Modern Browsers */

*:focus::-webkit-input-placeholder {
   opacity: 0;
   text-align: left;
}
/* Chrome <=56, Safari < 10 */
*:focus:-moz-placeholder {
    opacity: 0;
    text-align: left;
}
/* FF 4-18 */
*:focus::-moz-placeholder {
    opacity: 0;
    text-align: left;
}
/* FF 19-50 */
*:focus:-ms-input-placeholder {
    opacity: 0;
    text-align: left;
}
/* IE 10+ */
*:focus::placeholder {
    opacity: 0;
    text-align: left;
}
/* Modern Browsers */

input:focus {
    text-align: left;
}
étoile
la source
0

Une autre solution CSS pure

.form{
  position:relative;
  display:inline-block;
}
.form input{
  margin-top:10px;
}
.form label{
    position:absolute;
    left:0;
    top:0;
    opacity:0;
    transition:all 1s ease;
}
input:not(:placeholder-shown) + label{
    top:-10px;
    opacity:1;
}
<div class="form">
    <input type="text" id="inputFName" placeholder="Firstname">
    <label class="label" for="inputFName">Firstname</label>
</div>
<div class="form">
    <input type="text" id="inputLName" placeholder="Lastname">
    <label class="label" for="inputLName">Lastname</label>
</div>

vacsati
la source
-1

Cela devrait fonctionner dans les navigateurs modernes:

input[value]:not([value=""])

Il sélectionne toutes les entrées avec l'attribut value, puis sélectionne les entrées avec une valeur non vide parmi elles.

Andrew Kondratev
la source
10
Ce ne serait cependant pas dynamique. Il ne sélectionnerait que les éléments d'entrée dont l' attribut est défini comme value="". Taper / supprimer quelque chose dans la case n'entraînerait aucun changement.
animuson
-1
input:not([value=""])

Cela fonctionne car nous sélectionnons l'entrée uniquement lorsqu'il n'y a pas de chaîne vide.

Anton
la source
-1
input:not(:invalid){
 border: 1px red solid;
}

// or 

input:not(:focus):not(:invalid){
 border: 1px red solid;
}
SNEILΛ
la source
1
Lorsque vous ajoutez une réponse à une question de onze ans avec dix réponses existantes, il est vraiment important d'ajouter des explications sur le fonctionnement et le pourquoi de votre réponse et de souligner le nouvel aspect de la question auquel votre réponse répond. Si la réponse dépend de quelque chose qui a changé depuis que la question a été posée, indiquez-le également.
Jason Aller