CSS-Only Parallax Perspective Section — Free HTML CSS JS Snippet
CSS-Only Parallax Perspective Section · Layouts · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
CSS-Only Parallax Perspective Section — Depth Effect With Zero Scroll JavaScript

Most scroll parallax effects rely on a JavaScript scroll listener recalculating transforms on every frame. This snippet achieves the same layered depth illusion using only CSS — the perspective, transform-style: preserve-3d, and translateZ() combination — so scrolling produces a parallax effect the browser's own 3D rendering engine computes natively, with no scroll event listener at all.
Perspective on the scroll container
The trick starts on .pp-container, the scrollable element itself: perspective: 1px combined with overflow-y: scroll puts the whole scrolling context into a shallow 3D space. Because the perspective value is so small (1px instead of a more typical few hundred), any element pushed backward in Z-space appears to move dramatically less relative to scroll than an element at the natural Z position — that's the entire depth illusion, computed by the browser's rendering engine as a side effect of 3D perspective math, not by JavaScript recalculating positions.
Pushing the background layer back and compensating its scale
Each .parallax-bg layer is given transform: translateZ(-1px) scale(2). Moving an element 1px backward in Z-space at a 1px perspective effectively halves its apparent size, so multiplying its scale by 2 compensates and restores it to filling its container visually — while its actual scroll displacement (governed by the perspective math) is now dramatically slower than the normal-flow foreground content in front of it.
transform-style: preserve-3d ties it together
Each .pp-group section sets transform-style: preserve-3d, which is required for the perspective set on the ancestor .pp-container to actually apply 3D positioning to the .parallax-bg child instead of flattening it into the 2D plane. Without this, translateZ would have no visible effect.
Genuinely zero scroll-linked JavaScript
The JS file in this snippet does no visual work at all — there is no scroll listener, no requestAnimationFrame loop, and no per-frame style recalculation. The entire parallax effect is a byproduct of how the browser paints elements positioned in 3D space relative to a perspective origin as the page scrolls, which is both simpler to reason about and immune to the scroll-jank concerns that JS-driven parallax needs careful rAF throttling to avoid.
Build with AI
Build, Understand, Optimize, and Extend It With AI
Hand this snippet's HTML, CSS, and JavaScript to an AI coding assistant like Claude and ask it to adapt "CSS-Only Parallax Perspective Section" to your project — restyle it to match your design system, wire it up to real data instead of the static example, or port it to the framework you're building in.
Prompt to recreate it
Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:
Build a layouts component called "CSS-Only Parallax Perspective Section" using plain HTML, CSS, and vanilla JavaScript — no framework, no build step.
Requirements:
- Match the structure and behavior of the "CSS-Only Parallax Perspective Section" snippet from the UI Snippets Library.
- Keep the markup semantic and the styling self-contained (no external dependencies beyond what the original snippet uses).
- Keep the JavaScript vanilla, with no framework runtime required.
- Make it easy to restyle via CSS custom properties or class overrides so it can be dropped into a real project.Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.
Source Code
<div class="pp-container" id="ppContainer">
<section class="pp-group">
<div class="parallax-bg pp-bg-a"></div>
<div class="pp-foreground">
<span class="pp-eyebrow">Scene One</span>
<h2>Pure CSS Depth</h2>
<p>Scroll inside this box — no scroll-linked JavaScript at all.</p>
</div>
<span class="pp-scrollcue">Scroll ↓</span>
</section>
<section class="pp-group">
<div class="parallax-bg pp-bg-b"></div>
<div class="pp-foreground">
<span class="pp-eyebrow">Scene Two</span>
<h2>Perspective & TranslateZ</h2>
<p>The background layer sits behind the scroll plane and scales to compensate.</p>
</div>
</section>
<section class="pp-group">
<div class="parallax-bg pp-bg-c"></div>
<div class="pp-foreground">
<span class="pp-eyebrow">Scene Three</span>
<h2>Zero Scroll Listeners</h2>
<p>The browser's own 3D rendering handles the depth illusion.</p>
</div>
</section>
</div>*{box-sizing:border-box}
body{font-family:system-ui,-apple-system,sans-serif;margin:0}
.pp-container{
height:70vh;min-height:420px;overflow-y:scroll;overflow-x:hidden;
perspective:1px;perspective-origin:0 0;
background:#0b0d14;
scroll-snap-type:y mandatory;
scrollbar-width:thin;scrollbar-color:#4338ca #0b0d14;
}
.pp-container::-webkit-scrollbar{width:8px}
.pp-container::-webkit-scrollbar-track{background:#0b0d14}
.pp-container::-webkit-scrollbar-thumb{background:#4338ca;border-radius:99px}
.pp-group{
position:relative;height:70vh;min-height:340px;
display:flex;align-items:center;justify-content:center;
transform-style:preserve-3d;
scroll-snap-align:start;
}
.parallax-bg{
position:absolute;inset:0;
transform:translateZ(-1px) scale(2);
background-size:cover;background-position:center;
}
.pp-bg-a{background:radial-gradient(circle at 30% 30%,#4338ca,#0b0d14 70%)}
.pp-bg-b{background:radial-gradient(circle at 70% 40%,#be185d,#0b0d14 70%)}
.pp-bg-c{background:radial-gradient(circle at 40% 60%,#0e7490,#0b0d14 70%)}
.pp-foreground{
position:relative;z-index:1;
text-align:center;color:#fff;padding:28px 32px;max-width:420px;
background:rgba(11,13,20,.4);border:1px solid rgba(255,255,255,.08);
border-radius:18px;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
box-shadow:0 24px 60px -20px rgba(0,0,0,.6);
}
.pp-eyebrow{display:inline-block;font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:#c7cbe0;background:rgba(255,255,255,.08);padding:4px 12px;border-radius:99px;margin-bottom:14px}
.pp-foreground h2{font-size:clamp(22px,4vw,34px);font-weight:800;margin:0 0 10px;letter-spacing:-.02em}
.pp-foreground p{font-size:14px;color:#dfe1ee;margin:0;line-height:1.6}
.pp-scrollcue{
position:absolute;bottom:18px;left:50%;z-index:1;
transform:translateX(-50%);font-size:11px;font-weight:600;letter-spacing:.1em;
text-transform:uppercase;color:rgba(255,255,255,.55);
animation:pp-bounce 1.8s ease-in-out infinite;
}
@keyframes pp-bounce{0%,100%{transform:translate(-50%,0)}50%{transform:translate(-50%,6px)}}// This snippet is intentionally CSS-only for the parallax effect itself --
// the perspective + translateZ + scale technique on .parallax-bg layers
// produces the depth illusion purely through the browser's native 3D
// rendering as the .pp-container scrolls. No scroll event listeners or
// rAF loops are needed to drive the effect.
//
// This script only logs a confirmation so the snippet still has a JS
// entry point available; it performs no visual work.
console.log('CSS-only parallax perspective section: no scroll JS required.');Step by step
How to Use
- 1Load the snippetClick "CSS-Only Parallax Perspective Section" in the sidebar to load its HTML, CSS, and JS into the editor panels. The preview updates instantly.
- 2Edit the codeModify any panel — HTML, CSS, or JS. The preview refreshes as you type. Use Reset in each panel header to restore the original.
- 3Preview on devicesClick the Mobile (375px), Tablet (768px), or Desktop buttons in the preview header to check responsiveness.
- 4Export in your formatClick "HTML" to download a standalone file, "JSX" for a React component, "Tailwind" for a React + Tailwind CSS component, "Tailwind HTML" for a standalone HTML file with Tailwind CDN, "Vue" for a Vue 3 SFC with <template>/<script setup>/<style scoped>, or "Angular" for a standalone Angular .component.ts file. "Copy all" copies the full code to clipboard.
- 5Save your versionClick "Save as", type a name, and press Enter. Your snippet saves to IndexedDB and appears in the Saved tab.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
The scrollable container has a shallow CSS perspective (1px). Background layers are pushed backward in 3D space with translateZ(-1px) and their scale compensated to fill the viewport again. Because of how CSS 3D perspective projection works, an element positioned further back in Z-space visually displaces less per pixel of scroll than normal-flow content in front of it — the browser computes this automatically as part of rendering, with no JavaScript involved.
Moving an element backward in a 1px perspective space roughly halves how large it appears, since it is now twice as "far" from the viewer in perspective terms. Scaling it up by 2 compensates for that shrinkage so it still visually fills its container, while its slowed scroll displacement (the actual parallax effect) is unaffected by the scale.
Yes — replace the gradient in a .parallax-bg rule with a background-image, keep background-size: cover and background-position: center, and the same translateZ/scale technique will apply the parallax effect to it identically.




