デートピッカー Date Picker

カレンダーUIから日付を選択するフォーム要素。

使用場面: 予約日時選択、期間指定、誕生日入力 採用例: Google Calendar, Booking.com

ライブデモ

ソースコード

<div class="demo-datepicker">
  <label class="demo-datepicker-label">日付を選択</label>
  <div class="demo-datepicker-input-wrap">
    <input class="demo-datepicker-input" type="text" placeholder="YYYY/MM/DD" readonly />
    <svg class="demo-datepicker-cal-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
  </div>
  <div class="demo-datepicker-calendar" style="display:none;">
    <div class="demo-datepicker-header">
      <button class="demo-datepicker-prev">&lsaquo;</button>
      <span class="demo-datepicker-month-year"></span>
      <button class="demo-datepicker-next">&rsaquo;</button>
    </div>
    <div class="demo-datepicker-weekdays">
      <span>日</span><span>月</span><span>火</span><span>水</span><span>木</span><span>金</span><span>土</span>
    </div>
    <div class="demo-datepicker-days"></div>
  </div>
</div>
.demo-datepicker { position: relative; max-width: 280px; }
.demo-datepicker-label { display: block; font-size: 13px; font-weight: 600; color: #333; margin-bottom: 6px; }
.demo-datepicker-input-wrap { position: relative; }
.demo-datepicker-input {
  width: 100%; padding: 10px 40px 10px 12px; border: 2px solid #d1d5db;
  border-radius: 8px; font-size: 14px; cursor: pointer; outline: none;
  transition: border-color 0.2s;
}
.demo-datepicker-input:focus { border-color: var(--ui-primary); }
.demo-datepicker-cal-icon { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); color: #999; pointer-events: none; }
.demo-datepicker-calendar {
  position: absolute; top: 100%; left: 0; margin-top: 4px;
  background: #fff; border: 1px solid #e5e7eb; border-radius: 12px;
  padding: 12px; box-shadow: 0 4px 16px rgba(0,0,0,0.1); z-index: 20; width: 260px;
}
.demo-datepicker-header {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;
}
.demo-datepicker-header button {
  background: none; border: none; font-size: 18px; cursor: pointer; color: var(--ui-primary);
  width: 28px; height: 28px; border-radius: 6px;
}
.demo-datepicker-header button:hover { background: color-mix(in srgb, var(--ui-primary) 10%, transparent); }
.demo-datepicker-month-year { font-size: 14px; font-weight: 600; color: #333; }
.demo-datepicker-weekdays {
  display: grid; grid-template-columns: repeat(7, 1fr); text-align: center;
  font-size: 11px; color: #999; margin-bottom: 4px;
}
.demo-datepicker-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center; }
.demo-datepicker-day {
  padding: 6px; font-size: 13px; border-radius: 6px; cursor: pointer;
  border: none; background: none; transition: background 0.15s;
}
.demo-datepicker-day:hover { background: color-mix(in srgb, var(--ui-primary) 10%, transparent); }
.demo-datepicker-day.today { font-weight: 700; color: var(--ui-primary); }
.demo-datepicker-day.selected { background: var(--ui-primary); color: #fff; }
.demo-datepicker-day.other-month { color: #ccc; }
(function(){
  const input = document.querySelector('.demo-datepicker-input');
  const cal = document.querySelector('.demo-datepicker-calendar');
  const daysEl = document.querySelector('.demo-datepicker-days');
  const monthYearEl = document.querySelector('.demo-datepicker-month-year');
  let current = new Date();
  let selected = null;
  function render() {
    const y = current.getFullYear(), m = current.getMonth();
    monthYearEl.textContent = y + '年' + (m+1) + '月';
    const first = new Date(y, m, 1).getDay();
    const last = new Date(y, m+1, 0).getDate();
    const today = new Date();
    let html = '';
    for (let i = 0; i < first; i++) html += '<span class="demo-datepicker-day other-month"></span>';
    for (let d = 1; d <= last; d++) {
      const isToday = d === today.getDate() && m === today.getMonth() && y === today.getFullYear();
      const isSel = selected && d === selected.getDate() && m === selected.getMonth() && y === selected.getFullYear();
      html += '<button class="demo-datepicker-day'+(isToday?' today':'')+(isSel?' selected':'')+'" data-day="'+d+'">'+d+'</button>';
    }
    daysEl.innerHTML = html;
    daysEl.querySelectorAll('.demo-datepicker-day[data-day]').forEach(btn => {
      btn.addEventListener('click', function() {
        selected = new Date(y, m, parseInt(this.dataset.day));
        input.value = selected.getFullYear()+'/'+ String(selected.getMonth()+1).padStart(2,'0')+'/'+ String(selected.getDate()).padStart(2,'0');
        cal.style.display = 'none';
        render();
      });
    });
  }
  input.addEventListener('click', function() { cal.style.display = cal.style.display === 'none' ? 'block' : 'none'; render(); });
  document.querySelector('.demo-datepicker-prev').addEventListener('click', function() { current.setMonth(current.getMonth()-1); render(); });
  document.querySelector('.demo-datepicker-next').addEventListener('click', function() { current.setMonth(current.getMonth()+1); render(); });
  document.addEventListener('click', function(e) { if (!e.target.closest('.demo-datepicker')) cal.style.display = 'none'; });
})();

AIプロンプト

Basic
デートピッカーをHTML/CSS/JSで作ってください。カレンダーから日付を選択できるUIです。
Custom
以下の仕様でデートピッカーを実装してください。
- カレンダーグリッド表示
- プライマリカラー: #2563eb
- 月の切り替えアニメーション(スライド)
- 今日の日付をハイライト
- 選択日の強調表示
- 日本語の曜日表示
Advanced
高機能デートピッカーを実装してください。
- 範囲選択モード(開始日〜終了日)
- 無効な日付の設定(過去日、特定日)
- キーボード操作(矢印キーで日付移動、Enter確定)
- aria-label に日付を読み上げ用テキストで設定
- role="grid" + role="gridcell" の構造
- 年・月の直接選択(セレクトボックス)
- 祝日の表示(日本の祝日API対応)
- 国際化対応(ロケールで曜日・月名を変更)