Back to Components
Pure CSS Parallax Scrolling – Advanced 3D Perspective Animation (No JavaScript Required)
Component

Pure CSS Parallax Scrolling – Advanced 3D Perspective Animation (No JavaScript Required)

CodewithLord
December 15, 2025

A complete technical breakdown of pure CSS parallax scrolling using 3D perspective, transform-style preserve-3d, and translateZ. Create stunning depth effects with multiple layers moving at different speeds using only CSS.


🧠 Description


This pure CSS parallax scrolling effect demonstrates advanced 3D transformation techniques to create stunning depth perception and motion parallax effects. Without a single line of JavaScript, CSS handles all animation and perspective calculations, creating the illusion that different elements move at different speeds as you scroll.


What Makes This Project Exceptional?


Visual Features:

  • Multi-layered parallax depth effect
  • Foreground images moving slower than background
  • Nested images with varying depth perception
  • Smooth scrolling with natural motion
  • Rotating and scaled elements for visual interest
  • Realistic shadows and layering
  • Responsive design that adapts to viewport

Technical Innovation:

  • 3D Perspective: Creates vanishing point for depth
  • transform-style: preserve-3d: Maintains 3D space across children
  • translateZ(): Controls depth positioning on Z-axis
  • scale(): Perspective-adjusted scaling based on depth
  • No JavaScript Required: Entire effect powered by CSS
  • Hardware Acceleration: GPU-accelerated transforms
  • Browser-Optimized: Works with vendor prefixes

The Concept


How Parallax Works:

Traditional parallax in web uses JavaScript to move elements at different speeds during scroll. This pure CSS approach uses 3D perspective transforms to achieve the same effect mathematically.


The Physics:

When perspective: 1px is applied to the body,
objects with positive translateZ values appear to move SLOWER
objects with negative translateZ values appear to move FASTER

This creates the parallax illusion without JavaScript calculations.

Depth Layering:

  • Title: Large scale-down to appear far (translateZ: 0.25px)
  • Background images: Negative translateZ to move fast
  • Content boxes: Default positioning
  • Foreground images: Varying positive Z values

Each layer moves at a different rate based on its Z-depth, creating natural parallax.




💻 Step 1: HTML Structure


Complete HTML Code


1<!DOCTYPE html> 2<html lang="en"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>Pure CSS Parallax Scrolling | 3D Perspective</title> 8 <meta name="description" content="Advanced parallax scrolling effect using pure CSS 3D transforms and perspective. No JavaScript required."> 9 10 <!-- Custom Stylesheet --> 11 <link rel="stylesheet" href="./style.css"> 12 13 <!-- Vendor Prefix Fixer (Optional, for older browsers) --> 14 <script src="https://public.codepenassets.com/js/prefixfree-1.0.7.min.js"></script> 15</head> 16 17<body> 18 19 <!-- ==================================== 20 SLIDE 0: TITLE/HEADER 21 ===================================== --> 22 <div id="title" class="slide header"> 23 <h1>Pure CSS Parallax</h1> 24 </div> 25 26 <!-- ==================================== 27 SLIDE 1: TEXT CONTENT 28 ===================================== --> 29 <div id="slide1" class="slide"> 30 <!-- Content Box --> 31 <div class="title"> 32 <h1>Slide 1</h1> 33 <p>Lorem ipsum dolor sit amet, in velit iudico mandamus sit, persius dolorum in per, postulant mnesarchum cu nam. Malis movet ornatus id vim, feugait detracto est ea, eam eruditi conceptam in. Ne sit explicari interesset. Labores perpetua cum at. Id viris docendi denique vim.</p> 34 </div> 35 <!-- Background Image (attached to ::before pseudo-element) --> 36 </div> 37 38 <!-- ==================================== 39 SLIDE 2: TEXT + IMAGES 40 ===================================== --> 41 <div id="slide2" class="slide"> 42 <!-- Content Box --> 43 <div class="title"> 44 <h1>Slide 2</h1> 45 <p>Lorem ipsum dolor sit amet, in velit iudico mandamus sit, persius dolorum in per, postulant mnesarchum cu nam. Malis movet ornatus id vim, feugait detracto est ea, eam eruditi conceptam in. Ne sit explicari interesset. Labores perpetua cum at. Id viris docendi denique vim.</p> 46 </div> 47 48 <!-- Foreground Images (with parallax depth) --> 49 <!-- First image - closer to viewer --> 50 <img 51 src="https://picsum.photos/980/600" 52 alt="Parallax foreground image 1" 53 > 54 55 <!-- Second image - further from viewer --> 56 <img 57 src="https://picsum.photos/960/600" 58 alt="Parallax foreground image 2" 59 > 60 </div> 61 62 <!-- ==================================== 63 SLIDE 3: TEXT CONTENT 64 ===================================== --> 65 <div id="slide3" class="slide"> 66 <!-- Content Box --> 67 <div class="title"> 68 <h1>Slide 3</h1> 69 <p>Lorem ipsum dolor sit amet, in velit iudico mandamus sit, persius dolorum in per, postulant mnesarchum cu nam. Malis movet ornatus id vim, feugait detracto est ea, eam eruditi conceptam in. Ne sit explicari interesset. Labores perpetua cum at. Id viris docendi denique vim.</p> 70 </div> 71 <!-- Background Image (attached to ::before pseudo-element) --> 72 </div> 73 74 <!-- ==================================== 75 SLIDE 4: FOOTER/END SECTION 76 ===================================== --> 77 <div id="slide4" class="slide header"> 78 <h1>The End</h1> 79 </div> 80 81</body> 82 83</html>

