「日付入力フォームを作ってほしい」
あなたはそう言われたら、どうやって実装しますか?
HTML5になって追加された「input[type=date]」を使うでしょうか。それともプラグインを使うのでしょうか。
どちらにも一長一短があり、設置するサイトの目的に応じて柔軟に対応することが求められます。
だがしかし!この日付入力フォームのカスタマイズはなかなか曲者でして、苦戦している方も少なくないでしょう。
Chromeではうまく表示されても、IEでうまくいなかったり、ちょっと見た目をいじったら動かなくなってしまったり。
今回はそんな悩める日付入力難民の皆様のために、日付入力フォームをどんな端末から見ても同じ見た目・動きになるようカスタマイズする方法について書きました。少しでもお役に立てればなによりでございます。
※結論から言うと「日付入力フォームのカスタマイズなら、プラグイン(datepicker)がおすすめ」でして、手っ取り早くカスタマイズ方法を知りたい場合はこちらから飛んじゃってください。全部読んでくれたほうが嬉しいですけどね!!
「わざわざjQueryを使うのも面倒なんだけど、簡単にカスタマイズできる範囲で調整したい」「むしろHTML/CSSの限界に挑みたい」という方はこのままスクロールして読み進めていただければと思います。
目次
日付入力フォームの実装方法
冒頭でさらっと書きましたが、日付入力フォームを実装する方法には2種類あります。
ひとつめが「input[type=date]」を使う方法、ふたつめがプラグインを使う方法です。
まずは、ひとつめの「input[type=date]」で日付入力できるようにしてみましょう。
input[type=date]での日付入力フォームの実装
以下のように書きます。通常のinputタグと書き方は一緒ですね。
1 2 3 | <input name="date" type="date" /> |
実際のものがこちら↓。クリックしてみてください!
ブラウザによって変わりますが、基本的に「年月日」と書かれたテキストボックスのようなものが表示され、それをクリックするとカレンダーが出てくる…という動きになります。
input[type=date]は他のinputタグ同様、オプションを設定することができます。主なものをご紹介します。
value: 送信される値
max: 入力可能な最大値
min: 入力可能な最小値
readonly: 読み取り専用にする
required: 入力必須にする
step: 入力欄で刻む値を指定
requiredを設定すると、プラグインを入れたり特別な処理をしたりすることなく、必須チェックが行われます。
stepで、入力できる日付の間隔を設定でき、初期値は1で、2に設定すれば2日ごとで入力できることになります。
各ブラウザでのinput[type=date]の見え方
先ほどinput[type=date]はブラウザによって見た目が変わると書きましたが、この「ブラウザによって変わる」というのがものすごく曲者なのです。実際にどのくらい違うのかお見せしましょう(※お使いの端末・ブラウザのバージョンによって本記事と違う場合がありますがご了承ください)。
まずは左から順にChrome・Firefox・Edgeです。
Chrome、Firefoxならフォームをクリックすれば直感的に日付を選択できますね。Edgeはスライドボックスで選ぶ方式ですが、これもスムーズに選べるでしょう。
それではスマホではどんなふうに見えるのでしょうか。iOSとAndroid(Chrome)で確認してみましょう。
上の空白になっているボタンが初期状態で、タップするとiOSでは画面下部に、Androidでは全面にモーダルが出てきます。どちらもカレンダー入力ではなくスライドになっていますが、画面が小さいモバイル端末であれば、むしろスライドのほうがスムーズに日付を選べるでしょう。
ただ、初期状態で文字が何も表示されないのは考え物ですね…。
「えっ?IEとSafariがない」そう思った方もいるでしょう。どうぞご覧ください。
そうなんです、「何も表示されない」のです。正確にいうと、この2ブラウザはinput[type=date]に非対応なので、input[type=text]として扱われてしまうのですね。HTML5で追加されたinput[type~]はいろいろありますが、非対応のものはテキストボックスとして扱われます。
input[type=date]の問題点
では、ブラウザによって見た目が違うとどんな問題が起こるのでしょうか。
もし非対応ブラウザで、テキストボックスから日付を入力した場合、ユーザーが打ち間違ってしまって正しいデータを得られないということが起こりえます。
そうでなくても、日付の表記は世界的に統一されておらず、ざっと上げただけでも以下のようなパターンがあります。
- ・ddmmyyyy
- ・mm/dd/yyyy
- ・dd-mm-yyyy
例えばmm/dd/yyyyで入力したユーザーと、dd/mm/yyyyで入力したユーザーがいた場合に「月」と「日」が逆になってしまうこともありえます。
また、カレンダー選択ではありえない「8月33日」なんて数値を入力することも、テキスト入力であればできてしまいます。
これがinput[type=date]に対応していないブラウザの問題点のひとつです。対応ブラウザであればカレンダーあるいはスライドで直感的に選べ、「形式が違う」ということはありえないですものね。
そこで、input[type=date]を使う場合は「非対応ブラウザからアクセスしたユーザーにどうやって正しいデータを入力してもらうか」が重要になってきます。次はその点も含めてinput[type=date]のカスタマイズ方法をお伝えします。
input[type=date]のカスタマイズ方法(PCブラウザ対応編)
前の段落で、input[type=date]は
・非対応ブラウザでは「input[type=text]」として扱われる
・非対応ブラウザでは入力形式がユーザーまかせになり、期待していたデータを取得できない可能性がある
ということを説明しました。
まずはプラグインなどを使用せず、HTML/CSSだけでこれらを解決するカスタマイズについて考えていきましょう。
対応ブラウザでの見た目を揃えてみよう
ここではChromeを例にして、カスタマイズしていきます。
↑ どこかで見たことのあるキャッチフレーズとボタンを添えてみました
仕様としては、以下のようにします。
・カエルのアイコンをクリックするとカレンダーが表示される
・ボックス部分をクリックしてもカレンダーが表示される
まずHTMLを書きましょう。
1 2 3 | <label class="date-edit"><input type="date" value="2019-08-22" /></label> |
inputをlabelで囲います。optionはお好みで。
今回は初期値として今日の日付を入れておきましょう。なおvalueが未入力だと「年/月/日」「yyyy/mm/dd」といった表示になります。
続いてCSSです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //labelタグ .date-edit { position: relative; } //ボタン部分 .date-edit::before { background: url(../img/now.png) no-repeat center center / cover #F7D94C; border: solid 5px #cdcdcd; content: ""; position: absolute; top: -15px; right: -65px; border-radius: 28px; height: 50px; width: 50px; } //ボックス部分 input[type="date"] { padding: 10px; text-align: center; } |
ポイントがあるとするならば、ボタンをあえて疑似要素で作成しているところでしょうか。なぜbuttonタグなどで作らないのか、その理由は後ほどわかるでしょう…!
現時点だとこんな感じ。続いて「▼」「▲」のボタン類を非表示にします。そのためにはCSSで設定を変える必要があるのですが…、
これらのパーツって、検証ツールで探しても見つけられないんですよね。
Chromeの場合はデフォルトでブラウザ定義の要素を選択できないようになっています。そんなときは検証ツールの設定を変更すれば大丈夫です。
検証ツールの右上にある「…」が縦向きになったアイコンをクリック→「Settings」→「Show user agent shadow DOM」にチェックを入れる
こうすると無事に要素を選択できるようになります。
「×」が#clear、「上下の矢印」が#spin、右端の「▼」が#pickerです。それぞれ以下の役割があります。
#spin:クリックすると矢印キーで前後の値を選べる
#picker:クリックするとカレンダーが開く
カレンダーを開く#pickerは使いたいので今回は#clearと#spinを非表示にします。CSSを追記しましょう。
1 2 3 4 5 6 7 8 | input[type="date"]::-webkit-inner-spin-button{ -webkit-appearance: none; } input[type="date"]::-webkit-clear-button{ -webkit-appearance: none; } |
ポイントなのは、要素を指定するときにIDではなく「pseudo=”-webkit~”」の部分を書いているところです。「pseudo」というのは英語で「疑似」という意味なので、「この要素は疑似クラスだよ~!」と言っている、くらいに思うといいでしょう。また、display:none;などではなく-webkit-appearanceを使うのもミソですね。
だいぶすっきりした印象になりました。いよいよ「▼」に手を付けます!さらにCSSを追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | input[type="date"]::-webkit-calendar-picker-indicator{ position: absolute; left: 0; top: 0; bottom: 0; margin: auto; padding: 0; background: transparent; color: transparent; cursor: pointer; height: 50px; width: 180px; } |
ここでのポイントは背景画像と文字色を透明にしている点です。指定がないと、こうなります。
つまり、透明なボタンを押すことでカレンダーを表示させているのです。そのため実際に押すボタン部分は見た目さえボタンであればよかったのですね。
ちなみに、ボタンあるいはボックス部分をクリックしたときだけ、カレンダーを表示させたいという場合は、透明ボタンの領域を調整してそれぞれの領域にかぶせてください。
ところが!この状態だとFirefoxで開いたときに「×」ボタンが残ってしまいます。
現在CSSによって、Firefoxで「×」を確実に消す方法は見つかっていないようです。エンジニア版Yahoo知恵袋のようなサービスであるstackoverflowでは以下のような方法が紹介されています。
1 2 3 4 5 6 7 8 9 10 11 12 | @-moz-document url-prefix() { //Firefoxだけに適用させる input[type="time"]{ clip-path: inset(0 25px 0 0); border: none; outline:none; outline:0; } } |
clip-path: inset(0 25px 0 0);で、×ボタンがある箇所をトリミングしています。そうするとborderが不自然に残ってしまうので、border/ outlineプロパティでinput要素の枠を非表示にしているというわけです。
ただし、この方法を提示した方も「完璧な方法ではない」と断ったうえで書いています。
ちなみに「どうしても枠を付けたい!」ということであればlabelタグの中にspan要素などを追加して、疑似的にボーダーを作るといいでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @-moz-document url-prefix() { //Firefoxだけに適用させる .date-edit span { position: relative; } .date-edit span::before { content: ""; border: solid 1px #cdcdcd; height: 26px; width: 110px; position: absolute; top: 0px; left: 0px; z-index: 1; margin: auto; bottom: 0; } } |
ただ、ご覧のようにCSSの記述量がかなり増えてしまうので、Firefoxでは×ボタンが表示されていてもいいや!と割り切るのもいいかもしれません。
非対応ブラウザ(mac版Safari、IE)での対応
例えば、上記で作ったパーツをIEで見ると以下のようになります。
カエルさんをクリックすると、テキスト部分にカーソルが入ります。valueに値が入っているので「こんな風に入れればいいんだな!」という助けにもなります。
ですが、より確実に正しい値を入力させるためにpattern属性を入れることをおすすめします。日付の場合はこんな感じです。
yyyy/mm/ddにしたいなら「-」を「/」に変えるなど適宜修正してみてください。
あるいは、非対応ブラウザの際はセレクトボックスで選ばせるようにするのも手かもしれません。
「年」(用途に応じて必要な年数は決まっている)や「日」(月によって月末日が違う)はJavascriptなどで動的に出すのがよいでしょう。
input[type=date]のカスタマイズ方法(SPブラウザ対応編)
さて、ここまででinput[type=date]タグの見た目を(できる限り)対応ブラウザで揃え、非対応ブラウザでも可能な限り入力をスムーズにする方法を考えてきました。
それではSPで見た場合はどうでしょう。先ほどカスタマイズしたボタンは以下のように見えます。以下画面はSafari(iOS)の画面ですが、Androidもスライドボックスの見た目は違えど同じ挙動をしています。
valueで具体的な日付を入れているためこのような表示になりますが、valueを「yyyy-mm-dd」と変更してみると・・・?
何も表示されなくなってしまいました。
対処法としては、テキストで疑似的にプレースホルダーを作成し、セレクトボックスに重ねるのがベストでしょう。フォーカスされているときと値が入っているときはJSで非表示にすれば大丈夫です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** HTML */ <label class="date-edit"> <span id="placeholder">年 / 月 / 日</span> <input type="date" value="yyyy-mm-dd" /> </label> /** JavaScript */ $('input[type=date]').on('focus', function() { $('#placeholder').hide(); }).on('blur', function() { var val = $(this).val(); if (!val) { $('#placeholder').show(); } }); |
これでわかりやすくなりました。
日付入力フォームの見た目を全ブラウザ対応する方法
これまではinput[type=date]を使用して日付入力フォームを作成する方法を説明してきました。
とはいえ「IEでもカレンダー表示にしたい!」「ブラウザごとにいちいちカスタマイズするなんて面倒くさい!」という方にはプラグインを使う方法がおすすめです。
datepickerとは?特徴と選び方について
「datepicker」とは、ざっくりいうと日付入力フォームの作成に特化したプラグインのことです。IEやmac版Safariなどのinput[type=date]非対応ブラウザでも問題なく使用できます。また、自分でCSSを書かずともデザインされたカレンダーを使えるのも大きなメリットではないでしょうか。
見た目やどのくらいカスタマイズできるかなど細かい違いがあり、好きなものを選んで大丈夫です。今回はjQueryUIのdatepickerを使ってカスタマイズしてみます。
jQueryUI以外のdatepickerはどんなものがあるのかな?と気になる方は以下のサイトを覗いてみるといいでしょう。
参考:結局、どのdatepickerが一番使い勝手がよいのか
jQueryUI datepickerを使ったカスタマイズ・基本編
jQueryUIで提供されているdatepickerはシンプルなデザインと日本語化できるのが特徴です。「datepicker」と検索すれば上位の情報がほとんどjQueryUIなくらいネット上にも情報が比較的たくさんあるので、カスタマイズする際つまずいても対処しやすいのではないでしょうか。
↑ デザインに強いこだわりがないのであればjQueryUIを選ぶのがおすすめです。
datepickerを導入する
さっそくdatepickerを導入してみましょう。公式サイトからダウンロードする方法と、URL指定で利用する方法の2通りがあります。URL指定の場合は以下のコードを追記すればOKです。
1 2 3 | <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> |
CSSとJSファイルを設置して、datepickerを表示させるにはinputタグを用意し、jsでメソッドを呼べば簡単にカレンダー表示を実現することができます!
1 2 3 4 5 6 7 | /** HTML */ <input id="datepicker" type="text" /> /** javascript */ $('#datepicker').datepicker(); |
クリックすると以下のような感じになります。
datepickerのテーマを変更する
デフォルトのデザインから変えたい場合は、こちらのソースを追記します。今回は”le-frog”というテーマを選びましたが、お好みに合わせて適宜変更してみてください。
1 2 3 | <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> |
公式サイトの左側メニュー「Gallery」タブを選択するとテーマ一覧を確認することができます。
jQueryUI datepickerを使ったカスタマイズ・応用編
datepickerを日本語化する
datepickerはデフォルトだとmm/dd/yyyy形式になっており、日本人にはあまり見慣れない表示になっています。また月や曜日も英語表記なので英語が苦手な人には使いにくく感じるかもしれません。そこで、datepickerを日本語化してみましょう。
まず、以下のサイトから「datepicker-ja.js」をダウンロードします。
「Raw」をクリックして「名前をつけて保存」すると、当該のファイルだけをDLできます。あとは配置するだけ。
1 2 3 | <script src="/js/datepicker-ja.js"></script> |
jquery-uiを読み込んだ後に配置しましょう。じゃないとエラーになってしまいます。
日本語化するとこの通り。カレンダーも入力後の日付もわかりやすくなりました。
では気になる見た目はいかがでしょうか。
どれもほぼ同じ見た目になっていますね!
SafariもiOS、macともに問題なさそうです。
datepickerのオプションを設定する
jQueryUI datepickerでは豊富なオプションが用意されており、カスタマイズの自由度が高いのも魅力です。ここでは使用頻度が高そうなオプションをいくつかご紹介しましょう。
日付の後ろに追加できる文字を指定できます。
buttonImage:
ボタン画像を指定できます。
changeMonth:(true / false)
月をドロップダウンで選択するかどうか選べます。Yearにすると年のオプションになります。
firstDay:(Integer)
週の始まりを指定します。0(日曜日)~6(土曜日)までの数字をセットします。
monthNames:(Array)
月名のリストを作成し指定します。略称を設定したい場合はmonthNamesShortを使います。
dateFormat:
年月日表示のフォーマットを設定できます。初期値は”mm/dd/yy”です。
オプションを指定したい場合はdatepicker()の中に{}を入れ、その中にオプションを記述していきます。複数のオプションを指定する場合は”,”が必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | $('#datepicker').datepicker({ changeMonth: true, dateFormat: "yy年mm月dd日DD曜日", monthNamesShort: [ "睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走" ] }); |
かなり柔軟にカスタマイズできるので、皆様ぜひお試しください!
どんなオプションを指定できるかは、こちらのサイトが参考になります。
日付入力フォームのカスタマイズでハマったこと、気を付けるポイント
カスタマイズもしやすくて、とっても心強いdatepickerですが、お客様の要望にあれこれ対応しようとすると、なかなかうまくいかないことだってあります。ここでは筆者が実際にハマったポイントと解決策を共有したいと思います。
datepickerを含む要素を追加したいのに、うまく追加できなかった
とある案件で、datepickerをセットした要素を作成し、追加ボタンを押すと同じものがクローンされるという仕様のものを作りました。
ところが追加された要素をクリックしてもカレンダーが表示されないのです。
原因は、追加された要素ではdatepickerメソッドが発動しておらず、動的に要素を追加した場合はそれに対して再度datepicker()を呼ぶ必要があったためでした。
ソースを以下のように変更してみると、無事に動きました。
1 2 3 4 5 6 7 8 9 10 11 12 13 | /** javascript */ var currentDate = new Date(); $('body').on('click','.datepicker,label',function(){ var dateID = $(this).datepicker( { //datepickerでオプションを指定したい場合は記述 }); currentDate = $(this).val(); $(this).datepicker('setDate', currentDate); $(this).datepicker('show'); }); |
大事なのが最初にcurrentDateという変数を用意して、最後のほうでsetDateを使ってセットしているところです。
この工程を飛ばすとエラーになってしまいshowメソッドを呼び出せませんでした。
showメソッドを書かないと、一度目のクリックで反応してくれません。
ところが、旧バージョン(5.X)で動くのは確認できたのですが、Android7.0で動かないのです・・・。情報求!
日付だけでなく時間も選べるようにしたい
ちなみにメール配信のスケジュールなどで「年月日だけでなく時間も選びたい」という場合もあるでしょう。そんなときはdatetimepickerを使えば大丈夫です。
こちらのサイトから「build/jquery.datetimepicker.min.css」と「build/jquery.datetimepicker.full.min.js」をダウンロードしましょう。
使い方はdatepickerとほぼ同じです。詳しい使い方や見た目の例は公式サイトを確認してみてください。
まとめ
今回は日付入力フォームのカスタマイズについて解説してきました。現状では、全ブラウザで同じ見た目を再現するにはdatepickerなどのプラグインを使うのが一番の近道のようです。
ただAndroid7.0でうまく動作しなかったことなど、バージョンやデバイスによっても動かない部分があるようなので、コーディングする場合はクライアントさんと相談して「どのブラウザのどのバージョンまで対応するか」「どういう動き(結果)が得られればいいのか」を鑑みて実装していきましょう。
日付入力フォームの実装をしたサイトを作りたいけど、自分で作るのはちょっと自信がない、大変そうだ…という方は
弊社へお気軽にご連絡ください。制作実績も多数あります!
サイト制作について相談してみる