[html] Not showing placeholder for input type="date" field

I am doing a phonegap app. When I am trying type="date" input field as shown below, it shows date picker in iPhone as I expected but it doesn't show the placeholder I have given. I found the same issue here in SO, but no solution anywhere.

 <input placeholder="Date" class="textbox-n" type="date" id="date">

This question is related to html cordova datepicker placeholder

The answer is


I took jbarlow idea, but I added an if in the onblur function so the fields only change its type if the value is empty

<input placeholder="Date" class="textbox-n" type="text" onfocus="(this.type='date')" onblur="(this.value == '' ? this.type='text' : this.type='date')" id="date">

I'm surprised there's only one answer with an approach similar to the one I used.
I got the inspiration from @Dtipson's comment on @Mumthezir VP's answer.

I use two inputs for this, one is a fake input with type="text" on which I set the placeholder, the other one is the real field with type="date".
On the mouseenter event on their container, I hide the fake input and show the real one, and I do the opposite on the mouseleave event. Obviously, I leave the real input visibile if it has a value set on it.
I wrote the code to use pure Javascript but if you use jQuery (I do) it's very easy to "convert" it.

_x000D_
_x000D_
// "isMobile" function taken from this reply:_x000D_
// https://stackoverflow.com/a/20293441/3514976_x000D_
function isMobile() {_x000D_
  try { document.createEvent("TouchEvent"); return true; }_x000D_
  catch(e) { return false; }_x000D_
}_x000D_
_x000D_
var deviceIsMobile = isMobile();_x000D_
_x000D_
function mouseEnterListener(event) {_x000D_
  var realDate = this.querySelector('.real-date');_x000D_
  // if it has a value it's already visible._x000D_
  if(!realDate.value) {_x000D_
    this.querySelector('.fake-date').style.display = 'none';_x000D_
    realDate.style.display = 'block';_x000D_
  }_x000D_
}_x000D_
_x000D_
function mouseLeaveListener(event) {_x000D_
  var realDate = this.querySelector('.real-date');_x000D_
  // hide it if it doesn't have focus (except_x000D_
  // on mobile devices) and has no value._x000D_
  if((deviceIsMobile || document.activeElement !== realDate) && !realDate.value) {_x000D_
    realDate.style.display = 'none';_x000D_
    this.querySelector('.fake-date').style.display = 'block';_x000D_
  }_x000D_
}_x000D_
_x000D_
function fakeFieldActionListener(event) {_x000D_
  event.preventDefault();_x000D_
  this.parentElement.dispatchEvent(new Event('mouseenter'));_x000D_
  var realDate = this.parentElement.querySelector('.real-date');_x000D_
  // to open the datepicker on mobile devices_x000D_
  // I need to focus and then click on the field._x000D_
  realDate.focus();_x000D_
  realDate.click();_x000D_
}_x000D_
_x000D_
var containers = document.getElementsByClassName('date-container');_x000D_
for(var i = 0; i < containers.length; ++i) {_x000D_
  var container = containers[i];_x000D_
  _x000D_
  container.addEventListener('mouseenter', mouseEnterListener);_x000D_
  container.addEventListener('mouseleave', mouseLeaveListener);_x000D_
  _x000D_
  var fakeDate = container.querySelector('.fake-date');_x000D_
  // for mobile devices, clicking (tapping)_x000D_
  // on the fake input must show the real one._x000D_
  fakeDate.addEventListener('click', fakeFieldActionListener);_x000D_
  // let's also listen to the "focus" event_x000D_
  // in case it's selected using a keyboard._x000D_
  fakeDate.addEventListener('focus', fakeFieldActionListener);_x000D_
  _x000D_
  var realDate = container.querySelector('.real-date');_x000D_
  // trigger the "mouseleave" event on the_x000D_
  // container when the value changes._x000D_
  realDate.addEventListener('change', function() {_x000D_
    container.dispatchEvent(new Event('mouseleave'));_x000D_
  });_x000D_
  // also trigger the "mouseleave" event on_x000D_
  // the container when the input loses focus._x000D_
  realDate.addEventListener('blur', function() {_x000D_
    container.dispatchEvent(new Event('mouseleave'));_x000D_
  });_x000D_
}
_x000D_
.real-date {_x000D_
  display: none;_x000D_
}_x000D_
_x000D_
/* a simple example of css to make _x000D_
them look like it's the same element */_x000D_
.real-date, _x000D_
.fake-date {_x000D_
  width: 200px;_x000D_
  height: 20px;_x000D_
  padding: 0px;_x000D_
}
_x000D_
<div class="date-container">_x000D_
  <input type="text" class="fake-date" placeholder="Insert date">_x000D_
  <input type="date" class="real-date">_x000D_
