<button aria-pressed="false">
<span class="sr-only">Toggle Dark Mode</span>
<span class="sun-and-moon">
<span class="rays">
<span class="ray" style="--index: 0; --entry: 0; --exit: 1;"></span>
<span class="ray" style="--index: 1; --entry: 1; --exit: 2;"></span>
<span class="ray" style="--index: 2; --entry: 0; --exit: 3;"></span>
<span class="ray" style="--index: 3; --entry: 1; --exit: 4;"></span>
<span class="ray" style="--index: 4; --entry: 0; --exit: 3;"></span>
<span class="ray" style="--index: 5; --entry: 1; --exit: 2;"></span>
<span class="ray" style="--index: 6; --entry: 0; --exit: 1;"></span>
<span class="ray" style="--index: 7; --entry: 1; --exit: 0;"></span>
</span>
<span class="star" style="--index: 0;"></span>
<span class="star" style="--index: 1;"></span>
<span class="body"></span>
</span>
</button>
*,
*:after,
*:before {
box-sizing: border-box;
}
:root {
--step: 0.25s;
--dark-mode: 0;
--surface: hsl(
210
calc((17 - var(--dark-mode) * 6) * 1%)
calc((98 - var(--dark-mode) * 83) * 1%)
);
--color: hsl(
210
calc((9 + var(--dark-mode) * 5) * 1%)
calc((31 + var(--dark-mode) * 52) *1%)
);
--hover: hsl(
210
calc((16 - var(--dark-mode) * 6) * 1%)
calc((93 - var(--dark-mode) * 60) * 1%)
);
}
:root:has([aria-pressed="true"]) {
--dark-mode: 1;
}
body {
display: grid;
place-items: center;
min-height: 100vh;
font-family: 'Google Sans', sans-serif, system-ui;
background: var(--surface);
transition: background var(--step);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
button {
--size: calc(2 * 48px);
--distance: calc(1 - var(--dark-mode, 0));
--position: calc((40 + (var(--dark-mode, 0) * 70)) * 1%);
--ray-position: calc(var(--dark-mode, 0) * 150%) 0;
--step: 0.25s;
--bg: var(--surface);
aspect-ratio: 1;
padding: 0;
display: grid;
place-items: center;
background: var(--bg);
width: var(--size);
aspect-ratio: 1;
padding: 1%;
border-radius: calc(var(--size) * 0.2);
border: 1px solid hsl(0 0% 50%);
overflow: hidden;
transition: transform var(--step) var(--ease-elastic-5), box-shadow var(--step) var(--ease-elastic-5), background var(--step);
transform: translateY(var(--elevate, 0)) scale(var(--scale, 1));
box-shadow:
calc(var(--size) * var(--shadow-x, 0.05))
calc(var(--size) * var(--shadow-y, 0.05))
0
calc(var(--size) * var(--spread, 0));
}
button:focus-visible {
outline-color: hsl(0 0% 50%);
transition: transform var(--step) var(--ease-elastic-5),
box-shadow var(--step) var(--ease-elastic-5),
background var(--step);
}
button:hover {
background: var(--hover);
}
button:active {
--shadow: 0;
--elevate: 5%;
--scale: 0.9;
--shadow-x: 0;
--shadow-y: 0;
}
[aria-pressed="true"],
[aria-pressed="true"]:is(:hover, :active) {
--shadow: 0;
--elevate: 5%;
--scale: 0.9;
--shadow-x: 0;
--shadow-y: 0;
}
button span {
display: inline-block;
}
.sun-and-moon {
height: 100%;
width: 100%;
display: grid;
place-items: center;
position: relative;
}
.body {
height: 40%;
aspect-ratio: 1;
background: var(--color);
border-radius: 50%;
mask: radial-gradient(circle at right center, transparent 25%, #000 25.5%) var(--position, 40% 50%) / 200% 200% no-repeat;
transition: all var(--step);
transform: rotate(-45deg) scale(calc(1.5 - (var(--distance, 1) * 0.5)));
}
.star {
width: 10%;
aspect-ratio: 1;
background: var(--color);
border-radius: 50%;
position: absolute;
top: 20%;
left: 55%;
transition: transform var(--step) var(--ease-elastic-5);
transform: translate(-50%, -50%) translate(calc(var(--index) * 250%), calc(var(--index) * 220%)) scale(calc((1 + (var(--index) * 1)) * (1 - var(--distance, 1))));
}
.rays {
position: absolute;
inset: 0;
transition: all var(--step);
transform: rotate(-45deg);
mask: linear-gradient(90deg, #000 50%, transparent 75%) var(--ray-position, 0 0) / 200% 200% no-repeat;
}
.ray {
width: 10%;
aspect-ratio: 1;
background: var(--color);
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transition: transform var(--step) calc((var(--step) * 0.5) + ((var(--entry) * var(--step)) * 0.25)) var(--ease-elastic-5);
transform: translate(-50%, -50%)
rotate(calc((360 / 8) * var(--index) * 1deg))
translateX(calc(var(--distance, 1) * 350%));
}
[aria-pressed="true"] .ray {
transition: transform 0s var(--step);
}
[aria-pressed="true"] .star {
transition: transform var(--step) calc(var(--step) + (var(--index) * var(--step))) var(--ease-elastic-5);
}
const BUTTON = document.querySelector('[aria-pressed]')
BUTTON.addEventListener('click', () => BUTTON.setAttribute('aria-pressed', BUTTON.matches('[aria-pressed="true"]') ? false : true))
BUTTON.setAttribute('aria-pressed', window.matchMedia('prefers-color-scheme: dark') ? true : false)
View Compiled