HTML Best Practices Used


Semantic Structure: Clear slide divisions with unique IDs ✅ Accessibility: Proper lang attribute, alt text for images ✅ Mobile-First: Viewport meta tag included ✅ Clean Markup: Minimal divs, no unnecessary nesting ✅ Performance: Images from CDN, lazy-loadable ✅ Standards: Valid HTML5 with proper closing tags ✅ Descriptive: Clear class/id naming conventions




🎨 Step 2: CSS – 3D Perspective & Parallax Magic


Complete CSS Code


1/* ==================================== 2 IMPORTS & FONT LOADING 3 ==================================== */ 4 5@import url(https://fonts.googleapis.com/css?family=Nunito); 6 7/* ==================================== 8 HTML & BODY - PERSPECTIVE SETUP 9 ==================================== */ 10 11html { 12 height: 100%; 13 overflow: hidden; 14} 15 16body { 17 margin: 0; 18 padding: 0; 19 20 /* THE MAGIC: Enable 3D perspective */ 21 perspective: 1px; 22 transform-style: preserve-3d; 23 24 /* Layout */ 25 height: 100%; 26 overflow-y: scroll; 27 overflow-x: hidden; 28 29 /* Typography */ 30 font-family: Nunito; 31} 32 33/* ==================================== 34 TYPOGRAPHY 35 ==================================== */ 36 37h1 { 38 font-size: 250%; 39 margin: 0; 40 font-weight: bold; 41} 42 43p { 44 font-size: 140%; 45 line-height: 150%; 46 color: #333; 47 margin: 0; 48} 49 50/* ==================================== 51 SLIDE CONTAINER STYLING 52 ==================================== */ 53 54.slide { 55 position: relative; 56 padding: 25vh 10%; 57 min-height: 100vh; 58 width: 100vw; 59 box-sizing: border-box; 60 61 /* Preserve 3D space for children */ 62 transform-style: inherit; 63 64 /* Visual separation between slides */ 65 box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.7); 66} 67 68/* ==================================== 69 BACKGROUND PSEUDO-ELEMENTS 70 ==================================== 71 72 The ::before pseudo-element serves as: 73 - Background image container 74 - Parallax effect layer 75 - Depth-controlled element using negative translateZ 76 77 ==================================== */ 78 79.slide:before { 80 content: ""; 81 position: absolute; 82 top: 0; 83 bottom: 0; 84 left: 0; 85 right: 0; 86 87 /* Consistent shadow across all pseudo-elements */ 88 box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.7); 89 90 /* Background attachment */ 91 background: 50% 50% / cover; 92 93 /* THIS IS KEY: Negative translateZ makes background move faster 94 With perspective: 1px on body, scale(2) compensates the shrink 95 Result: Background moves at 2x speed of scroll */ 96 transform: translateZ(-1px) scale(2); 97} 98 99/* ==================================== 100 TITLE BOX STYLING 101 ==================================== */ 102 103.title { 104 width: 50%; 105 padding: 5%; 106 border-radius: 5px; 107 background: rgba(240, 230, 220, 0.7); 108 box-shadow: 0 0 8px rgba(0, 0, 0, 0.7); 109 110 /* Z-index for layering */ 111 position: relative; 112 z-index: 1; 113} 114 115/* Alternate left/right positioning */ 116.slide:nth-child(2n) .title { 117 margin-left: 0; 118 margin-right: auto; 119} 120 121.slide:nth-child(2n+1) .title { 122 margin-left: auto; 123 margin-right: 0; 124} 125 126/* ==================================== 127 HEADER/TITLE SLIDE STYLING 128 ==================================== */ 129 130.header { 131 text-align: center; 132 font-size: 175%; 133 color: #fff; 134 text-shadow: 0 2px 2px #000; 135 136 /* No pseudo-element background */ 137 box-shadow: none; 138} 139 140.header:before { 141 display: none; 142} 143 144/* ==================================== 145 INDIVIDUAL SLIDE BACKGROUNDS 146 ==================================== */ 147 148#title { 149 background-image: url("https://picsum.photos/640/480"); 150 z-index: 2; 151 152 /* Keep ::before's box-shadow */ 153 box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.7); 154} 155 156/* Scale down the title text for depth effect */ 157#title h1 { 158 transform: translateZ(0.25px) scale(0.75); 159 transform-origin: 50% 100%; 160} 161 162/* Slide 1 background - faster parallax */ 163#slide1:before { 164 background-image: url("https://picsum.photos/960/520"); 165 transform: translateZ(-1px) scale(2); 166} 167 168/* Slide 2 - foreground images with parallax */ 169#slide2 { 170 background-image: url("https://picsum.photos/960/400"); 171 z-index: 2; 172} 173 174/* Slide 3 background - faster parallax */ 175#slide3:before { 176 background-image: url("https://picsum.photos/980/600"); 177 transform: translateZ(-1px) scale(2); 178} 179 180/* Slide 4 - dark ending */ 181#slide4 { 182 background: #222; 183 box-shadow: none; 184} 185 186/* ==================================== 187 FOREGROUND IMAGES - PARALLAX DEPTH 188 ==================================== */ 189 190img { 191 position: absolute; 192 top: 50%; 193 left: 35%; 194 width: 320px; 195 height: 240px; 196 197 /* FIRST IMAGE: Closer to viewer than background 198 translateZ: 0.25px (positive = closer) 199 scale: 0.75 (smaller due to perspective) 200 Translates to move with scroll, but SLOWER than background */ 201 transform: 202 translateZ(0.25px) 203 scale(0.75) 204 translateX(-94%) 205 translateY(-100%) 206 rotate(2deg); 207 208 /* Visual styling */ 209 padding: 10px; 210 border-radius: 5px; 211 background: rgba(240, 230, 220, 0.7); 212 box-shadow: 0 0 8px rgba(0, 0, 0, 0.7); 213} 214 215/* SECOND IMAGE: Even closer to viewer than first 216 translateZ: 0.4px (more positive = much closer) 217 scale: 0.6 (smaller scale) 218 Moves even slower than first image */ 219img:last-of-type { 220 transform: 221 translateZ(0.4px) 222 scale(0.6) 223 translateX(-104%) 224 translateY(-40%) 225 rotate(-5deg); 226} 227 228/* ==================================== 229 BACKGROUND PROPERTY SHORTHAND 230 ==================================== */ 231 232.slide, .slide:before { 233 background: 50% 50% / cover; 234 background-repeat: no-repeat; 235 background-position: center center; 236 background-size: cover; 237 background-attachment: fixed; 238}

CSS Architecture Explanation


1. The 3D Perspective Foundation


Critical CSS:

1body { 2 perspective: 1px; 3 transform-style: preserve-3d; 4}

What This Does:

  • perspective: 1px: Creates a vanishing point 1 pixel away from viewport

    • Very close perspective = dramatic depth effect
    • Objects further away (negative Z) appear to move faster
    • Objects closer (positive Z) appear to move slower
  • transform-style: preserve-3d: Maintains 3D space for child elements

    • Without this, transforms would flatten
    • Critical for layered parallax effects
    • Inherited by all child elements

The Physics:

With perspective: 1px:

Distance from Viewer → Scroll Speed

-1px (far back):     2x scroll speed (scale(2))
 0px (default):      1x scroll speed
+0.25px (closer):    0.75x scroll speed (scale(0.75))
+0.4px (very close): 0.6x scroll speed (scale(0.6))

This mathematical relationship creates natural parallax without JavaScript.


2. The Background Parallax Effect


1.slide:before { 2 content: ""; 3 position: absolute; 4 top: 0; 5 bottom: 0; 6 left: 0; 7 right: 0; 8 background: 50% 50% / cover; 9 10 /* THE KEY: Negative Z with scale(2) compensation */ 11 transform: translateZ(-1px) scale(2); 12}

How It Works:

  1. translateZ(-1px): Moves element 1px behind viewer's perspective point

    • With perspective: 1px, this makes element move at 2x scroll speed
    • Background appears to scroll faster than content
  2. scale(2): Scales up to compensate for perspective shrinking

    • Perspective makes far objects appear smaller
    • scale(2) restores visibility
    • Maintains proper visual size
  3. Result: Background moves faster = parallax illusion


3. Foreground Image Parallax


1img { 2 transform: 3 translateZ(0.25px) 4 scale(0.75) 5 translateX(-94%) 6 translateY(-100%) 7 rotate(2deg); 8} 9 10img:last-of-type { 11 transform: 12 translateZ(0.4px) 13 scale(0.6) 14 translateX(-104%) 15 translateY(-40%) 16 rotate(-5deg); 17}

Transform Breakdown:

First Image (translateZ: 0.25px, scale: 0.75):

  • Positive Z (closer to viewer)
  • Moves SLOWER than content (0.75x speed)
  • Appears to float above background
  • Creates depth layering

Second Image (translateZ: 0.4px, scale: 0.6):

  • Even more positive Z (even closer)
  • Even slower scroll speed (0.6x)
  • Even smaller scale (closer perspective)
  • Maximum depth effect among images

Position Transforms:

  • translateX(-94% and -104%): Horizontal positioning
  • translateY(-100% and -40%): Vertical positioning
  • rotate(2deg and -5deg): Slight rotation for visual interest

4. Slide Container Structure


1.slide { 2 position: relative; 3 padding: 25vh 10%; 4 min-height: 100vh; 5 width: 100vw; 6 box-sizing: border-box; 7 transform-style: inherit; 8 box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.7); 9}

