: não (: vazio) O seletor CSS não está funcionando?

92

Estou tendo um inferno com este seletor CSS específico que não quer funcionar quando eu adiciono :not(:empty)a ele. Parece funcionar bem com qualquer combinação dos outros seletores:

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

Se eu remover a :not(:empty)peça, funciona perfeitamente. Mesmo se eu mudar o seletor para input:not(:empty)ele ainda não selecionará os campos de entrada que têm texto digitado neles. Ele está quebrado ou não tenho permissão para usar :emptyem um :not()seletor?

A única outra coisa que consigo pensar é que os navegadores ainda estão dizendo que o elemento está vazio porque não tem filhos, apenas um "valor" por dizer. O :emptyseletor não tem funcionalidade separada para um elemento de entrada e um elemento regular? Isso não parece provável porque usar:empty em um campo e digitar algo nele fará com que os efeitos alternativos desapareçam (porque ele não está mais vazio).

Testado no Firefox 8 e Chrome.

animuson
fonte
Você pode postar o código relevante?
Virendra
2
Posso citar-lhe parte da referência da API para o :emptyseletor : "Alguns outros elementos, por outro lado, estão vazios (ou seja, não têm filhos) por definição: <input>, <img>, <br>, e <hr>, por exemplo."
David diz para restabelecer Monica em
@Virendra: Esse é o código relevante, mas adicionei as regras CSS reais a ele. Se eu remover o :not(:empty), a borda vermelha funcionará conforme o esperado para uma entrada que não está em foco, mas é inválida.
animuson

Respostas:

149

Sendo um elemento void , um <input>elemento é considerado vazio pela definição HTML de "vazio", uma vez que o modelo de conteúdo de todos os elementos void está sempre vazio . Portanto, eles sempre corresponderão à :emptypseudoclasse, tenham ou não um valor. É também por isso que seu valor é representado por um atributo na tag inicial, em vez de conteúdo de texto nas tags inicial e final.

Além disso, nas especificações dos seletores :

A :emptypseudoclasse representa um elemento que não possui nenhum filho. Em termos de árvore de documento, apenas nós de elemento e nós de conteúdo (como nós de texto DOM, nós CDATA e referências de entidade) cujos dados têm um comprimento diferente de zero devem ser considerados como afetando o vazio;

Conseqüentemente, input:not(:empty)nunca corresponderá a nada em um documento HTML adequado. (Ainda funcionaria em um documento XML hipotético que define um <input>elemento que pode aceitar texto ou elementos filho.)

Eu não acho que você pode estilizar <input>campos vazios dinamicamente usando apenas CSS (ou seja, regras que se aplicam sempre que um campo está vazio e não se aplicam depois que o texto é inserido). Você pode selecionar campos inicialmente vazios se eles tiverem um valueatributo vazio ( input[value=""]) ou não tiverem o atributo completamente ( input:not([value])), mas isso é tudo.

BoltClock
fonte
Hmm, não me lembro o que fiz para que os efeitos desaparecessem apenas com o input:empty. Talvez eu tenha digitado algo errado, quem sabe.
animuson
9
No último parágrafo da resposta, os inputelementos podem ser estilizados dinamicamente (em navegadores suficientemente modernos) se você puder usar o requiredatributo na marcação HTML. Em seguida, você pode usar :valide :invalidem CSS para testar o valor não vazio vs. valor vazio do controle. Consulte stackoverflow.com/questions/16952526/…
Jukka K. Korpela
1
@ JukkaK.Korpela, a menos que você também esteja usando o atributo de padrão.
WORMSS 01 de
2
input: not ([value = '']) selecionará uma entrada com um valor;)
Chris Love
@Chris Love: entradas com um valor inicial (no carregamento da página).
BoltClock
43

É possível com javascript inline onkeyup="this.setAttribute('value', this.value);"&input:not([value=""]):not(:focus):invalid

Demo: 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.
fonte
O onchangeevento não é melhor neste caso? Uma vez que você também pode editar valores de entrada com Right click > Cut(por exemplo). Testei: funciona bem.
Derk Jan Speelman
38

Você pode tentar usar: placeholder-mostrado ...

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>

nenhum grande suporte ... caniuse

Gijs Erenstein
fonte
1
muito bom suporte ... caniuse
Reggie Pinkham
O bom e velho Internet Explorer (Y)
rorymorris89
@ rorymorris89 mesmo a versão mais recente de EDGE não suporta :-(
Mo.
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
fonte
7

Você pode abordar isso de forma diferente; omita o uso da :emptypseudoclasse e utilize inputeventos para detectar um valor significativo no <input>campo e estilize-o de acordo:

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>

Relacionados


Isenção de responsabilidade: observe que os inputeventos são atualmente experimentais e provavelmente não são amplamente suportados.

Eliran Malka
fonte
3

Como o marcador desaparece na entrada, você pode usar:

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

solução css pura

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;
}
Estrela
fonte
0

Outra solução CSS pura

.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
fonte
-1

Isso deve funcionar em navegadores modernos:

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

Ele seleciona todas as entradas com atributo de valor e, em seguida, seleciona entradas com valor não vazio entre elas.

Andrew Kondratev
fonte
10
Isso não seria dinâmico, no entanto. Ele selecionaria apenas os elementos de entrada que têm o atributo definido como value="". Digitar / remover algo na caixa não causaria nenhuma alteração.
animuson
-1
input:not([value=""])

Isso funciona porque estamos selecionando a entrada apenas quando não há uma string vazia.

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

// or 

input:not(:focus):not(:invalid){
 border: 1px red solid;
}
SNEILΛ
fonte
1
Ao adicionar uma resposta a uma pergunta de onze anos com dez respostas existentes, é realmente importante adicionar alguma explicação de como e por que sua resposta funciona e apontar qual novo aspecto da pergunta sua resposta aborda. Se a resposta depender de algo que mudou desde que a pergunta foi feita, indique isso também.
Jason Aller