16

I'm looking for css code that move the placeholder text above the input on focus. I found this code here. This code is perfect but my input tag is wrapped inside <span> and for that reason general sibling selector is not working. Any ideas how to edit this css?

<div>
  <span class='blocking-span'>
  <input type="text" class="inputText" />
  </span>
  <span class="floating-label">Your email address</span>
</div>
Community
  • 1
  • 1
trenccan
  • 720
  • 3
  • 7
  • 19
  • This is not possible with CSS using your current layout. – Rick Hitchcock Feb 14 '17 at 18:23
  • If you show your CSS as well, so we can see how it is suppose to render, we might be able to suggest a solution – Asons Feb 14 '17 at 18:29
  • css is on the original link in description. – trenccan Feb 14 '17 at 18:31
  • 1
    Could you move `floating-label` after the input within `blocking-span`? – Rick Hitchcock Feb 14 '17 at 18:32
  • What does `blocking-span` class do? ... `display: block`? – Asons Feb 14 '17 at 18:35
  • Please replace your `` with a ` – aardrian Feb 14 '17 at 21:48
  • 1. http://bradfrost.com/blog/post/float-label-pattern/ 2. http://allthingssmitty.com/2016/09/25/accessible-floating-labels/ 3. http://codepen.io/aardrian/pen/MeeZrQ – aardrian Feb 14 '17 at 21:53
  • I noticed you changed the accepted answer, which is fine, do not though that the `:placeholder-shown` is an experimental technology (meaning it can change its behavior at any time), and still, 1.5 year after this answer were given, only work in less than half of all the existing browsers. – Asons Jul 04 '18 at 14:40
  • 2022 :placeholder-shown is now in 95% of browsers https://caniuse.com/css-placeholder-shown – notapatch Mar 23 '22 at 10:49

3 Answers3

37

You can use the CSS pseudo-selector :placeholder-shown in this case to detect when to move a fake placeholder out of the way. See example below:

label {
  margin:20px 0;
  position:relative;
  display:inline-block;
}
  
span {
  padding:10px;
  pointer-events: none;
  position:absolute;
  left:0;
  top:0;
  transition: 0.2s;
  transition-timing-function: ease;
  transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
  opacity:0.5;
}

input {
  padding:10px;
}

input:focus + span, input:not(:placeholder-shown) + span {
  opacity:1;
  transform: scale(0.75) translateY(-100%) translateX(-30px);
}

/* For IE Browsers*/
input:focus + span, input:not(:-ms-input-placeholder) + span {
  opacity:1;
  transform: scale(0.75) translateY(-100%) translateX(-30px);
}
<label>
  <input placeholder=" ">
  <span>Placeholder Text</span>
</label>
Kiran
  • 20,167
  • 11
  • 67
  • 99
Stanley
  • 3,935
  • 2
  • 18
  • 22
  • 1
    I'd suggest setting the font-size instead of scale(0.75) and translateX(-30px) – lynx Nov 07 '18 at 03:10
  • What does input:not(:placeholder-shown) + span do? I recently recreated this effect without the need to add that line in. It is not clear what it is doing. As @lynx suggested, font-size is much better solution otherwise the x translates are all off when adding multiple inputs – Theorder Mar 24 '20 at 06:49
8

With the given links CSS etc, simply move the floating-label inside the blocking-span.

By using position: relative on the div the floating-label will still re-position as if it were outside the blocking-span

div {
  position: relative; /*  make label relate to div  */
  padding-top: 10px;  /*  make space for label      */
}
.inputText {
  font-size: 14px;
  width: 200px;
  height: 25px;
}
.floating-label {
  position: absolute;
  pointer-events: none;
  left: 15px;
  top: 18px;
  transition: 0.2s ease all;
}
input:focus ~ .floating-label,
input:not(:focus):valid ~ .floating-label {
  top: -6px;
}
<div>
  <span class='blocking-span'>
    <input type="text" class="inputText" required/>
    <span class="floating-label">Your email address</span>
  </span>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
0

If you change html structure then your reference example is work but if you don't want change html structure then you need to write little jQuery. You can check this.

$(function(){
  $('.blocking-span input').on('focus', function(){
    $(this).parents('.parents-elm').addClass('foucs-content'); // When focus the input area
  });
  $(document).mouseup(function(e){
  if($(e.target).parents('.blocking-span input').length==0 && !$(e.target).is('.blocking-span input')){
   $('.parents-elm').removeClass('foucs-content');
  }
 });
});
div{
  position: relative;
}
.blocking-span{
  display: block;
}
.blocking-span input{
  border: 1px solid #eaeaea;
  height: 80px;
  padding-top: 30px;
  padding-left: 20px;
  padding-right: 20px;
  width: 100%;
}
.floating-label{
  display: inline-block;
  font-size: 15px;
  left: 20px;
  line-height: 20px;
  position: absolute;
  top: -webkit-calc(50% - 10px);
  top: -moz-calc(50% - 10px);
  top: calc(50% - 10px);
  transition: top 0.3s ease-in-out 0s;
}
.foucs-content .floating-label{
  top: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="parents-elm">
  <span class='blocking-span'>
  <input type="text" class="inputText" />
  </span>
  <span class="floating-label">Your email address</span>
</div>
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Rahul
  • 2,011
  • 3
  • 18
  • 31