</div>
_x000D_
_x000D_
_x000D_

I tested this also on an Android phone and it works, when the user taps on the field the datepicker is shown. The only thing is, if the real input had no value and the user closes the datepicker without choosing a date, the input will remain visible until they tap outside of it. There's no event to listen to to know when the datepicker closes so I don't know how to solve that.

I don't have an iOS device to test it on.


Im working with ionicframework and solution provided by @Mumthezir is almost perfect. In case if somebody would have same problem as me(after change, input is still focused and when scrolling, value simply dissapears) So I added onchange to make input.blur()

<input placeholder="Date" class="textbox-n" type="text" onfocus=" (this.type='date')" onchange="this.blur();"  id="date"> 

From Angular point of view I managed to put a placeholder in input type date element.

First of all I defined the following css:

.placeholder {
    color: $text-grey;
  }

  input[type='date']::before {
    content: attr(placeholder);
  }

  input::-webkit-input-placeholder {
    color: $text-grey;
  }

The reason why this is neccessary is that if css3 content has different color that the normal placeholder, so I had to use a common one.

<input #birthDate
         class="birthDate placeholder"
         type="date"
         formControlName="birthDate"
         placeholder="{{getBirthDatePlaceholder() | translate}}"
         [class.error]="!onboardingForm.controls.birthDate.valid && onboardingForm.controls.birthDate.dirty"
         autocomplete="off"
         >

Then in the template used a viewchild birthDate attribute, to be able to access this input from the component. And defined an angular expression on the placeholder attribute, which will decide if we show the placeholder or not. This is the major drawback of the solution, is that you have to manage the visibility of the placeholder.

@ViewChild('birthDate') birthDate;

getBirthDatePlaceholder() {
  if (!this.birthDate) {
    return;
  } else {
    return this.birthDate.nativeElement.value === '' ?
    'ONBOARDING_FORM_COMPONENT.HINT_BIRTH_DATE' :
    '';
  }
}

Expanding on @mvp's solution with unobtrusive javascript in mind, here's the approach:

HTML:

<input type="text" placeholder="Date" class="js-text-date-toggle">

Javascript:

$('.js-text-date-toggle').on('focus', function() {
  $(this).attr('type', 'date') }
).on('blur', function() {
  $(this).attr('type'), 'text') }
)

According to the HTML standard:

The following content attributes must not be specified and do not apply to the element: accept, alt, checked, dirname, formaction, formenctype, formmethod, formnovalidate, formtarget, height, inputmode, maxlength, minlength, multiple, pattern, placeholder, size, src, and width.


I ended up using the following.

Regarding Firefox comment(s): Generally, Firefox will not show any text placeholder for inputs type date. But as this is a Cordova/PhoneGap question this should be of no concern (Unless you want to develop against FirefoxOS).

_x000D_
_x000D_
input[type="date"]:not(.has-value):before{_x000D_
  color: lightgray;_x000D_
  content: attr(placeholder);_x000D_
}
_x000D_
<input type="date" placeholder="MY PLACEHOLDER" onchange="this.className=(this.value!=''?'has-value':'')">
_x000D_
_x000D_
_x000D_


If you use mvp's method but add the onblur event to change it back to a text field so the placeholder text appears again when the input field looses focus. It just makes the hack a little bit nicer.

_x000D_
_x000D_
<input placeholder="Date" class="textbox-n" type="text" onfocus="(this.type='date')" onblur="(this.type='text')" id="date" />
_x000D_
_x000D_
_x000D_

Hope this helps.


I used this in my css:

input[type="date"]:before{
    color:lightgray;
    content:attr(placeholder);
}

