Mobile + input[type="date"] + placeholder

Попалась в одном проекте, рассчитанном только на мобильные устройства, форма с различными полями, у которых есть плейсхолдеры. Одно из полей — дата. Конечно же, захотелось сделать это поле <input type="date">, чтобы и нативные дейтпикеры вызывались на устройствах, и не использовать какие бы то ни было плагины, регулярные выражения и пр. Но проблема в плейсхолдере, который для данного инпута не работает.

В процессе поиска было найдено несколько решений, но все они не подходили по разным причинам, работали не так, как надо. В итоге, методом проб и ошибок сделал свой вариант.

Все поля имели обёртку, и разметка выглядит примерно так:

<div class="field">
    <input type="date">
</div>

Немного стилизуем, сбрасывая дефолтные стили:

.field input[type="date"] {
    font-family: sans-serif;
	font-size: 14px;
    line-height: 20px;
    box-sizing: border-box;
    width: 100%;
    padding: 9px;
    color: #000;
    border: 1px solid #000;
    background: transparent;
    -webkit-appearance: none;
}

В результате, в Хроме (десктопном) получили что-то вроде этого:

input date

В мобильных устройствах этого «неизменяего плейсхолдера» (дд.мм.гггг) нет, лишь пустое поле.

Далее для обёртки создаётся псевдоэлемент, который и будет играть роль плейсхолдера:

.field {
    position: relative;
    background: #fff;
}

.field::before {
    font-family: sans-serif;
    font-size: 14px;
    line-height: 20px;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    padding: 10px;
    content: "Введите дату";
    color: #000;
}

То, что увидим на телефоне:

input date

Теперь надо добавить немного JS-магии. При любом изменении инпута проверяем, чему равно value. Если оно не является пустым, то задаём ему background: #fff, что спрячет псевдоэлемент родителя. В противном же случае меняем фон на прозрачный.

Но для срабатывания этой логики необходимо, чтобы инпут был над псевдоэлементом, поэтому добавляем инпуту position и z-index.

Ниже рабочий пример, который фигово смотрится в обычных браузерах, но отлично работает как на Андроидах, так и на Айосе.

UPD: А можно сделать проще. Делаем два инпута с разными типами:

<div class="field">
    <input type="text">
    <input type="date">
</div>

Первому задаём необходимый плейсхолдер и абсолютное позиционирование. Второму же ставим нулевую непрозрачность.
Далее при фокусе по input[type="date"] убираем прозрачность, а при необходимости (onblur, oninput) её возвращаем, проверяя value. Событие onblur нам нужно для мобильных, а oninput для десктопных браузеров, т. к. там после очистки поля фокус сохраняется, и onblur не срабатывает.

Получилось универсальнее, и на десктопе тоже работает.

P. S. А популярное решение с одним инпутом и сменой его типа при фокусе не является хорошим, поскольку на мобильных устройствах в данном случае не вызывается сразу нативный пикер, приходится делать повторный тап.

{{ message }}

{{ 'Comments are closed.' | trans }}