Date-Picker with Click & Drag in JavaScript

Date-Picker with Click & Drag in JavaScript
Project: Date Picker with Click & Drag! | @keyframers 2.30.0
Author: @keyframers
Edit Online: View on CodePen
License: MIT

This JavaScript code snippet helps you to create a simple date-picker with the click & drag method. It allows users to select a date range by drag method. Basically, it makes a selection between two dates and updates the date range values in DOM.

This date picker project comes with a simple UI design that only makes selections between the two dates. Then store the selected dates in the data object in the JavaScript program. Furthermore, you can display the selected dates inside the input. If you need a simple date picker solution, check this JavaScript date picker using the select tag.

How to Create Date-Picker with Click & Drag in JavaScript

First of all, load the Normalize CSS by adding the following CDN link into the head tag of your HTML document.

<link rel="stylesheet" href="">

Create the HTML structure for the date picker as follows:

<div class="calendar">
  <div class="day" data-day="1"><span class="number">1</span></div>
  <div class="day" data-day="2"><span class="number">2</span></div>
  <div class="day" data-day="3"><span class="number">3</span></div>
  <div class="day" data-day="4"><span class="number">4</span></div>
  <div class="day" data-day="5"><span class="number">5</span></div>
  <div class="day" data-day="6"><span class="number">6</span></div>
  <div class="day" data-day="7"><span class="number">7</span></div>
  <div class="day" data-day="8"><span class="number">8</span></div>
  <div class="day" data-day="9"><span class="number">9</span></div>
  <div class="day" data-day="10"><span class="number">10</span></div>
  <div class="day" data-day="11"><span class="number">11</span></div>
  <div class="day" data-day="12"><span class="number">12</span></div>
  <div class="day" data-day="13" data-selected="start"><span class="number" >13</span></div>
  <div class="day" data-day="14"><span class="number">14</span></div>
  <div class="day" data-day="15"><span class="number">15</span></div>
  <div class="day" data-day="16"><span class="number">16</span></div>
  <div class="day" data-day="17"><span class="number">17</span></div>
  <div class="day" data-day="18"><span class="number">18</span></div>
  <div class="day" data-day="19"><span class="number">19</span></div>
  <div class="day" data-day="20"><span class="number">20</span></div>
  <div class="day" data-day="21"><span class="number">21</span></div>
  <div class="day" data-day="22"><span class="number">22</span></div>
  <div class="day" data-day="23" data-selected="end"><span class="number" >23</span></div>
  <div class="day" data-day="24"><span class="number">24</span></div>
  <div class="day" data-day="25"><span class="number">25</span></div>
  <div class="day" data-day="26"><span class="number">26</span></div>
  <div class="day" data-day="27"><span class="number">27</span></div>
  <div class="day" data-day="28"><span class="number">28</span></div>
  <div class="day" data-day="29"><span class="number">29</span></div>
  <div class="day" data-day="30"><span class="number">30</span></div>
  <div class="day" data-day="31"><span class="number">31</span></div>

Style the date picker using the following CSS styles:

*::after {
  position: relative;
  box-sizing: border-box;

html {
  height: 100%;
  display: flex;
  background: #eee;

body {
  margin: auto;

:root {
  --color-primary: #00AEF2;

.calendar {
  font-size: 3vw;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-gap: 0.25em 0;
  margin: auto;
  padding: 1em;
  background: #FFF;
  box-shadow: 0 1em 2em rgba(0, 0, 0, 0.25);
  border-radius: 0.5em;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;

.day:first-child {
  grid-column-start: 4;

.day {
  padding: 0.5em;
  text-align: center;
.day::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
display: block !important;
.day[data-selected]::before {
  border-radius: 0.5em;
.day[data-selected=start]::before {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
.day[data-selected], .day[data-selected] ~ .day {
  color: white;
.day[data-selected]::before, .day[data-selected] ~ .day::before {
  background-color: var(--color-primary);
.day[data-selected=start] ~ .day:not([data-selected=end])::before {
  opacity: 0.5;
.day[data-selected=end][data-selected=end]::before {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
.day[data-selected=end] ~ .day {
  color: inherit;
.day[data-selected=end] ~ .day::before {
  background-color: transparent;

Add the following JavaScript function:


// idle
// -> onPointerDown
// dragging
// -> onPointerMove / onPointerOver
// <- onPointerUp

/* NOTE: We retooled the data to be based on first selection and second selection. We'll calculate which is the start & end date later in the `updateDOM` function. */
const data = {
  firstDate: null,
  secondDate: null

const machine = {
  initial: 'idle',
  states: {
    idle: {
      on: {
        pointerdown: (data, event) => {
          data.firstDate =;
          data.secondDate = null;
          return 'dragging';
    dragging: {
      on: {
        pointerover: (data, event) => {
          data.secondDate =;
          return 'dragging';
        pointerup: 'idle',
        pointercancel: 'idle'

// idle
let currentState = machine.initial;

function send(event) {
  const transition = machine

  if (typeof transition === 'function') {
    currentState = transition(data, event);
  } else if (transition) {
    currentState = transition;

/* ---------------------------------- */

const allDayEls = document.querySelectorAll('[data-day]');

allDayEls.forEach(dayEl => {
  dayEl.addEventListener('pointerdown', send);
  dayEl.addEventListener('pointerover', send);

document.body.addEventListener('pointerup', send);

/* ---------------------------------- */

function updateDOM(){
    .forEach(el => {
      delete el.dataset.selected
  const startDate = Math.min(data.firstDate, data.secondDate);
  const endDate = Math.max(data.firstDate, data.secondDate);
  if ( startDate ) {
    const startDateEl = document.querySelector(`[data-day="${startDate}"]`);
    startDateEl.dataset.selected = "start";
  if ( endDate ) {
    const endDateEl = document.querySelector(`[data-day="${endDate}"]`);
    endDateEl.dataset.selected = "end";

That’s all! hopefully, you have successfully created a date picker with click & drag. If you have any questions or suggestions, feel free to comment below.

Leave a Comment


No comments yet. Why don’t you start the discussion?

Leave a Reply