After learning SVG knowledge these days, I thought of some colleagues who said that background effects of Windows 10 calendar were very powerful. I hadn’t learned SVG yet, and it felt very complicated to implement it in HTML + CSS alone. After looking at most of SVG these days, it seems a little easier to implement using SVG.

Click on the date in the lower right corner of Win 10 and as you move your mouse through calendars, you can see that the background uses a radial gradient that only works on the border.

HTML + CSS implementation

If you are using HTML + CSS, you need to mask the gradient with HTML on the background of the radial gradient, leaving only the border area. This sounds like a stretch, and it will be implemented as well, generating one redundant element for each date box. Because you’re overlaying radial gradients with HTML elements, there’s less flexibility in color matching, which can be difficult if the background is an image.

Assuming a pure black background, use HTML + CSS as follows:

<! DOCTYPEhtml>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>Document</title>
    <style>
      .root div {
        pointer-events: none;
      }
      .root {
        background: # 000;
        width: 500px;
        height: 500px;
        position: relative;
      }
      .gradient {
        position: absolute;
        left: 20px;
        top: 30px;
        width: 200px;
        height: 200px;
        background: radial-gradient(rgba(200.200.200.1), rgba(200.200.200.0) 75%.rgba(200.200.200.0));
      }
      .root div:not(.gradient) {
        position: relative;
        z-index: 1;
        box-sizing: border-box;
        width: 100px;
        height: 100px;
        float: left;
        padding: 10px;
        background: content-box # 000;
        border: 2px solid # 000;
      }
    </style>
  </head>
  <body>
    <div id="root" class="root">
      <div id="gradient" class="gradient"></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>
    <script>
      const root = document.getElementById("root");
      const gradient = document.getElementById("gradient");
      root.onmousemove = function (e) {
        gradient.style.left = e.offsetX - 100 + "px";
        gradient.style.top = e.offsetY - 100 + "px";
      };
    </script>
  </body>
</html>
Copy the code

Using SVG

Using SVG is a natural implementation because SVG allows you to draw radial gradients to the area where the date border is.

All we need to do is draw the date box path and fill in the radial gradient. Because the date box is regular, only one double loop is required to generate the path.

The detailed code is as follows:

<! DOCTYPEhtml>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0" />
    <title>Document</title>
  </head>
  <body>
    <svg id="Calendar" version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 70 70">
      <defs>
        <style type="text/css">
          rect {
            pointer-events: all;
          }
        </style>
        <radialGradient id="Linear-1" cx="0.2" cy="0.5" r="0.2">
          <stop stop-color="#bbb" stop-opacity="1" offset="0" />
          <stop stop-color="#bbb" stop-opacity="0" offset="1" />
        </radialGradient>
        <g id="boxs">
          <rect x="0" y="0" width="100%" height="100%" fill="# 000" />
        </g>
      </defs>
      <use href="#boxs" />
      <path stroke="#eee" stroke-width="0.5" />
    </svg>

    <script>
      (function () {
        const NS = "http://www.w3.org/2000/svg";
        const boxs = document.getElementById("boxs");
        / / the number of rows
        const rows = [..."1234567"];
        / / the number of columns
        const dayLabels = [..."Day one, two, three, four, five, six."];

        function createSVGEl(name) {
          return document.createElementNS(NS, name);
        }

        function setElAttrbute(obj, attrs) {
          Object.keys(attrs).forEach((key) = > obj.setAttribute(key, attrs[key]));
        }

        // Gradient path
        const pathBox = createSVGEl("path");
        // An array of date boxes to highlight each date box
        const rectBoxItems = [];

        // Clear the path
        const d = rows.reduce(function (prev, _, r) {
          var dRow = dayLabels.reduce(function (prev, _, i) {
            var x = i * 10 + 0.5;
            var y = r * 10 + 0.5;

            // Generate a date box along the way
            const rectBoxItem = createSVGEl("rect");
            setElAttrbute(rectBoxItem, {
              x,
              y,
              width: 9.height: 9."stroke-width": 0.5.fill: "transparent"});// :hover pseudo-class does not work, only event highlighting can be used
            rectBoxItem.onmouseenter = () = > (rectBoxItem.style.stroke = "#ddd");
            rectBoxItem.onmouseout = () = > (rectBoxItem.style.stroke = "");
            rectBoxItems.push(rectBoxItem);

            return (prev += `M ${x} ${y} l 9 0 l 0 9 l -9 0 z `);
          }, "");
          return (prev += dRow);
        }, "");

        // Use gradient render path box
        setElAttrbute(pathBox, {
          d,
          stroke: "url(#Linear-1)"."stroke-width": 0.5});// Mount path and date box
        boxs.appendChild(pathBox);
        rectBoxItems.forEach((v) = > boxs.appendChild(v));

        // Get calendar background and gradient
        const Calendar = document.getElementById("Calendar");
        const Linear1 = document.getElementById("Linear-1");

        // Make the gradient follow the mouse movement in the calendar
        Calendar.addEventListener("mousemove".function (e) {
          const { width, height } = e.target.getBoundingClientRect();
          const x = e.offsetX / width;
          const y = e.offsetY / height;

          requestAnimationFrame(function () {
            Linear1.setAttribute("cx", x);
            Linear1.setAttribute("cy", y); }); }); }) ();</script>
  </body>
</html>
Copy the code