Weekend in Lisbon
Three days of tiles, tarts and trams.
A landscape split into sky, ridge and hills that slide at different speeds on hover, so the near hills travel most and the sky least. Three transformed layers, no JavaScript.
Also known as: parallax hover effect, layered image hover, depth image hover.
<div class="hfx-image-parallax-layers" role="img" aria-label="Mountain landscape"> <span class="hfx-image-parallax-layers-sky"></span> <span class="hfx-image-parallax-layers-ridge"></span> <span class="hfx-image-parallax-layers-hills"></span> </div>
.hfx-image-parallax-layers {
--c: var(--hfx-color, #3b82f6);
font-size: var(--hfx-size, 16px);
position: relative;
width: 15em;
height: 9.5em;
border-radius: 0.75em;
overflow: hidden;
}
.hfx-image-parallax-layers span {
position: absolute;
inset: -0.6em -2.4em -0.6em -0.6em;
transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
.hfx-image-parallax-layers-sky {
background:
radial-gradient(circle at 55% 27%, #fff 0 0.85em, rgb(255 255 255 / 0.45) 0.95em, transparent 3.2em),
linear-gradient(color-mix(in srgb, var(--c) 64%, #fff), color-mix(in srgb, var(--c) 12%, #fff7ed) 72%);
}
.hfx-image-parallax-layers-ridge {
background:
conic-gradient(from 130deg at 72% 40%, transparent 0, color-mix(in srgb, var(--c) 80%, #1e293b) 0.4deg 99.6deg, transparent 100deg),
conic-gradient(from 118deg at 94% 55%, transparent 0, color-mix(in srgb, var(--c) 80%, #1e293b) 0.4deg 123.6deg, transparent 124deg),
conic-gradient(from 124deg at 30% 36%, transparent 0, color-mix(in srgb, var(--c) 48%, #fff) 0.4deg 111.6deg, transparent 112deg),
conic-gradient(from 126deg at 52% 50%, transparent 0, color-mix(in srgb, var(--c) 48%, #fff) 0.4deg 107.6deg, transparent 108deg);
}
.hfx-image-parallax-layers-hills {
background:
radial-gradient(74% 44% at 20% 110%, color-mix(in srgb, var(--c) 42%, #0f172a) 99%, transparent),
radial-gradient(62% 36% at 90% 107%, color-mix(in srgb, var(--c) 56%, #0f172a) 99%, transparent);
}
.hfx-image-parallax-layers:hover .hfx-image-parallax-layers-sky {
transform: translate(-0.3em, 0.1em);
}
.hfx-image-parallax-layers:hover .hfx-image-parallax-layers-ridge {
transform: translate(-1em, 0.15em) scale(1.02);
}
.hfx-image-parallax-layers:hover .hfx-image-parallax-layers-hills {
transform: translate(-2.4em, -0.3em) scale(1.07);
}
@media (prefers-reduced-motion: reduce) {
.hfx-image-parallax-layers, .hfx-image-parallax-layers *, .hfx-image-parallax-layers::before, .hfx-image-parallax-layers::after, .hfx-image-parallax-layers *::before, .hfx-image-parallax-layers *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--hfx-color on the element or a parent.
Currently previewing #3b82f6.--hfx-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.