input[type="date"].full:before {
    color:black;
    content:""!important;
}

and put somenthing like this into javascript:

$("#myel").on("input",function(){
    if($(this).val().length>0){
    $(this).addClass("full");
}
else{
   $(this).removeClass("full");
   }
 });

it works for me for mobile devices (Ios8 and android). But I used jquery inputmask for desktop with input text type. This solution it's a nice way if your code run on ie8.


Adressing the problem in the current correct answer "clicking the field shows the onscreen keyboard instead of the datepicker":

The problem is caused by the Browser behaving according to the type of input when clicking (=text). Therefore it is necessary to stop from focussing on the input element (blur) and then restart focus programmatically on the input element which was defined as type=date by JS in the first step. Keyboard displays in phonenumber-mode.

<input placeholder="Date" type="text" onfocus="this.type='date';
                      this.setAttribute('onfocus','');this.blur();this.focus();">

I think all you have to do is change the model to say the date field is nullable and then put [Required] on it if it is required. If you do this the placeholder text does appear.


Found a better way to solve your problem. I think this will help you. when focused out, the box will change type into text so it will show your placeholder. when focused in, its type changes into date so the calendar view will be shown.

<input placeholder="Date" class="textbox-n" type="text" onfocusin="(this.type='date')" onfocusout="(this.type='text')"  id="date"> 

Hey so I ran into the same issue last night and figured out a combination of all of your answer and some sparkling magic are doing a good job:

The HTML:

<input type="date"  name="flb5" placeholder="Datum"     class="datePickerPlaceHolder"/>

The CSS:

@media(max-width: 1024px) {
   input.datePickerPlaceHolder:before {
      color: #A5A5A5; //here you have to match the placeholder color of other inputs
      content: attr(placeholder) !important;
   }
}

The jQuery:

$(document).ready(function() {
    $('input[type="date"]').change(function(){
            if($(this).val().length < 1) {
                $(this).addClass('datePickerPlaceHolder');
            } else {
                $(this).removeClass('datePickerPlaceHolder');
            }
    });
});

Explanation: So, what is happening here, first of all in the HTML, this is pretty straight forward just doing a basic HMTL5-date-input and set a placeholder. Next stop: CSS, we are setting a :before-pseudo-element to fake our placeholder, it just takes the placeholder's attribute from the input itself. I made this only available down from a viewport width of 1024px - why im going to tell later. And now the jQuery, after refactoring a couple of times I came up with this bit of code which will check on every change if there is a value set or not, if its not it will (re-)add the class, vice-versa.

KNOW ISSUES:

  • there is a problem in chrome with its default date-picker, thats what the media-query is for. It will add the placeholder infront of the default 'dd.mm.yyyy'-thing. You could also set the placeholder of the date-input to 'date: ' and adjust the color incase of no value inside the input...for me this resulted in some other smaller issues so i went with just not showing it on 'bigger' screens

hope that helps! cheerio!


try my solution. I use 'required' attribute to get know whether input is filled and if not I show the text from attribute 'placeholder'

//HTML
<input required placeholder="Date" class="textbox-n" type="date" id="date">

//CSS
input[type="date"]:not(:valid):before {
   content: attr(placeholder);
   // style it like it real placeholder
}

HTML:

<div>
    <input class="ui-btn ui-btn-icon-right ui-corner-all ui-icon-calendar ui-shadow" id="inputDate" type="date"/>
    <h3 id="placeholder-inputDate">Date Text</h3>
</div>

JavaScript:

$('#inputDate').ready(function () {
$('#placeholder-inputDate').attr('style'
    , 'top: ' + ($('#placeholder-inputDate').parent().position().top + 10)
    + 'px; left: ' + ($('#placeholder-inputDate').parent().position().left + 0) + 'px; position: absolute;');
$('#inputDate').attr('style'
    , 'width: ' + ($('#placeholder-inputDate').width() + 32) + 'px;');
});

If you're only concerned with mobile:

input[type="date"]:invalid:before{
    color: rgb(117, 117, 117);
    content: attr(placeholder);
}

I used this whit jQuery: http://jsfiddle.net/daviderussoabram/65w1qhLz/

