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