: not (: empty) Selektor CSS nie działa?

95

Mam świetny czas z tym konkretnym selektorem CSS, który nie chce działać, gdy :not(:empty)do niego dodam . Wydaje się, że działa dobrze z dowolną kombinacją innych selektorów:

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

Jeśli usunę :not(:empty)część, działa dobrze. Nawet jeśli zmienię selektor na input:not(:empty)to, nadal nie będę wybierał pól wejściowych, w których wpisano tekst. Czy to jest zepsute, czy po prostu nie wolno mi używać :emptyw:not() selektorze?

Jedyną inną rzeczą, o której przychodzi mi do głowy, jest to, że przeglądarki wciąż mówią, że element jest pusty, ponieważ nie ma dzieci, tylko „wartość” na każde powiedzenie. Czy :emptyselektor nie ma oddzielnej funkcji dla elementu wejściowego w porównaniu ze zwykłym elementem? Nie wydaje się to jednak prawdopodobne, ponieważ używasz:empty na polu i wpisanie czegoś w nim spowoduje, że alternatywne efekty znikną (ponieważ nie jest już puste).

Przetestowano w przeglądarce Firefox 8 i Chrome.

animuson
źródło
Czy możesz wysłać odpowiedni kod?
Virendra
2
Mogę zacytować część odniesienia API dla :emptyselektora : „Niektóre inne elementy, z drugiej strony, są puste (czyli nie mają dzieci) według definicji: <input>, <img>, <br>, i <hr>, na przykład.”
David mówi, że przywróć Monikę
@Virendra: To jest odpowiedni kod, ale dodałem do niego aktualne reguły CSS. Jeśli usunę :not(:empty), czerwona ramka będzie działać zgodnie z oczekiwaniami dla danych wejściowych, które nie są aktywne, ale są nieprawidłowe.
animuson

Odpowiedzi:

152

Będąc elementem void , <input>element jest uważany za pusty zgodnie z definicją HTML słowa „empty”, ponieważ model zawartości wszystkich elementów void jest zawsze pusty . Dlatego zawsze będą pasować do :emptypseudoklasy, niezależnie od tego, czy mają wartość, czy nie. Z tego powodu ich wartość jest reprezentowana przez atrybut w tagu początkowym, a nie treść tekstowa w tagach początkowych i końcowych.

Ponadto ze specyfikacji selektorów :

:emptyPseudo-klasa reprezentuje element, który nie ma dzieci w ogóle. Jeśli chodzi o drzewo dokumentów, tylko węzły elementów i węzły treści (takie jak węzły tekstowe DOM, węzły CDATA i odniesienia do encji), których dane mają niezerową długość, należy traktować jako wpływające na pustkę;

W związku z tym input:not(:empty)nigdy nie dopasuje niczego w odpowiednim dokumencie HTML. (Nadal działałby w hipotetycznym dokumencie XML, który definiuje <input>element, który może akceptować tekst lub elementy potomne).

Nie sądzę, aby można <input>dynamicznie stylizować puste pola za pomocą samego CSS (tj. Reguł, które mają zastosowanie, gdy pole jest puste, a nie po wprowadzeniu tekstu). Możesz wybrać początkowo puste pola, jeśli mają pusty valueatrybut ( input[value=""]) lub całkowicie go brakuje ( input:not([value])), ale to wszystko.

BoltClock
źródło
Hmm, nie pamiętam, co zrobiłem, aby efekty zniknęły tylko z input:empty. Być może wpisałem coś źle, kto wie.
animuson
9
Wracając do ostatniego akapitu odpowiedzi, inputelementy mogą być stylizowane dynamicznie (w wystarczająco nowoczesnych przeglądarkach), jeśli możesz użyć requiredatrybutu w znacznikach HTML. Następnie możesz użyć :validi :invalidw CSS, aby przetestować niepustą i pustą wartość kontrolki. Zobacz stackoverflow.com/questions/16952526/…
Jukka K. Korpela
1
@ JukkaK.Korpela, chyba że używasz również atrybutu wzorca.
WORMSS
2
input: not ([value = '']) wybierze wejście z wartością;)
Chris Love
@Chris Love: dane wejściowe z wartością początkową (przy ładowaniu strony).
BoltClock
46

Jest to możliwe dzięki wbudowanemu javascript 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);" />

Pon.
źródło
Czy onchangew tym przypadku impreza nie jest lepsza? Ponieważ możesz również edytować wartości wejściowe Right click > Cut(na przykład). Przetestowałem: działa dobrze.
Derk Jan Speelman
42

Możesz spróbować użyć: symbol zastępczy pokazany ...

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>

ale bez wielkiego wsparcia ... caniuse

Gijs Erenstein
źródło
2
całkiem niezłe wsparcie ... caniuse
Reggie Pinkham
Stary dobry Internet Explorer (Y)
rorymorris89
@ rorymorris89 Nawet najnowsza wersja EDGE nie obsługuje :-(
pon.
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
źródło
7

Możesz podejść do tego inaczej; pomiń użycie :emptypseudoklasy i wykorzystaj inputzdarzenia do wykrycia znaczącej wartości w <input>polu i odpowiednio ją stylizuj:

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>

Związane z


Zastrzeżenie: pamiętaj, że inputwydarzenia są obecnie eksperymentalne i prawdopodobnie nie są szeroko obsługiwane.

Eliran Malka
źródło
3

Ponieważ symbol zastępczy znika przy wprowadzaniu danych, możesz użyć:

input:placeholder-shown{
    //rules for not empty input
}
Luca C.
źródło
2

czyste rozwiązanie 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;
}
gwiazda
źródło
0

Kolejne czyste rozwiązanie CSS

.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
źródło
-1

To powinno działać w nowoczesnych przeglądarkach:

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

Wybiera wszystkie dane wejściowe z atrybutem wartości, a następnie wybiera spośród nich dane wejściowe niepuste.

Andrew Kondratev
źródło
10
Nie byłoby to jednak dynamiczne. Wybrałby tylko elementy wejściowe, które mają atrybut zdefiniowany jako value="". Wpisanie / usunięcie czegoś w polu nie spowodowałoby żadnych zmian.
animuson
-1
input:not([value=""])

To działa, ponieważ wybieramy dane wejściowe tylko wtedy, gdy nie ma pustego ciągu.

Anton
źródło
-1
input:not(:invalid){
 border: 1px red solid;
}

// or 

input:not(:focus):not(:invalid){
 border: 1px red solid;
}
SNEILΛ
źródło
1
Dodając odpowiedź na pytanie sprzed jedenastu lat z dziesięcioma istniejącymi odpowiedziami, naprawdę ważne jest, aby dodać wyjaśnienie, jak i dlaczego działa twoja odpowiedź oraz wskazać, jaki nowy aspekt pytania dotyczy odpowiedzi. Jeśli odpowiedź zależy od czegoś, co zmieniło się od czasu zadania pytania, również to zaznacz.
Jason Aller