1

I have tried the solutions here and the other duplicate here, but those questions are 4 years old and the solutions do not work on newer versions of Firefox. Also, the bug linked in the latter has status: VERIFIED FIXED.

I have tried using only the transition prefix matching the placeholder prefix along with the transition fallback with no luck. ex:

&::-moz-placeholder {
    -moz-transition: $transition;
    transition: $transition;
}

What's below works on chrome but not Firefox or Edge. The opacity changes fine but there is no transition. Am I missing something to support both Firefox and Edge placeholder transitions?

@mixin transition($transition...) {
    -webkit-transition: $transition;
    -moz-transition: $transition;
    -o-transition: $transition;
    transition: $transition;
}

@mixin placeholderOpacity($opacity) {
    &:-moz-placeholder {opacity: $opacity}
    &:-ms-input-placeholder  {opacity: $opacity}
    &::-webkit-input-placeholder {opacity: $opacity}
    &::-moz-placeholder {opacity: $opacity}
    &::placeholder  {opacity: $opacity}
}

@mixin placeholderTransition($transition) {
    &:-moz-placeholder {@include transition($transition);}
    &:-ms-input-placeholder  {@include transition($transition);}
    &::-webkit-input-placeholder {@include transition($transition);}
    &::-moz-placeholder {@include transition($transition);}
    &::placeholder  {@include transition($transition);}
}

input {
    @include placeholderOpacity(0);
    @include placeholderTransition(opacity 500ms ease-in-out);
}

input:focus {
    @include placeholderOpacity(1);
}
Alireza
  • 2,319
  • 2
  • 23
  • 35
Clint
  • 2,696
  • 23
  • 42
  • 1
    For a cross browser solution, maybe this answer of mine would be of interest: https://stackoverflow.com/questions/44333727/simulation-of-a-placeholder/44333787#44333787 – Asons Jul 03 '17 at 18:06
  • 2
    umm, my answers :) I just tried on the latest Firefox and yes, it fails.. can you give me a day to solve it? I'll see if I can find an alternative way to animate the placeholders. – Mr. Alien Jul 03 '17 at 18:09
  • @LGSon Thank you, I am not opposed to javascript solutions if it's not possible with CSS. – Clint Jul 03 '17 at 18:16
  • Well, the script has actually nothing to do with the animation itself, it fixes an issue the input element has, where when one adds a value to an input, you can't detect using the CSS `input:not([value=""])` if there is a value or not, as the selector check the `input`s attribute `value`, which is not the same as what you enter in the field – Asons Jul 03 '17 at 18:24
  • @LGSon I see, I just took a quick peek before. I already have a label effect like the one listed in your answer but now I'm trying to transition the placeholder in to view while the label is transitioning to the top. Since I already have something very similar to your answer it would be easy to do the same thing on another element. In my specific case it would require a little more JS, so I would prefer a pure CSS solution if possible. – Clint Jul 03 '17 at 18:40

1 Answers1

2

Since there is no real cross browser solution to style and animate placeholder's, I decided to post an updated version from another answer of mine, where this one having both a label, a placeholder and a required asterisk.

I have added a tiny script with one purpose only, to replicate what is written in an input field to its attribute value.

With that, one can then use CSS alone for the actual styling and animations, by simply use the attribute selector [attribute="value"] (in the way I think most users expect it to be used)

(function(pls) {
  /* run this script when page loaded */
  window.addEventListener('load', function() {
    /* find and iterate all "input placeholder" elements */
    pls = document.querySelectorAll('.placeholder input');
    for (var i = 0; i < pls.length; i++) {
      /* attach a handler to replicate input value */
      pls[i].addEventListener('input', function() {
        this.setAttribute('value', this.value);
      })
    }
  })
})();
.placeholder {
  position: relative;
  padding-top: 15px;
}
.placeholder + .placeholder {
  margin-top: 10px;
}
.placeholder label {
  position: absolute;
  left: 5px;
  width: 100%;
  top: calc(50.5% + 7.5px);
  transform: translateY(-50.5%);
  pointer-events: none;
  font-size: 16px;
  line-height: 16px;
}
.placeholder label::before,
.placeholder label span {  
  position: relative;
  top: 0;
  transition: top .5s;
}

/* the label text + asterisk */
.placeholder input + label::before {
  content: attr(data-text) ' '; 
  color: black;
}
.placeholder label span {
  color: red;
}
.placeholder input:not([required]) + label span {
  display: none;
}
.placeholder input:not([value=""]) + label::before,
.placeholder input:focus + label::before,
.placeholder input:not([value=""]) + label span,
.placeholder input:focus + label span {
  top: -22px;
}

/* the placeholder text */
.placeholder input + label::after {
  content: attr(data-placeholder); 
  position: absolute;
  left: 0; top: 0;
  color: gray;
  opacity: 0;
  transition: opacity .5s .2s;
}
.placeholder input:focus + label::after {
  opacity:  1;
}
.placeholder input:not([value=""]) + label::after {
  opacity:  0;
  transition: opacity .2s;
}
<div class="placeholder">
  <input type="text" name="name" value="">
  <label data-text="Name" data-placeholder="Add your name"><span>*</span></label>
</div>
<div class="placeholder">
  <input type="text" name="mail" value="" required>
  <label data-text="Email" data-placeholder="Add your email address"><span>*</span></label>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165