: not (: empty) Селектор CSS не работает?

95

У меня чертовски много времени с этим конкретным селектором 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.

анимусон
источник
Вы можете разместить соответствующий код?
Вирендра
2
Могу ли я сослаться на вас часть ссылки API для :emptyвыбора : «Некоторые другие элементы, с другой стороны, являются пустыми (т.е. не имеют детей) по определению: <input>, <img>, <br>, и <hr>, например.»
Дэвид говорит, что нужно восстановить Монику
@Virendra: это соответствующий код, но я добавил к нему настоящие правила CSS. Если я удалю :not(:empty), красная рамка будет работать должным образом для ввода, который не в фокусе, но недействителен.
animuson

Ответы:

152

Являясь элементом void , <input>элемент считается пустым в соответствии с определением HTML "пустым", поскольку модель содержимого всех элементов void всегда пуста . Таким образом, они всегда будут соответствовать :emptyпсевдоклассу, независимо от того, имеют ли они значение. Вот почему их значение представлено атрибутом в начальном теге, а не текстовым содержимым внутри начального и конечного тегов.

Также из спецификации Selectors :

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

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

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

BoltClock
источник
Хм, я не помню, что я сделал, чтобы эффекты исчезли только с input:empty. Может, я что-то не так набрал, кто знает.
анимусон
9
Возвращаясь к последнему абзацу ответа, inputэлементы можно стилизовать динамически (в достаточно современных браузерах), если вы можете использовать requiredатрибут в разметке HTML. Затем вы можете использовать :validи :invalidв CSS для проверки непустого или пустого значения элемента управления. См. Stackoverflow.com/questions/16952526/…
Юкка К. Корпела
1
@ JukkaK.Korpela, если вы также не используете атрибут pattern.
WORMSS 01
2
input: not ([value = '']) выберет вход со значением;)
Крис Лав
@Chris Love: вводит начальное (при загрузке страницы) значение.
BoltClock
46

Это возможно со встроенным 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" 
  onchange="this.setAttribute('value', this.value);" />

Пн.
источник
Разве onchangeв этом случае мероприятие не лучше? Так как вы также можете редактировать входные значения с помощью Right click > Cut(например). Протестировал: работает нормально.
Дерк Ян
42

Вы можете попробовать использовать: 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

Гийс Эренштейн
источник
2
довольно неплохая поддержка ... caniuse
Реджи Пинкхэм
Старый добрый Internet Explorer (Y)
rorymorris89
@ rorymorris89 даже последняя версия EDGE не поддерживает :-(
Пн.
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>

Амит
источник
7

Вы можете подойти к этому иначе; исключить использование :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события в настоящее время являются экспериментальными и, вероятно, широко не поддерживаются.

Элиран Малка
источник
3

Поскольку заполнитель исчезает при вводе, вы можете использовать:

input:placeholder-shown{
    //rules for not empty input
}
Лука К.
источник
2

чистое решение 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;
}
звезда
источник
0

Еще одно чистое решение 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
источник
-1

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

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

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

Андрей Кондратьев
источник
10
Однако это не было бы динамичным. Он будет выбирать только элементы ввода, для которых атрибут определен как value="". Ввод / удаление чего-либо в поле не вызовет никаких изменений.
animuson
-1
input:not([value=""])

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

Антон
источник
-1
input:not(:invalid){
 border: 1px red solid;
}

// or 

input:not(:focus):not(:invalid){
 border: 1px red solid;
}
SNEILΛ
источник
1
Добавляя ответ на вопрос одиннадцатилетней давности с десятью существующими ответами, действительно важно добавить некоторое объяснение того, как и почему ваш ответ работает, и указать, какой новый аспект вопроса касается вашего ответа. Если ответ зависит от чего-то, что изменилось после того, как вопрос был задан, также укажите это.
Джейсон Аллер