What Is Parallax Scrolling?
Parallax scrolling makes backgrounds move slower than foreground content as you scroll. It's like looking out a car
window: trees (background) move slower than the road (foreground). This adds depth and makes sites feel dynamic.
Technique 1: CSS Fixed Background
The key CSS property is
background-attachment: fixed
. This keeps the background image stationary while the content scrolls over it.
.parallax-bg {
background-image: url('image.jpg');
min-height: 400px;
background-attachment: fixed;
background-position: center;
background-size: cover;
}
Why Use It?
-
Engagement:
Makes sites more engaging (users scroll longer)
-
Storytelling:
Helps tell a story visually through layers
-
Depth:
Creates a sense of 3D space on a 2D screen
⚠️ Cautions:
- Can cause motion sickness in some users
- May impact performance on older devices
- Doesn't work well on mobile (iOS Safari doesn't support it)
- Use sparingly for best effect
Atelier Reflection:
Does the parallax effect make this page feel more "alive"? Why or why not? Does it enhance your understanding of the
content, or is it purely decorative? Consider the balance between visual interest and accessibility.
Comparison: Normal Scrolling
The section above uses
background-attachment: scroll
(the default). Notice how it scrolls with the content instead of staying fixed. This is the traditional approach.
Key Differences:
-
Parallax (fixed):
Background stays in place, content moves over it
-
Normal (scroll):
Background and content move together at the same speed
Tip:
Scroll up and down this page multiple times to really feel the difference between the purple (parallax) and green
(normal) sections!
Mobile Considerations
On mobile devices,
background-attachment: fixed
often doesn't work due to browser limitations. The CSS in this demo automatically switches to regular scrolling on
smaller screens to ensure a good experience for all users.
Critical Design Question:
Is the parallax effect truly enhancing the user experience, or could it be a barrier? Consider users with vestibular
disorders who may experience discomfort with motion effects. How might we offer alternatives or respect the
prefers-reduced-motion
media query?
Technique 2: JavaScript Parallax with Multiple Layers
The section above uses
JavaScript with
transform: translateY()
to move three separate layers at different speeds. This creates a more sophisticated depth effect than pure CSS.
Understanding the 3-Layer System
Each layer has a data-speed attribute:
- Back layer (🌌):
data-speed="0.2" - Moves very slowly (distant background)
- Middle layer (☁️):
data-speed="0.5" - Moves at medium speed
- Front layer (text):
data-speed="0.8" - Moves fastest (closest to viewer)
Step 1: HTML Structure with data-speed
<div class="parallax-js-section">
<!-- Each layer moves at different speed -->
<div class="parallax-layer layer-back" data-speed="0.2">🌌</div>
<div class="parallax-layer layer-middle" data-speed="0.5">☁️</div>
<div class="parallax-layer layer-front" data-speed="0.8">Text</div>
</div>
Step 2: JavaScript reads data-speed and applies transform
// 1. Select all layers
const parallaxLayers = document.querySelectorAll('.parallax-layer');
// 2. On scroll, update each layer's position
function updateParallax() {
parallaxLayers.forEach((layer) => {
// Read the speed value from HTML attribute
const speed = parseFloat(layer.dataset.speed);
// Calculate how much to move this layer
const scrolled = window.pageYOffset;
const yPos = scrolled * speed * 0.5;
// Apply the transform
layer.style.transform = `translateY(${yPos}px)`;
});
}
// 3. Listen to scroll events efficiently
window.addEventListener('scroll', () => {
requestAnimationFrame(updateParallax);
}, { passive: true });
Advantages of JavaScript Parallax:
-
Precise Control:
You can control exactly how fast each layer moves
-
Multiple Elements:
Move any HTML element, not just backgrounds
-
Works on Mobile:
Unlike
background-attachment: fixed
-
Complex Animations:
Combine with opacity, scale, rotation, etc.
⚠️ Considerations:
- Requires JavaScript (fallback if JS is disabled)
-
Use
requestAnimationFrame
for better performance
-
Respect
prefers-reduced-motion
♿ Accessibility: Respecting User Preferences
⚠️ Important: Motion Sensitivity
Parallax effects can cause motion sickness, dizziness, or vestibular disorders for some users.
It's essential to respect the prefers-reduced-motion media query.
What is prefers-reduced-motion?
prefers-reduced-motion is a CSS media query that detects if a user has requested reduced motion
in their operating system settings. Users can enable this in:
- macOS: System Preferences → Accessibility → Display → Reduce motion
- Windows: Settings → Ease of Access → Display → Show animations
- iOS: Settings → Accessibility → Motion → Reduce Motion
- Android: Settings → Accessibility → Remove animations
How This Demo Respects It
This demo automatically disables parallax effects when users have motion reduction enabled:
// 1. Detect user's motion preference
const prefersReducedMotion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
);
let isReducedMotion = prefersReducedMotion.matches;
// 2. Disable CSS parallax if needed
function handleMotionPreference() {
if (isReducedMotion) {
// Change fixed backgrounds to scroll normally
document.querySelectorAll('.parallax-bg').forEach((el) => {
el.style.backgroundAttachment = 'scroll';
});
}
}
// 3. Don't initialize JavaScript parallax if reduced motion
function initParallax() {
if (isReducedMotion) {
console.log('Parallax disabled: user prefers reduced motion');
return; // Exit without setting up animations
}
// ... rest of parallax code
}
// 4. Listen for preference changes during session
prefersReducedMotion.addEventListener('change', (e) => {
isReducedMotion = e.matches;
// Update animations accordingly
});
Test It Yourself
- Open your browser's DevTools (F12)
- Go to the Console tab and type:
window.matchMedia('(prefers-reduced-motion: reduce)').matches
- It returns
true if reduce motion is enabled, false otherwise
- Enable "Reduce motion" in your OS settings and refresh this page
- Notice how all parallax effects are disabled!
💡 Best Practices for Accessibility
- Always respect prefers-reduced-motion - It's a user request, not a suggestion
- Provide fallbacks: Ensure content is accessible without motion
- Don't just reduce: Disable motion entirely when requested
- Test thoroughly: Check with motion reduction enabled
- Semantic HTML: Use proper structure that works regardless of effects
Technique 3: Multi-Layer Images
The section above combines multiple background images moving at different speeds to create a 3D depth effect.
📊 Comparison of All 3 Techniques:
| Technique |
Implementation |
Mobile Support |
Complexity |
| CSS Fixed |
background-attachment: fixed |
❌ Limited |
⭐ Very simple |
| JS Transform |
transform: translateY() |
✅ Works |
⭐⭐ Medium |
| Multi-layer |
Multiple elements + JS |
✅ Works |
⭐⭐⭐ Advanced |
Final Reflection:
Which technique do you prefer? CSS is perfect for simple sites. JavaScript offers full control but requires more
code. Multi-layer creates the most impressive effects but may impact performance.
The best choice depends on your specific project.