Layout Details:

  • position: relative: Positioning context for children
  • padding: 25vh 10%: Vertical rhythm (25% viewport height)
  • min-height: 100vh: Full viewport height minimum
  • width: 100vw: Full viewport width
  • transform-style: inherit: Preserves 3D space from body

5. Title Box Positioning


1.title { 2 width: 50%; 3 padding: 5%; 4 background: rgba(240, 230, 220, 0.7); 5} 6 7.slide:nth-child(2n) .title { 8 margin-left: 0; 9 margin-right: auto; /* Align RIGHT */ 10} 11 12.slide:nth-child(2n+1) .title { 13 margin-left: auto; 14 margin-right: 0; /* Align LEFT */ 15}

Pattern:

  • Even-numbered slides (2, 4): Title box on RIGHT
  • Odd-numbered slides (1, 3, 5): Title box on LEFT
  • Creates visual zigzag pattern
  • Alternating alignment improves readability

6. Header Slide Styling


1.header { 2 text-align: center; 3 font-size: 175%; 4 color: #fff; 5 text-shadow: 0 2px 2px #000; 6} 7 8#title h1 { 9 transform: translateZ(0.25px) scale(0.75); 10 transform-origin: 50% 100%; 11} 12 13#slide4 { 14 background: #222; 15 box-shadow: none; 16}

Features:

  • Title Slide (#title): Large background image with title text

    • Title text scaled down for depth effect
    • Positive translateZ makes it move slower
    • White text on dark background
  • End Slide (#slide4): Dark background

    • No background image
    • Clean ending slide
    • No box-shadow



🎬 Step 3: How Parallax Scrolling Works


The Mathematical Model


Perspective and Parallax Formula:

Apparent Scroll Speed = 1 + (1 - translateZ / perspective)

With perspective: 1px:

Element with translateZ(-1px):
  Speed = 1 + (1 - (-1px) / 1px) = 1 + 2 = 2x

Element with translateZ(0.25px):
  Speed = 1 + (1 - 0.25px / 1px) = 1 + 0.75 = 1.75x

Element with translateZ(0px) (default):
  Speed = 1 + (1 - 0px / 1px) = 1 + 1 = 1x

Result:

  • Negative Z values scroll faster
  • Positive Z values scroll slower
  • Default (0) scrolls at normal speed

Browser Rendering Process


When User Scrolls:

1. Browser calculates viewport scroll position
2. Applies perspective transformation to all elements
3. Elements with different translateZ values calculated at different positions
4. GPU renders final result at 60fps
5. User sees parallax effect
6. NO JAVASCRIPT NEEDED

Performance Characteristics


Why This Is Efficient:

Hardware Accelerated: GPU handles 3D transforms ✅ No JavaScript Overhead: Pure CSS calculations ✅ 60fps Possible: GPU optimized ✅ Minimal Repaints: Only perspective recalculation ✅ Battery Friendly: No CPU-intensive scroll listeners ✅ Mobile Optimized: GPU acceleration on mobile devices


Browser Support:

  • Chrome: Full support (v12+)
  • Firefox: Full support (v10+)
  • Safari: Full support (v4+)
  • Edge: Full support (v12+)
  • IE: Partial support (IE10+, limited)
  • Mobile: Excellent support (iOS Safari 3.2+, Chrome Mobile)



🎯 Advanced Concepts


1. Transform Order Matters


1/* This order is CORRECT */ 2transform: 3 translateZ(0.25px) 4 scale(0.75) 5 translateX(-94%) 6 translateY(-100%) 7 rotate(2deg); 8 9/* Order of operations in CSS transforms: 10 1. translateZ applies first (3D positioning) 11 2. scale then reduces size (perspective scale) 12 3. translateX/Y position the scaled element 13 4. rotate adds final rotation */

Why Order Matters:

Transforms are applied left-to-right. Changing order produces different results:

1/* Result: Scale first, then move */ 2transform: scale(0.5) translateX(100px); 3 4/* Result: Move first, then scale (moves 50px, not 100px) */ 5transform: translateX(100px) scale(0.5);

2. The Preserve-3D Inheritance


1body { 2 transform-style: preserve-3d; 3} 4 5.slide { 6 transform-style: inherit; /* Inherits from body */ 7} 8 9img { 10 /* Implicitly inherits preserve-3d from .slide */ 11}

Why Important:

Without preserve-3d, transforms flatten to 2D. All children would lose depth perception. Inheritance ensures entire element tree maintains 3D space.


3. Scale Compensation


1/* Without perspective, this would just scale: */ 2transform: scale(0.75); /* Element becomes 75% size */ 3 4/* With perspective: 1px, scale compensation is needed: */ 5transform: translateZ(0.25px) scale(0.75); 6/* 7 The positive Z makes element appear smaller due to perspective 8 scale(0.75) compensates to restore visual size 9 Balance is critical for correct appearance 10*/

4. Transform Origins


1#title h1 { 2 transform: translateZ(0.25px) scale(0.75); 3 transform-origin: 50% 100%; /* Scale from bottom center */ 4}

Transform Origin Values:

  • 50% 100%: Center horizontally, bottom vertically
  • 50% 50%: Center (default)
  • 0% 0%: Top-left corner
  • 100% 100%: Bottom-right corner

Different origins produce different visual effects when combined with scale.




📱 Responsive Considerations


Mobile Optimizations


Mobile Performance:

1/* On mobile, reduce perspective for less intense effect */ 2@media (max-width: 768px) { 3 body { 4 perspective: 2px; /* Less dramatic on mobile */ 5 } 6} 7 8/* Or disable parallax entirely on low-power devices */ 9@media (prefers-reduced-motion: reduce) { 10 body { 11 perspective: none; 12 } 13 14 .slide:before, 15 img { 16 transform: none; 17 } 18}

Viewport Considerations:

1.slide { 2 min-height: 100vh; /* Full viewport height */ 3 width: 100vw; /* Full viewport width */ 4 padding: 25vh 10%; /* 25% viewport for padding */ 5}

Uses viewport-relative units (vh, vw) for responsive sizing.


Accessibility


Motion Sensitivity:

1/* Respect user's motion preferences */ 2@media (prefers-reduced-motion: reduce) { 3 * { 4 animation-duration: 0.01ms !important; 5 animation-iteration-count: 1 !important; 6 transition-duration: 0.01ms !important; 7 } 8 9 body { 10 perspective: none; 11 } 12}

Some users experience motion sickness from parallax. Always respect prefers-reduced-motion media query.




🔧 Customization Guide


Adjusting Parallax Intensity


Subtle Effect (Slower Parallax):

1body { 2 perspective: 2px; /* Less dramatic */ 3} 4 5.slide:before { 6 transform: translateZ(-0.5px) scale(1.5); /* Milder effect */ 7}

Dramatic Effect (Faster Parallax):

1body { 2 perspective: 0.5px; /* Very close perspective */ 3} 4 5.slide:before { 6 transform: translateZ(-2px) scale(3); /* More intense */ 7}

Adding More Depth Layers


1/* Create more layers with different Z-depths */ 2.layer-1 { transform: translateZ(-2px) scale(3); } /* Fastest */ 3.layer-2 { transform: translateZ(-1px) scale(2); } /* Fast */ 4.layer-3 { transform: translateZ(0px) scale(1); } /* Normal */ 5.layer-4 { transform: translateZ(0.25px) scale(0.75); } /* Slow */ 6.layer-5 { transform: translateZ(0.5px) scale(0.5); } /* Slowest */

Each layer scrolls at different speed, creating rich depth.


Changing Colors & Backgrounds


1#slide1:before { 2 background-image: url("your-image.jpg"); 3 background-color: #333; /* Fallback color */ 4} 5 6#slide4 { 7 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 8}



⚡ Performance Tips


GPU Acceleration


1/* Ensure GPU acceleration */ 2.slide { 3 /* Force GPU acceleration */ 4 transform: translate3d(0, 0, 0); 5 will-change: transform; 6}

These properties signal browser to use GPU for rendering.


Image Optimization


1/* Use smaller images or WebP format for better performance */ 2img { 3 /* Consider lazy-loading via HTML attribute */ 4 /* <img loading="lazy" ... > */ 5}

Large images hurt scrolling performance. Optimize images:

  • Use appropriate dimensions
  • Compress heavily
  • Consider WebP format
  • Lazy load when possible

Reduce Element Count


Fewer elements = Better performance
- Minimize pseudo-elements
- Consolidate backgrounds
- Remove unnecessary styling



🚀 Final Thoughts


Why Pure CSS Parallax?


Advantages:

No JavaScript: No performance overhead ✅ Hardware Accelerated: GPU optimization ✅ Smooth: 60fps possible with modern browsers ✅ Accessible: Works without JavaScript ✅ SEO Friendly: Content visible to crawlers ✅ Mobile Optimized: Excellent mobile performance ✅ Future Proof: CSS is stable and evolving


When to Use:

  • Hero sections with depth
  • Magazine-style layouts
  • Portfolio showcases
  • Immersive storytelling
  • Visual-heavy presentations

Browser Compatibility Note


This technique uses:

  • CSS 3D Transforms (widespread support)

Love this component?

Explore more components and build amazing UIs.

View All Components