A thin white beam hits a glass prism and fans out into a rainbow that sways and shimmers across the dark. The spectrum is one conic gradient wedge, faded toward the edge with a mask.
Also known as: light dispersion css, rainbow prism effect css, spectrum light background.
<div class="bgx-prism-rainbow" aria-hidden="true"><span></span><span></span><span></span></div>
.bgx-prism-rainbow {
--c: var(--bgx-color, #3b82f6);
font-size: var(--bgx-size, 16px);
position: absolute;
inset: 0;
overflow: hidden;
background: radial-gradient(ellipse 70% 80% at 40% 50%, oklch(from var(--c) 0.2 0.04 calc(h + 0)), #06060b 70%);
isolation: isolate;
}
.bgx-prism-rainbow span {
position: absolute;
}
.bgx-prism-rainbow span:nth-child(1) {
right: 60%;
top: 50%;
width: 45%;
height: 0.22em;
translate: 0 -50%;
transform-origin: 100% 50%;
transform: rotate(8deg);
background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.9));
box-shadow: 0 0 0.6em rgb(255 255 255 / 0.5);
animation: bgx-prism-rainbow-flicker 3s ease-in-out infinite alternate;
}
.bgx-prism-rainbow span:nth-child(2) {
left: 40%;
top: 50%;
width: 70%;
height: 300%;
translate: 0 -50%;
transform-origin: 0 50%;
background: conic-gradient(from 76deg at 0 50%, transparent, #ff4d4d 3deg, #ff9f1a 7deg, #ffe14d 11deg, #4ddb6a 15deg, #3aa8ff 19deg, #8b5cf6 23deg, transparent 27deg);
-webkit-mask-image: linear-gradient(90deg, #000 20%, transparent 95%);
mask-image: linear-gradient(90deg, #000 20%, transparent 95%);
mix-blend-mode: screen;
animation: bgx-prism-rainbow-sway 6s cubic-bezier(0.45, 0, 0.55, 1) infinite alternate;
}
.bgx-prism-rainbow span:nth-child(3) {
left: 40%;
top: 50%;
width: 6em;
aspect-ratio: 1.15;
translate: -50% -58%;
clip-path: polygon(50% 0, 100% 100%, 0 100%);
background: linear-gradient(160deg, oklch(from var(--c) 0.95 0.04 calc(h + 0) / 0.9), oklch(from var(--c) 0.7 0.12 calc(h + 0) / 0.35) 40%, oklch(from var(--c) 0.3 0.08 calc(h + 0) / 0.5));
}
.bgx-prism-rainbow span:nth-child(3)::after {
content: "";
position: absolute;
inset: 0.12em;
clip-path: polygon(50% 1.5%, 99% 99%, 1% 99%);
background: linear-gradient(170deg, oklch(from var(--c) 0.3 0.06 calc(h + 0)), #0b0b14 70%);
}
@keyframes bgx-prism-rainbow-sway {
from { transform: rotate(-3deg) scaleY(0.92); opacity: 0.8; }
to { transform: rotate(3deg) scaleY(1.06); opacity: 1; }
}
@keyframes bgx-prism-rainbow-flicker {
from { opacity: 0.75; }
to { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
.bgx-prism-rainbow, .bgx-prism-rainbow *, .bgx-prism-rainbow::before, .bgx-prism-rainbow::after, .bgx-prism-rainbow *::before, .bgx-prism-rainbow *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--bgx-color on the element or a parent.
Currently previewing #3b82f6.--bgx-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.