<nav>
<div>
<h2>CSS Clocks</h2>
</div>
<div>
<span>
<label for="">Size</label> <output name="result" for="size">1.5vw</output>
</span>
<form><input name="size" type="range" min=5 max=50 step="0.1" defaultValue=10>
</form>
</span>
</nav>
<main>
<div class="clock">
<div class="light">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div><span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class="clock">
<div class="light">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div><span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div class="clock">
<div class="light">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div><span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
</main>
:root {
--size: 1.5vw;
--bx-zero: inset 0 0 0 var(--size) white, 0px var(--size) white,
0px calc(var(--size) * 2) white, 0px calc(var(--size) * 3) white,
0px calc(var(--size) * 4) white, var(--size) 0 white,
calc(var(--size) * 2) 0 white, calc(var(--size) * 3) 0 white,
calc(var(--size) * 3) var(--size) white,
calc(var(--size) * 3) calc(var(--size) * 2) white,
calc(var(--size) * 3) calc(var(--size) * 3) white,
calc(var(--size) * 3) calc(var(--size) * 4) white,
var(--size) calc(var(--size) * 4) white,
calc(var(--size) * 2) calc(var(--size) * 4) white;
--hue: 270deg;
--saturation: 100%;
--light: 15%;
--theme: hsl(var(--hue) var(--saturation) var(--light));
--transition: none;
}
html,
body {
width: 100%;
min-height: 100%;
padding: 0;
margin: 0;
background: var(--theme);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
grid-gap: 16px;
}
nav {
position: absolute;
top: 0;
left: 0;
right: 0;
margin: auto;
padding: 1em;
color: white;
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-around;
font-family: sans-serif;
z-index: 3;
backdrop-filter: blur(4px);
}
nav div {
display: flex;
grid-gap: 8px;
flex-direction: column;
}
nav span {
width: 100%;
flex-direction: column;
}
nav div input {
width: 100%;
}
main {
display: flex;
flex-direction: column;
grid-gap: 16px;
margin-top: 120px;
}
.clock {
--saturation: 65%;
--light: 25%;
--theme: hsl(var(--hue) var(--saturation) var(--light));
--shadow-light: 10%;
--bottom-shadow: hsl(var(--hue) var(--saturation) var(--shadow-light));
--outline-light: 20%;
--outline-saturation: 80%;
--outline-color: hsl(
var(--hue) var(--outline-saturation) var(--outline-light)
);
--outer-border: var(--size) / 4;
--transition-easing: ease;
--transition-timing: 0.2s;
position: relative;
width: calc(var(--size) * 33);
height: calc(var(--size) * 9);
border: calc(var(--outer-border)) solid var(--theme);
border-radius: calc(var(--size) / 1.5);
background-image: conic-gradient(
from 90deg at calc(var(--size) / 15) calc(var(--size) / 15),
#000 90deg,
rgb(255 255 255 / 10%) 0
);
background-blend-mode: multiply;
background-repeat: repeat;
background-position: 0 0;
background-size: var(--size) var(--size);
box-shadow: inset 0 0 50px rgb(0 0 0 / 1), inset 0 0 30px rgb(0 0 0 / 1),
inset 0 0 10px rgb(0 0 0 / 1), 0 calc(var(--size) / 4) var(--bottom-shadow);
outline: calc(var(--size) / 4) dashed var(--outline-color);
outline-offset: calc(var(--size) * -0.52);
}
.clock:nth-of-type(1) {
--saturation: 65%;
--light: 35%;
--theme: hsl(var(--hue) var(--saturation) var(--light));
}
.clock:nth-of-type(2) {
--hue: 0deg;
--saturation: 65%;
--light: 70%;
--shadow-light: 20%;
--theme: hsl(var(--hue) var(--saturation) var(--light));
--transition: 0;
}
.clock:nth-of-type(3) {
--hue: 120deg;
--saturation: 85%;
--light: 70%;
--shadow-light: 20%;
--theme: hsl(var(--hue) var(--saturation) var(--light));
--transition: 0;
--transition-timing: 1s;
--transition-easing: ease-in-out;
}
.clock:after {
content: "";
display: block;
position: absolute;
width: 100%;
height: 1px;
background: linear-gradient(
to right,
transparent,
rgb(255 255 255 / 60%),
transparent
);
top: calc(calc(var(--outer-border)) * -1);
border-radius: calc(var(--size) / 1.5);
}
.clock:before {
content: "";
display: block;
position: absolute;
width: 100%;
height: 100%;
background: var(--theme);
z-index: 0;
mix-blend-mode: hue;
border-radius: calc(var(--size) / 1.5);
}
.clock span {
--color: var(--theme);
position: absolute;
width: var(--size);
height: var(--size);
top: calc(var(--size) * 2);
left: calc(var(--size) * 2);
border-radius: calc(var(--size));
box-shadow: var(--bx-zero);
transition: box-shadow var(--transition-timing) var(--transition-easing);
transition-property: var(--transition);
}
.clock .light span {
--color: rgb(255 255 255 / 100%);
z-index: 2;
opacity: 0.65;
filter: blur(3px);
}
.clock span:nth-child(2) {
left: calc(var(--size) * 7);
}
.clock span:nth-child(3) {
left: calc(var(--size) * 12);
}
.clock span:nth-child(4) {
left: calc(var(--size) * 17);
}
.clock span:nth-child(5) {
left: calc(var(--size) * 22);
}
.clock span:nth-child(6) {
left: calc(var(--size) * 27);
}
window.addEventListener("DOMContentLoaded", () => {
const nb = [
"inset 0 0 0 var(--size) var(--color), 0px var(--size) var(--color), 0px calc(var(--size) * 2) var(--color), 0px calc(var(--size) * 3) var(--color), 0px calc(var(--size) * 4) var(--color), var(--size) 0 var(--color), calc(var(--size) * 2) 0 var(--color), calc(var(--size) * 3) 0 var(--color), calc(var(--size) * 3) var(--size) var(--color), calc(var(--size) * 3) calc(var(--size) * 2) var(--color), calc(var(--size) * 3) calc(var(--size) * 3) var(--color), calc(var(--size) * 3) calc(var(--size) * 4) var(--color), var(--size) calc(var(--size) * 4) var(--color), calc(var(--size) * 2) calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) rgb(0 0 0 / 0),calc(var(--size)*2) var(--size) var(--color), calc(var(--size)*2) 0 var(--color), calc(var(--size)*2) calc(var(--size) * 2) var(--color), calc(var(--size)*2) calc(var(--size) * 3) var(--color), calc(var(--size)*2) calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) var(--color), var(--size) 0px var(--color), calc(var(--size) * 2) 0px var(--color), calc(var(--size) * 3) 0px var(--color), calc(var(--size) * 3) var(--size) var(--color), 0 calc(var(--size) * 2) var(--color), var(--size) calc(var(--size) * 2) var(--color), calc(var(--size) * 2) calc(var(--size) * 2) var(--color), calc(var(--size) * 3) calc(var(--size) * 2) var(--color), 0 calc(var(--size) * 3) var(--color), 0 calc(var(--size) * 4) var(--color), var(--size) calc(var(--size) * 4) var(--color), calc(var(--size) * 2) calc(var(--size) * 4) var(--color), calc(var(--size) * 3) calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) var(--color),0px calc(var(--size) * 4) var(--color), var(--size) 0 var(--color), calc(var(--size) * 2) 0 var(--color), calc(var(--size) * 3) 0 var(--color), calc(var(--size) * 3) var(--size) var(--color), calc(var(--size) * 3) calc(var(--size) * 2) var(--color), calc(var(--size) * 2) calc(var(--size) * 2) var(--color),var(--size) calc(var(--size) * 2) var(--color),0 calc(var(--size) * 2) var(--color), calc(var(--size) * 3) calc(var(--size) * 3) var(--color), calc(var(--size) * 3) calc(var(--size) * 4) var(--color), var(--size) calc(var(--size) * 4) var(--color), calc(var(--size) * 2) calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) var(--color),calc(var(--size)* 3) 0 var(--color), calc(var(--size)* 3) var(--size) var(--color), calc(var(--size)* 3) calc(var(--size) * 2) var(--color), calc(var(--size)* 2) calc(var(--size) * 2) var(--color), var(--size) calc(var(--size) * 2) var(--color), 0 calc(var(--size) * 2) var(--color), 0 var(--size) var(--color), calc(var(--size)* 3) calc(var(--size) * 3) var(--color), calc(var(--size)* 3) calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) var(--color), 0px var(--size) var(--color), var(--size) 0 var(--color), calc(var(--size) * 2) 0 var(--color), calc(var(--size) * 3) 0 var(--color), 0 calc(var(--size) * 2) var(--color), var(--size) calc(var(--size) * 2) var(--color), calc(var(--size) * 2) calc(var(--size) * 2) var(--color), calc(var(--size) * 3) calc(var(--size) * 2) var(--color), calc(var(--size) * 3) calc(var(--size) * 3) var(--color), calc(var(--size) * 3) calc(var(--size) * 4) var(--color), calc(var(--size) * 2) calc(var(--size) * 4) var(--color), var(--size) calc(var(--size) * 4) var(--color), 0 calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) var(--color),0px var(--size) var(--color), 0px calc(var(--size) * 2) var(--color), 0px calc(var(--size) * 3) var(--color), 0px calc(var(--size) * 4) var(--color), var(--size) calc(var(--size) * 4) var(--color), calc(var(--size)*2) calc(var(--size) * 4) var(--color), calc(var(--size)*3) calc(var(--size) * 3) var(--color), calc(var(--size)*3) calc(var(--size) * 2) var(--color), calc(var(--size)*2) calc(var(--size) * 2) var(--color), var(--size) calc(var(--size) * 2) var(--color), calc(var(--size)*3) calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) var(--color),calc(var(--size) * 3) 0 var(--color), calc(var(--size) * 2) 0 var(--color), var(--size) 0 var(--color), calc(var(--size) * 3) var(--size) var(--color), calc(var(--size) * 3) calc(var(--size) * 2) var(--color), calc(var(--size) * 3) calc(var(--size) * 3) var(--color), calc(var(--size) * 3) calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) var(--color),0px var(--size) var(--color), 0px calc(var(--size) * 2) var(--color), 0px calc(var(--size) * 3) var(--color), 0px calc(var(--size) * 4) var(--color), var(--size) 0 var(--color), calc(var(--size) * 2) 0 var(--color), calc(var(--size) * 3) 0 var(--color), calc(var(--size) * 3) var(--size) var(--color), calc(var(--size) * 3) calc(var(--size) * 2) var(--color), calc(var(--size) * 2) calc(var(--size) * 2) var(--color),var(--size) calc(var(--size) * 2) var(--color), calc(var(--size) * 3) calc(var(--size) * 3) var(--color), calc(var(--size) * 3) calc(var(--size) * 4) var(--color), var(--size) calc(var(--size) * 4) var(--color), calc(var(--size) * 2) calc(var(--size) * 4) var(--color)",
"inset 0 0 0 var(--size) var(--color),calc(var(--size) * 3) 0 var(--color),calc(var(--size) * 2) 0 var(--color),var(--size) 0 var(--color),calc(var(--size) * 2) calc(var(--size) * 2) var(--color),var(--size) calc(var(--size) * 2) var(--color),0 calc(var(--size) * 2) var(--color),0 var(--size) var(--color), calc(var(--size) * 3) var(--size) var(--color), calc(var(--size) * 3) calc(var(--size) * 2) var(--color), calc(var(--size) * 3) calc(var(--size) * 3) var(--color), calc(var(--size) * 3) calc(var(--size) * 4) var(--color)"
];
const clocks = document.querySelectorAll(".clock");
const updateTime = () => {
const today = new Date();
const hours = padNumber(today.getHours());
const minutes = padNumber(today.getMinutes());
const seconds = padNumber(today.getSeconds());
const timeString = `${hours}:${minutes}:${seconds}`;
const time = timeString.split("").filter((v) => v !== ":");
clocks.forEach((clock) => {
const divs = clock.querySelectorAll("div");
time.forEach((t, i) => {
if (t !== ":") {
for (let x = 0; x < divs.length; x++) {
const cell = divs[x].querySelector(`span:nth-child(${i + 1})`);
cell.style.boxShadow = nb[parseInt(t)];
}
}
});
});
requestAnimationFrame(updateTime);
};
const padNumber = (num) => {
return num.toString().padStart(2, "0");
};
const updateClockSize = (e) => {
const size = parseInt(e.target.value) / 20 + "vw";
clocks.forEach((clock) => {
clock.style.setProperty("--size", size);
});
document.querySelector("output").value = size;
};
document.querySelector("input").addEventListener("input", updateClockSize);
updateTime();
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.