: not (: leer) CSS-Selektor funktioniert nicht?

92

Ich habe eine verdammt gute Zeit mit diesem speziellen CSS-Selektor, der nicht funktionieren möchte, wenn ich ihn hinzufüge :not(:empty). Es scheint gut mit jeder Kombination der anderen Selektoren zu funktionieren:

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

Wenn ich das :not(:empty)Teil entferne , funktioniert es einwandfrei. Selbst wenn ich den Selektor auf input:not(:empty)ihn ändere, werden keine Eingabefelder ausgewählt, in die Text eingegeben wurde. Ist das kaputt oder darf ich es einfach nicht :emptyin einem :not()Selektor verwenden?

Das einzige andere, woran ich denken kann, ist, dass Browser immer noch sagen, dass das Element leer ist, weil es keine untergeordneten Elemente hat, sondern nur einen "Wert" pro Wort. Verfügt der :emptySelektor nicht über eine separate Funktionalität für ein Eingabeelement im Vergleich zu einem regulären Element? Dies scheint jedoch nicht wahrscheinlich zu sein, da bei Verwendung :emptyeines Felds und Eingabe etwas dazu führen, dass die alternativen Effekte verschwinden (weil es nicht mehr leer ist).

Getestet in Firefox 8 und Chrome.

animuson
quelle
Können Sie den entsprechenden Code posten?
Virendra
2
Kann ich Ihnen einen Teil des Zitats API - Referenz für die :emptyWähler „Einige andere Elemente, auf der anderen Seite, sind leer (dh sie haben keine Kinder) definitionsgemäß : <input>, <img>, <br>, und <hr>, zum Beispiel.“
David sagt, Monica
@Virendra: Das ist der relevante Code, aber ich habe die tatsächlichen CSS-Regeln hinzugefügt. Wenn ich das entferne :not(:empty), funktioniert der rote Rand wie erwartet für eine Eingabe, die nicht scharfgestellt, aber ungültig ist.
animuson

Antworten:

149

Als nichtiges Element wird ein <input>Element von der HTML-Definition von "leer" als leer betrachtet , da das Inhaltsmodell aller leeren Elemente immer leer ist . Sie stimmen also immer mit der :emptyPseudoklasse überein , unabhängig davon, ob sie einen Wert haben oder nicht. Aus diesem Grund wird ihr Wert auch durch ein Attribut im Start-Tag und nicht durch Textinhalt in Start- und End-Tags dargestellt.

Auch aus der Selectors-Spezifikation :

Die :emptyPseudoklasse repräsentiert ein Element, das überhaupt keine Kinder hat. In Bezug auf den Dokumentbaum müssen nur Elementknoten und Inhaltsknoten (wie DOM-Textknoten, CDATA-Knoten und Entitätsreferenzen), deren Daten eine Länge ungleich Null haben, als die Leere beeinflussend betrachtet werden.

Folglich input:not(:empty)wird niemals etwas in einem richtigen HTML-Dokument übereinstimmen. (Es würde immer noch in einem hypothetischen XML-Dokument funktionieren, das ein <input>Element definiert , das Text oder untergeordnete Elemente akzeptieren kann.)

Ich glaube nicht, dass Sie leere <input>Felder dynamisch mit nur CSS formatieren können (dh Regeln, die gelten, wenn ein Feld leer ist und nicht, wenn Text eingegeben wird). Sie können anfänglich leere Felder auswählen, wenn sie ein leeres valueAttribut haben ( input[value=""]) oder das Attribut insgesamt fehlt ( input:not([value])), aber das war es auch schon.

BoltClock
quelle
Hmm, ich erinnere mich nicht, was ich getan habe, um die Effekte mit nur dem zu beseitigen input:empty. Vielleicht habe ich etwas falsch geschrieben, wer weiß.
Animuson
9
Zum letzten Absatz der Antwort können inputElemente dynamisch gestaltet werden (in ausreichend modernen Browsern), wenn Sie das requiredAttribut im HTML-Markup verwenden können. Anschließend können Sie mit :validund :invalidin CSS testen, ob der Wert des Steuerelements nicht leer oder leer ist. Siehe stackoverflow.com/questions/16952526/…
Jukka K. Korpela
1
@ JukkaK.Korpela, sofern Sie nicht auch das Musterattribut verwenden.
WORMSS
2
Eingabe: nicht ([Wert = '']) wählt eine Eingabe mit einem Wert aus;)
Chris Love
@ Chris Love: Eingaben mit einem anfänglichen Wert (beim Laden der Seite).
BoltClock
43

Es ist mit Inline-Javascript onkeyup="this.setAttribute('value', this.value);"& möglichinput: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.
quelle
Ist die onchangeVeranstaltung in diesem Fall nicht besser? Da können Sie auch Eingabewerte mit bearbeiten Right click > Cut(zum Beispiel). Getestet: funktioniert gut.
Derk Jan Speelman
38

Sie könnten versuchen, Folgendes zu verwenden: Platzhalter angezeigt ...

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>

Keine große Unterstützung ... caniuse

Gijs Erenstein
quelle
1
ziemlich gute Unterstützung obwohl ... caniuse
Reggie Pinkham
Guter alter Internet Explorer (Y)
rorymorris89
@ rorymorris89 sogar die neueste Version von EDGE unterstützt nicht :-(
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
quelle
7

Sie können dies anders angehen; Lassen Sie die Verwendung der :emptyPseudoklasse aus und verwenden Sie inputEreignisse, um einen signifikanten Wert im <input>Feld zu erkennen und entsprechend zu formatieren :

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>

verbunden


Haftungsausschluss: Beachten Sie, dass inputEreignisse derzeit experimentell sind und wahrscheinlich nicht allgemein unterstützt werden.

Eliran Malka
quelle
3

Da Platzhalter bei der Eingabe verschwinden, können Sie Folgendes verwenden:

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

reine CSS-Lösung

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;
}
Star
quelle
0

Eine weitere reine CSS-Lösung

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

Dies sollte in modernen Browsern funktionieren:

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

Es wählt alle Eingaben mit dem Wertattribut aus und wählt dann Eingaben mit nicht leerem Wert aus.

Andrew Kondratev
quelle
10
Dies wäre jedoch nicht dynamisch. Es werden nur Eingabeelemente ausgewählt, für die das Attribut definiert ist value="". Das Eingeben / Entfernen von etwas in das Feld würde keine Änderungen verursachen.
Animuson
-1
input:not([value=""])

Dies funktioniert, weil wir die Eingabe nur auswählen, wenn keine leere Zeichenfolge vorhanden ist.

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

// or 

input:not(:focus):not(:invalid){
 border: 1px red solid;
}
SNEILΛ
quelle
1
Wenn Sie eine Antwort auf eine elf Jahre alte Frage mit zehn vorhandenen Antworten hinzufügen, ist es wirklich wichtig, eine Erklärung hinzuzufügen, wie und warum Ihre Antwort funktioniert, und darauf hinzuweisen, welchen neuen Aspekt der Frage Ihre Antwort anspricht. Wenn die Antwort von etwas abhängt, das sich seit dem Stellen der Frage geändert hat, weisen Sie auch darauf hin.
Jason Aller