: no (: vacío) ¿El selector de CSS no funciona?

93

Me lo estoy pasando genial con este selector de CSS en particular que no quiere funcionar cuando lo agrego :not(:empty). Parece funcionar bien con cualquier combinación de los otros selectores:

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

Si quito la :not(:empty)pieza, funciona bien. Incluso si cambio el selector a input:not(:empty), todavía no seleccionará campos de entrada que tengan texto escrito en ellos. ¿Está roto o simplemente no puedo usarlo :emptydentro de un :not()selector?

La única otra cosa en la que puedo pensar es que los navegadores siguen diciendo que el elemento está vacío porque no tiene hijos, solo un "valor" por decir. ¿El :emptyselector no tiene una funcionalidad separada para un elemento de entrada frente a un elemento regular? Sin embargo, esto no parece probable porque usarlo :emptyen un campo y escribir algo en él hará que los efectos alternativos desaparezcan (porque ya no está vacío).

Probado en Firefox 8 y Chrome.

animuson
fuente
¿Puedes publicar el código relevante?
Virendra
2
Puedo citar parte de la documentación sobre API para :emptyselectora : "Algunos otros elementos, por otra parte, se vacía (es decir, no tienen hijos) por definición: <input>, <img>, <br>, y <hr>, por ejemplo."
David dice reinstalar a Monica
@Virendra: Ese es el código relevante, pero le agregué las reglas CSS reales. Si elimino el :not(:empty), el borde rojo funciona como se esperaba para una entrada que no está enfocada pero no es válida.
animuson

Respuestas:

151

Al ser un elemento vacío , un <input>elemento se considera vacío según la definición HTML de "vacío", ya que el modelo de contenido de todos los elementos vacíos siempre está vacío . Por lo tanto, siempre coincidirán con la :emptypseudoclase, tengan o no un valor. Esta es también la razón por la que su valor está representado por un atributo en la etiqueta de inicio, en lugar del contenido de texto dentro de las etiquetas de inicio y finalización.

Además, de la especificación de Selectores :

La :emptypseudoclase representa un elemento que no tiene hijos. En términos del árbol del documento, solo los nodos de elementos y los nodos de contenido (como los nodos de texto DOM, los nodos CDATA y las referencias de entidad) cuyos datos tienen una longitud distinta de cero deben considerarse que afectan la vacuidad;

En consecuencia, input:not(:empty)nunca coincidirá con nada en un documento HTML adecuado. (Todavía funcionaría en un documento XML hipotético que define un <input>elemento que puede aceptar texto o elementos secundarios).

No creo que pueda <input>aplicar estilo a los campos vacíos dinámicamente usando solo CSS (es decir, reglas que se aplican siempre que un campo está vacío, y no una vez que se ingresa el texto). Puede seleccionar campos inicialmente vacíos si tienen un valueatributo vacío ( input[value=""]) o carecen del atributo por completo ( input:not([value])), pero eso es todo.

BoltClock
fuente
Hmm, no recuerdo qué hice para que los efectos desaparecieran solo con el input:empty. Quizás escribí algo mal, quién sabe.
animuson
9
Con respecto al último párrafo de la respuesta, los inputelementos se pueden diseñar dinámicamente (en navegadores suficientemente modernos) si puede usar el requiredatributo en el marcado HTML. Luego puede usar :validy :invaliden CSS para probar el valor no vacío frente al valor vacío del control. Ver stackoverflow.com/questions/16952526/…
Jukka K. Korpela
1
@ JukkaK.Korpela a menos que también esté usando el atributo de patrón.
WORMSS
2
input: not ([value = '']) seleccionará una entrada con un valor;)
Chris Love
@Chris Love: Entradas con un valor inicial (al cargar la página).
BoltClock
43

Es posible con JavaScript en línea onkeyup="this.setAttribute('value', this.value);"yinput:not([value=""]):not(:focus):invalid

Demostración: 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);" />

Mes.
fuente
¿No es onchangemejor el evento en este caso? Dado que también puede editar valores de entrada con Right click > Cut(por ejemplo). Probado: funciona bien.
Derk Jan Speelman
41

Podría intentar usar: 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>

aunque no hay un gran apoyo ... caniuse

Gijs Erenstein
fuente
2
bastante buen apoyo aunque ... caniuse
Reggie Pinkham
Buen viejo Internet Explorer (Y)
rorymorris89
@ rorymorris89 incluso la última versión de EDGE no admite :-(
Lunes
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
fuente
7

Puede abordar esto de manera diferente; omitir el uso de la :emptypseudoclase y utilizar inputeventos para detectar un valor significativo en el <input>campo y diseñarlo en consecuencia:

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>

Relacionado


Descargo de responsabilidad: tenga en cuenta que los inputeventos son actualmente experimentales y probablemente no cuentan con un amplio apoyo.

Eliran Malka
fuente
3

Dado que el marcador de posición desaparece en la entrada, puede usar:

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

solución 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;
}
estrella
fuente
0

Otra solución 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
fuente
-1

Esto debería funcionar en los navegadores modernos:

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

Selecciona todas las entradas con atributo de valor y luego selecciona las entradas con valor no vacío entre ellas.

Andrew Kondratev
fuente
10
Sin embargo, esto no sería dinámico. Solo seleccionaría elementos de entrada que tengan el atributo definido como value="". Escribir / eliminar algo en el cuadro no provocaría ningún cambio.
animuson
-1
input:not([value=""])

Esto funciona porque estamos seleccionando la entrada solo cuando no hay una cadena vacía.

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

// or 

input:not(:focus):not(:invalid){
 border: 1px red solid;
}
SNEILΛ
fuente
1
Al agregar una respuesta a una pregunta de once años con diez respuestas existentes, es realmente importante agregar alguna explicación de cómo y por qué funciona su respuesta y señalar qué aspecto nuevo de la pregunta aborda su respuesta. Si la respuesta depende de algo que haya cambiado desde que se hizo la pregunta, indíquelo también.
Jason Aller