$('input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="month"], input[type="time"], input[type="week"]').each(function() {
    var el = this, type = $(el).attr('type');
    if ($(el).val() == '') $(el).attr('type', 'text');
    $(el).focus(function() {
        $(el).attr('type', type);
        el.click();
    });
    $(el).blur(function() {
        if ($(el).val() == '') $(el).attr('type', 'text');
    });
});

SO what i have decided to do finally is here and its working fine on all mobile browsers including iPhones and Androids.

_x000D_
_x000D_
$(document).ready(function(){_x000D_
_x000D_
  $('input[type="date"]').each(function(e) {_x000D_
    var $el = $(this), _x000D_
        $this_placeholder = $(this).closest('label').find('.custom-placeholder');_x000D_
    $el.on('change',function(){_x000D_
      if($el.val()){_x000D_
        $this_placeholder.text('');_x000D_
      }else {_x000D_
        $this_placeholder.text($el.attr('placeholder'));_x000D_
      }_x000D_
    });_x000D_
  });_x000D_
  _x000D_
});
_x000D_
label {_x000D_
  position: relative;  _x000D_
}_x000D_
.custom-placeholder {_x000D_
    #font > .proxima-nova-light(26px,40px);_x000D_
    position: absolute;_x000D_
    top: 0;_x000D_
    left: 0;_x000D_
    z-index: 10;_x000D_
    color: #999;_x000D_
}
_x000D_
<label>_x000D_
  <input type="date" placeholder="Date">_x000D_
  <span class="custom-placeholder">Date</span>_x000D_
</label>
_x000D_
_x000D_
_x000D_

Date


To summarize the date inputs problem:

  • You have to display them (i.e. avoid display:none) otherwise the input UI will not be triggered ;
  • a placeholder is contradictory with them (as per the spec, and because they have to display a specific UI) ;
  • converting them to another input type for the unfocused time do allows placeholders, but focus then triggers the wrong input UI (keyboard), at least for a small time, because focus events cannot be cancelled.
  • inserting (before) or adding (after) content doesn't prevent the date input value to be displayed.

The solution I found to meet those requirements is to use the usual trick to style native form elements : ensure the element is displayed but not visible, and display its expected style through its associated label. Typically, the label will display as the input (including a placeholder), but over it.

So, an HTML like:

<div class="date-input>
  <input id="myInput" type="date"> 
  <label for="myInput"> 
    <span class="place-holder">Enter a date</span> 
  </label>
</div>

Could be styled as:

.date-input {
  display: inline-block;
  position: relative;
}
/* Fields overriding */
input[type=date] + label {
  position: absolute;  /* Same origin as the input, to display over it */
  background: white;   /* Opaque background to hide the input behind */
  left: 0;             /* Start at same x coordinate */
}

/* Common input styling */
input[type=date], label {  
  /* Must share same size to display properly (focus, etc.) */
  width: 15em;
  height: 1em;
  font-size: 1em;
}

Any event (click, focus) on such an associated label will be reflected on the field itself, and so trigger the date input UI.

Should you want to test such a solution live, you can run this Angular version from your tablet or mobile.


It works for me:

input[type='date']:after {
  content: attr(placeholder)
}

Here is another possible hack not using js and still using css content. Note that as :after is not supported on some browser for inputs, we need to select the input in another way, same for content attr('')

_x000D_
_x000D_
input[type=date]:invalid+span:after {_x000D_
  content:"Birthday";_x000D_
  position:absolute;_x000D_
  left:0;_x000D_
  top:0;_x000D_
}_x000D_
_x000D_
input[type=date]:focus:invalid+span:after {_x000D_
  display:none;_x000D_
}_x000D_
_x000D_
input:not(:focus):invalid {_x000D_
  color:transparent;_x000D_
}_x000D_
_x000D_
label.wrapper {_x000D_
 position:relative;_x000D_
}
_x000D_
<label class="wrapper">_x000D_
 <input_x000D_
    type="date"_x000D_
     required="required" _x000D_
 />_x000D_
 <span></span>_x000D_
</label>
_x000D_
_x000D_
_x000D_


