Deep water that darkens toward the bottom, with slanted shafts of light swaying down from a shimmering surface. The caustics are two ring tiles drifting in opposite directions.
Also known as: underwater light rays css, ocean background animation css, water caustics css.
<div class="bgx-underwater" aria-hidden="true"><span></span><span></span><span></span><span></span></div>
.bgx-underwater {
--c: var(--bgx-color, #3b82f6);
font-size: var(--bgx-size, 16px);
position: absolute;
inset: 0;
overflow: hidden;
background: linear-gradient(oklch(from var(--c) 0.62 0.11 calc(h - 60)), oklch(from var(--c) 0.36 0.09 calc(h - 45)) 45%, oklch(from var(--c) 0.14 0.04 calc(h - 30)));
isolation: isolate;
}
.bgx-underwater::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: 0;
height: 45%;
background:
radial-gradient(ellipse 50% 42% at 50% 50%, transparent 58%, rgb(255 255 255 / 0.35) 70%, transparent 80%) 0 0 / 3.2em 1.6em,
radial-gradient(ellipse 50% 42% at 50% 50%, transparent 55%, rgb(255 255 255 / 0.28) 68%, transparent 80%) 0 0 / 4.4em 2.1em;
-webkit-mask-image: linear-gradient(#000, transparent);
mask-image: linear-gradient(#000, transparent);
mix-blend-mode: soft-light;
animation: bgx-underwater-caustics 6s linear infinite;
}
.bgx-underwater span {
position: absolute;
top: -10%;
left: var(--x);
width: var(--w);
height: 130%;
background: linear-gradient(oklch(from var(--c) 0.97 0.04 calc(h - 60) / 0.5), transparent 80%);
transform-origin: 50% 0;
filter: blur(0.5em);
mix-blend-mode: screen;
animation: bgx-underwater-shaft var(--t) ease-in-out var(--d) infinite alternate;
}
.bgx-underwater span:nth-child(1) { --x: 14%; --w: 2.2em; --t: 5s; --d: -1s; }
.bgx-underwater span:nth-child(2) { --x: 36%; --w: 4em; --t: 6.5s; --d: -3s; }
.bgx-underwater span:nth-child(3) { --x: 60%; --w: 1.6em; --t: 4.2s; --d: -2s; }
.bgx-underwater span:nth-child(4) { --x: 80%; --w: 3.2em; --t: 7s; --d: -5s; }
@keyframes bgx-underwater-shaft {
from { transform: rotate(18deg) skewX(-6deg); opacity: 0.35; }
to { transform: rotate(26deg) skewX(6deg); opacity: 0.9; }
}
@keyframes bgx-underwater-caustics {
to { background-position: 6.4em 1.6em, -4.4em 2.1em; }
}
@media (prefers-reduced-motion: reduce) {
.bgx-underwater, .bgx-underwater *, .bgx-underwater::before, .bgx-underwater::after, .bgx-underwater *::before, .bgx-underwater *::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.