: не (: пустой) селектор CSS не работает?

у меня чертовски много времени с этим конкретным селектором CSS, который не хочет работать, когда я добавляю :not(:empty) к нему. Кажется, он отлично работает с любой комбинацией других селекторов:

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

если я удалить :not(:empty) часть, она работает просто отлично. Даже если я изменю селектор на input:not(:empty) он по-прежнему не будет выбирать поля ввода, в которые введен текст. Это сломано или мне просто не разрешено использовать :empty внутри :not() селектор?

только другая вещь, о которой я могу думать, это то, что браузеры все еще говорят, что элемент пуст, потому что у него нет детей, просто "значение", скажем. Делает :empty селектор не имеет отдельной функциональности для входного элемента по сравнению с обычным элементом? Это не кажется вероятным, хотя, потому что использование :empty на поле и ввод чего-то в него приведет к тому, что альтернативные эффекты исчезнут (потому что он больше не пуст).

протестировано в Firefox 8 и Chrome.

7 ответов


будучи недействительными элемент, an <input> элемент является пустой по определению HTML "пустой", так как модель содержимого всех элементов void всегда пусто. Поэтому они всегда будут соответствовать :empty псевдо-класс, независимо от того, имеют ли они значение. Именно поэтому их значение представлено атрибутом в теге start, а не текстовым содержимым в тегах start и end.

С селекторы spec:

на :empty псевдо-класс представляет элемент, который не имеет дочерних элементов вообще. С точки зрения дерева документов, только узлы элементов и узлы содержимого (такие как текстовые узлы DOM, узлы CDATA и ссылки на сущности), данные которых имеют ненулевую длину, должны рассматриваться как влияющие на пустоту;

следовательно, input:not(:empty) никогда не будет соответствовать чему-либо в правильном HTML-документе. (Он все равно будет работать в гипотетическом XML-документе, который определяет <input> элемент, который может принимать текстовые или дочерние элементы.)

Я не думаю, что вы можете стиль пустой <input> поля динамически, используя только CSS (т. е. правила, которые применяются, когда поле пусто, и не один раз вводится текст). Вы можете выбрать изначально пустые поля, если у них есть пустой (input[value=""]) или вообще отсутствует атрибут (input:not([value])), но это все.


это возможно с помощью встроенного javascript onkeyup="this.setAttribute('value', this.value);" & input:not([value=""]):not(:focus):invalid

демо:http://jsfiddle.net/mhsyfvv9/

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

вы можете попробовать использовать: 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>
нет большой поддержки... caniuse

вы можете подойти к этому по-другому; отказаться от использования :empty псевдо-классе и использовать input события для обнаружения значительного значения в <input> поле и стиль его соответствующим образом:

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>

по теме


отказ от ответственности: отметим, что input событий в настоящее время экспериментальные, и, вероятно, не получило широкой поддержки.


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

Это должно работать в современных браузерах:

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

он выбирает все входы со значением атрибута, а затем выберите входы с непустым значением среди них.


input:not([value=""])

это работает, потому что мы выбираем ввод только тогда, когда нет пустой строки.