<html>

<head>
  <title>Windows 10 calendar hover effect</title>
</head>

<body>
  <h1>Windows 10 Calendar hover effect</h1>
  <div class="win-grid">
    <p class="week" id="1">Mo</p>
    <p class="week" id="2">Tu</p>
    <p class="week" id="3">We</p>
    <p class="week" id="4">Th</p>
    <p class="week" id="5">Fr</p>
    <p class="week" id="6">Sa</p>
    <p class="week" id="7">Su</p>
    <div class="win-btn win-btn-inactive" id="40">29</div>
    <div class="win-btn win-btn-inactive" id="41">30</div>
    <div class="win-btn win-btn-inactive" id="42">31</div>
    <div class="win-btn" id="1">1</div>
    <div class="win-btn" id="2">2</div>
    <div class="win-btn" id="3">3</div>
    <div class="win-btn" id="4">4</div>
    <div class="win-btn" id="5">5</div>
    <div class="win-btn" id="6">6</div>
    <div class="win-btn" id="7">7</div>
    <div class="win-btn" id="8">8</div>
    <div class="win-btn" id="9">9</div>
    <div class="win-btn" id="10">10</div>
    <div class="win-btn" id="11">11</div>
    <div class="win-btn" id="12">12</div>
    <div class="win-btn" id="13">13</div>
    <div class="win-btn" id="14">14</div>
    <div class="win-btn" id="15">15</div>
    <div class="win-btn" id="16">16</div>
    <div class="win-btn win-btn-active" id="17">17</div>
    <div class="win-btn" id="18">18</div>
    <div class="win-btn" id="19">19</div>
    <div class="win-btn" id="20">20</div>
    <div class="win-btn" id="21">21</div>
    <div class="win-btn" id="22">22</div>
    <div class="win-btn" id="23">23</div>
    <div class="win-btn" id="24">24</div>
    <div class="win-btn" id="25">25</div>
    <div class="win-btn" id="26">26</div>
    <div class="win-btn" id="27">27</div>
    <div class="win-btn" id="28">28</div>
    <div class="win-btn" id="29">29</div>
    <div class="win-btn" id="30">30</div>
    <div class="win-btn win-btn-inactive" id="31">1</div>
    <div class="win-btn win-btn-inactive" id="32">2</div>
    <div class="win-btn win-btn-inactive" id="33">3</div>
    <div class="win-btn win-btn-inactive" id="34">4</div>
    <div class="win-btn win-btn-inactive" id="35">5</div>
    <div class="win-btn win-btn-inactive" id="36">6</div>
    <div class="win-btn win-btn-inactive" id="37">7</div>
    <div class="win-btn win-btn-inactive" id="38">8</div>
    <div class="win-btn win-btn-inactive" id="39">9</div>
  </div>
  <a target="_devto2" href="https://bit.ly/win10-calendar-effect">I have explained the code here</a>
</body>

</html>
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100&display=swap");

* {
  box-sizing: border-box !important;
  color: white;
  text-transform: capitalize !important;
  font-family: "Noto Sans JP", sans-serif;
  letter-spacing: 2px;
}

body {
  background-color: black;
  display: flex;
  flex-flow: column wrap;
  justify-content: center;
  align-items: center;
}

.win-grid {
  border: 1px solid white;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-gap: 0.2rem;
  align-items: stretch;
  text-align: center;
  padding: 2rem;
  cursor: default;
}

.win-btn {
  padding: 1rem;
  text-align: center;
  border-radius: 0px;
  border: 3px solid transparent;
  transition: border, border-image 10s ease-in-out;
  background: center linear-gradient(black, black) no-repeat;
  background-origin: content-box;
}

/* Today's Date */
.win-btn-active {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0.2rem;
  border: 3px solid red;
  background: center linear-gradient(red, red) no-repeat;
  background-origin: content-box;
}

/* Today's Date when some other date is clicked*/
.win-btn-active-unselected {
  background-origin: border-box;
}

/* Other Month's Date */
.win-btn-inactive {
  color: #ffffff5f;
}

/* Clicked Date */
.win-btn-selected {
  border: 3px solid red;
}

.win-btn:hover {
  border: 3px solid rgba(255, 255, 255, 0.4);
}

.win-btn-active:hover {
  border: 3px solid hsl(0, 90%, 75%);
}

.win-btn-selected:hover {
  border: 3px solid hsl(0, 70%, 50%) !important;
}

button:focus {
  outline: none;
}
/**
 * You can find an explanation for this code here - https://dev.to/jashgopani
 article coming soon*/

//*************
const offset = 69;
const borderWidth = 3;
const angles = []; //in  rad
for (let i = 0; i <= 2; i += 0.25) {
  angles.push(Math.PI * i);
}
let nearBy = [];
let activeBtn = document.querySelector(".win-btn-active");
let lastClicked = null;

document.querySelectorAll(".win-btn").forEach((btn) => {
  btn.onclick = (e) => {
    //clear effects from last clicked date and set lastClicked to current item
    if (lastClicked) {
      lastClicked.classList.remove("win-btn-selected");
    }
    lastClicked = e.currentTarget;

    activeBtn.classList.toggle(
      "win-btn-active-unselected",
      e.currentTarget.id !== activeBtn.id
    );
    e.currentTarget.classList.add("win-btn-selected");
  };
});

function clearNearBy() {
  nearBy.splice(0).forEach((e) => (e.style.borderImage = null));
}

const body = document.querySelector(".win-grid");

body.addEventListener("mousemove", (e) => {
  let x = e.clientX; //x position of cursor.
  let y = e.clientY; //y position of cursor

  clearNearBy();

  nearBy = angles.reduce((acc, rad, index, arr) => {
    const offsets = [offset * 0.35, offset * 1.105];

    const elements = offsets.reduce((elementAccumulator, o, i, offsetArray) => {
      //to skip the intermediate first points calculation
      // if (index % 2 === 0 && i === 0) return elementAccumulator;
      const cx = Math.floor(x + Math.cos(rad) * o);
      const cy = Math.floor(y + Math.sin(rad) * o);
      const element = document.elementFromPoint(cx, cy);

      if (
        element &&
        element.classList.contains("win-btn") &&
        !element.classList.contains("win-btn-active") &&
        !element.classList.contains("win-btn-selected") &&
        elementAccumulator.findIndex((ae) => ae.id === element.id) < 0
      ) {
        const brect = element.getBoundingClientRect();
        const bx = x - brect.left; //x position within the element.
        const by = y - brect.top; //y position within the element.
        const gr = Math.floor(offset * 1.7);
        if (!element.style.borderImage)
          element.style.borderImage = `radial-gradient(${gr}px ${gr}px at ${bx}px ${by}px ,rgba(255,255,255,0.3),rgba(255,255,255,0.1),transparent ) 9 / ${borderWidth}px / 0px stretch `;
        console.log("element at", offsets, (rad * 180) / Math.PI, element);

        return [...elementAccumulator, element];
      }
      return elementAccumulator;
    }, []);

    return acc.concat(elements);
  }, []);
});

body.onmouseleave = (e) => {
  clearNearBy();
};

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.