You can

  1. set it as type text
  2. convert to date on focus
  3. make click on it
  4. ...let user check date
  5. on change store the value
  6. set input to type text
  7. set text type input value to the stored value

like this...

_x000D_
_x000D_
$("#dateplaceholder").change(function(evt) {_x000D_
  var date = new Date($("#dateplaceholder").val());_x000D_
  $("#dateplaceholder").attr("type", "text");_x000D_
  $("#dateplaceholder").val(date.getDate() + "/" + (date.getMonth() + 1) + "/" + date.getFullYear());_x000D_
});_x000D_
$("#dateplaceholder").focus(function(evt) {_x000D_
  $("#dateplaceholder").attr("type", "date");_x000D_
  setTimeout('$("#dateplaceholder").click();', 500);_x000D_
});_x000D_
$("#dateplaceholder").attr("type", "text");
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>_x000D_
<input type="date" id="dateplaceholder" placeholder="Set the date" />
_x000D_
_x000D_
_x000D_


Found a better way to handle user basic comprehension with mouseover and opening datepicker on click :

<input type="text" onfocus="(this.type='date')" onmouseover="(this.type = 'date')" onblur="(this.value ? this.type = 'date' : this.type = 'text')" id="date_start" placeholder="Date">

Also hide webkit arrow and make it 100% wide to cover the click :

input[type="date"] {
    position: relative;
}
input[type="date"]::-webkit-calendar-picker-indicator {
  position: absolute;
  height: 100%;
  width: 100%;
  opacity: 0;
  left: 0;
  right: 0;
  top:0;
  bottom: 0;
}

Took me a while figuring this one out, leave it as type="text", and add onfocus="(this.type='date')", just as shown above.

I even like the onBlur idea mentioned above

<input placeholder="Date" class="textbox-n" type="text" onfocus="(this.type='date')" onblur="(this.type='text')" id="date">

Hope this helps anyone who didn't quite gather whats going on above


As of today (2016), I have successfully used those 2 snippets (plus they work great with Bootstrap4).

Input data on the left, placeholder on the left

input[type=date] {
  text-align: right;
}

input[type="date"]:before {
  color: lightgrey;
  content: attr(placeholder) !important;
  margin-right: 0.5em;
}

Placeholder disappear when clicking

input[type="date"]:before {
  color: lightgrey;
  content: attr(placeholder) !important;
  margin-right: 0.5em;
}
input[type="date"]:focus:before {
  content: '' !important;
}

Based on deadproxor and Alessio answers, I would try only using CSS:

input[type="date"]::before{
    color: #999;
    content: attr(placeholder) ": ";
}
input[type="date"]:focus::before {
    content: "" !important;
}

And if you need to make the placeholder invisible after writing something in the input, we could try using the :valid and :invalid selectors, if your input is a required one.

EDIT

Here the code if you are using required in your input:

_x000D_
_x000D_
input[type="date"]::before {_x000D_
 color: #999999;_x000D_
 content: attr(placeholder);_x000D_
}_x000D_
input[type="date"] {_x000D_
 color: #ffffff;_x000D_
}_x000D_
input[type="date"]:focus,_x000D_
input[type="date"]:valid {_x000D_
 color: #666666;_x000D_
}_x000D_
input[type="date"]:focus::before,_x000D_
input[type="date"]:valid::before {_x000D_
 content: "" !important;_x000D_
}
_x000D_
<input type="date" placeholder="Date" required>
_x000D_
_x000D_
_x000D_


This works for me using this as input element:

<input name="birthdate" class="" class="wpcf7-form-control wpcf7-date 
 wpcf7-validates-as-required wpcf7-validates-as-date birthdate" value="" 
 aria-required="true" aria-invalid="false" placeholder="birthdate *" 
 type="date">

This CSS shows a permanent placeholder. The selected value is shown after the placeholder.

input[type="date"]:before {
    content: attr(placeholder) !important;
    margin-right: 0.5em;
    display: block;
}
/* only for FF */
@-moz-document url-prefix() {
    input[type="date"]:before {
        content: attr(placeholder) !important;
        margin-right: 0.5em;
        display: block;
        position: absolute;
        left: 200px; /* please adopt */
    }
}

