animuson
animuson

Reputation: 54729

:not(:empty) CSS selector is not working?

I'm having a heck of a time with this particular CSS selector which does not want to work when I add :not(:empty) to it. It seems to work fine with any combination of the other selectors:

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

If I remove the :not(:empty) part, it works just fine. Even if I change the selector to input:not(:empty) it still won't select input fields which have text typed into them. Is this broken or am I just not allowed to use :empty within a :not() selector?

The only other thing I can think of is that browsers are still saying that the element is empty because it has no children, just a "value" per say. Does the :empty selector not have separate functionality for an input element versus a regular element? This doesn't seem probable though because using :empty on a field and typing something into it will cause the alternate effects to go away (because it is no longer empty).

Tested in Firefox 8 and Chrome.

Upvotes: 142

Views: 316748

Answers (13)

Muhammed
Muhammed

Reputation: 211

You can do trick by adding placeholder to input with empty value then add input:not(:placeholder-shown)

<input type="text" placeholder=" ">
input:not(:placeholder-shown){
 color: red;
}

Upvotes: 4

Muhammad Tahir Ali
Muhammad Tahir Ali

Reputation: 415

If you want to check whether the input field is empty or not you can try this:

HTML

<input type="text" placeholder='Placeholder'/>

CSS

input:not(:placeholder-shown){
   background-color: red;
}

Since Placeholder get vanishes when something is typed in the input field so we can check whether Placeholder is visible or not through CSS

Upvotes: 8

Mo.
Mo.

Reputation: 27465

It is possible with inline 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);" />

Upvotes: 70

Anton
Anton

Reputation: 29

input:not([value=""])

This works because we are selecting the input only when there isn't an empty string.

Upvotes: -1

Andrew Kondratev
Andrew Kondratev

Reputation: 307

This should work in modern browsers:

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

It selects all inputs with value attribute and then select inputs with non empty value among them.

Upvotes: -2

star
star

Reputation: 19

pure css solution

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;
}

Upvotes: 1

Eliran Malka
Eliran Malka

Reputation: 16263

You may approach this differently; omit the use of the :empty pseudo-class, and utilize input events to detect a significant value in the <input> field, then style it accordingly:

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>

Related


Disclaimer: note that input events are currently experimental, and probably not widely supported. nope! forget about it - it's a living standard now.

Upvotes: 8

Simon Botero
Simon Botero

Reputation: 603

You can use &:valid on your input and that make the trick.

Upvotes: -3

vacsati
vacsati

Reputation: 567

Another pure CSS solution

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

Upvotes: 3

Luca C.
Luca C.

Reputation: 12574

Since placeholder disappear on input, you can use:

input:placeholder-shown{
    //rules for not empty input
}

Upvotes: 10

Amit
Amit

Reputation: 1919

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

Upvotes: 20

BoltClock
BoltClock

Reputation: 723719

Being a void element, an <input> element is considered empty by the HTML definition of "empty", since the content model of all void elements is always empty. So they will always match the :empty pseudo-class, whether or not they have a value. This is also why their value is represented by an attribute in the start tag, rather than text content within start and end tags.

Also, from the Selectors spec:

The :empty pseudo-class represents an element that has no children at all. In terms of the document tree, only element nodes and content nodes (such as DOM text nodes, CDATA nodes, and entity references) whose data has a non-zero length must be considered as affecting emptiness;

Consequently, input:not(:empty) will never match anything in a proper HTML document. (It would still work in a hypothetical XML document that defines an <input> element that can accept text or child elements.)

I don't think you can style empty <input> fields dynamically using just CSS (i.e. rules that apply whenever a field is empty, and don't once text is entered). You can select initially empty fields if they have an empty value attribute (input[value=""]) or lack the attribute altogether (input:not([value])), but that's about it.

Upvotes: 199

Gijs Erenstein
Gijs Erenstein

Reputation: 1200

You could try using :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>

no great support though... caniuse

Upvotes: 75

Related Questions