I use this solution for a Wordpress form with contact-form-7 plugin.


Extension of Mumthezir's version that works better on iOS, based on Mathijs Segers' comment:

(Uses some AngularJS but hopefully you get the idea.)

<label style='position:relative'>
    <input type="date" 
           name="dateField" 
           onfocus="(this.type='date')"
           ng-focus="dateFocus=true" ng-blur="dateFocus=false" />
    <span ng-if='!dateFocus && !form.date' class='date-placeholder'>
        Enter date
    </span>
</label>

Because it's all wrapped in a label, clicking the span automatically focuses the input.

CSS:

.date-placeholder {
    display: inline-block;
    position: absolute;
    text-align: left;
    color: #aaa;
    background-color: white;
    cursor: text;
    /* Customize this stuff based on your styles */
    top: 4px;
    left: 4px;
    right: 4px;
    bottom: 4px;
    line-height: 32px;
    padding-left: 12px;
}

_x000D_
_x000D_
<input placeholder="Date" type="text" onMouseOver="(this.type='date')" onMouseOut="(this.type='text')"  id="date" class="form-control">
_x000D_
_x000D_
_x000D_

Revised code of mumthezir


You could use the "value" attribute, for example:

<input type="date" value="Date" class="textbox-n" id="date"/>

None of the solutions were working correctly for me on Chrome in iOS 12 and most of them are not tailored to cope with possible multiple date inputs on a page. I did the following, which basically creates a fake label over the date input and removes it on tap. I am also removing the fake label if viewport width is beyond 992px.

JS:

function addMobileDatePlaceholder() {
    if (window.matchMedia("(min-width: 992px)").matches) {
        $('input[type="date"]').next("span.date-label").remove();
        return false;
    }

    $('input[type="date"]').after('<span class="date-label" />');

    $('span.date-label').each(function() {
        var $placeholderText = $(this).prev('input[type="date"]').attr('placeholder');
        $(this).text($placeholderText);
    });

    $('input[type="date"]').on("click", function() {
        $(this).next("span.date-label").remove();
    });
}

CSS:

@media (max-width: 991px) {
    input[type="date"] {
        padding-left: calc(50% - 45px);
    }

    span.date-label {
        pointer-events: none;
        position: absolute;
        top: 2px;
        left: 50%;
        transform: translateX(-50%);
        text-align: center;
        height: 27px;
        width: 70%;
        padding-top: 5px;
    }
}

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to cordova

Why am I seeing net::ERR_CLEARTEXT_NOT_PERMITTED errors after upgrading to Cordova Android 8? Xcode couldn't find any provisioning profiles matching Cordova app not displaying correctly on iPhone X (Simulator) JAVA_HOME is set to an invalid directory: ionic 2 - Error Could not find an installed version of Gradle either in Android Studio cordova Android requirements failed: "Could not find an installed version of Gradle" Error: Could not find gradle wrapper within Android SDK. Might need to update your Android SDK - Android Ionic 2: Cordova is not available. Make sure to include cordova.js or run in a device/simulator (running in emulator) Cordova : Requirements check failed for JDK 1.8 or greater Can't accept license agreement Android SDK Platform 24

Examples related to datepicker

Angular-Material DateTime Picker Component? $(...).datepicker is not a function - JQuery - Bootstrap Uncaught TypeError: $(...).datepicker is not a function(anonymous function) Get date from input form within PHP Angular bootstrap datepicker date format does not format ng-model value jQuery Datepicker close datepicker after selected date bootstrap datepicker setDate format dd/mm/yyyy bootstrap datepicker change date event doesnt fire up when manually editing dates or clearing date Clear the value of bootstrap-datepicker Disable future dates after today in Jquery Ui Datepicker

Examples related to placeholder

Keep placeholder text in UITextField on input in IOS HTML Input - already filled in text Add placeholder text inside UITextView in Swift? Bootstrap select dropdown list placeholder fail to change placeholder color with Bootstrap 3 Not showing placeholder for input type="date" field Use Font Awesome Icon in Placeholder How do I put hint in a asp:textbox How to support placeholder attribute in IE8 and 9 HTML5 image icon to input placeholder