You actually can make pure CSS parallax effects without the need for background-image
or background-attachment
. Keith Clark has a great write up & tutorial on it. I'm going to borrow his code for the sake of the example:
HTML
<div class="parallax">
<div class="parallax__layer parallax__layer--back">
...
</div>
<div class="parallax__layer parallax__layer--base">
...
</div>
</div>
CSS
.parallax {
perspective: 1px;
height: 100vh;
overflow-x: hidden;
overflow-y: auto;
}
.parallax__layer {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.parallax__layer--base {
transform: translateZ(0);
}
.parallax__layer--back {
transform: translateZ(-1px) scale(2);
}
It's actually quite a simple solution, but it might take a second to grasp how it's all happening. The big thing that's going on here is the transform: translateZ(-1px) scale(2)
, which moves that <div>
back along the z-axis and resizes it back to normal. Setting the z-axis is how the speed of the parallax is controlled. So translateZ(-1px)
is slower than translateZ(-2px)
.
Now that the div has been moved back in the z-axis, it needs to be resized back to its normal size. To do that, you simply add scale
to the transform
property. The scale must be calculated using 1 + (translateZ * -1) / perspective
. So transform: translateZ(-10px)
should be transform: translateZ(-2px) scale(3)
assuming you keep the perspective
set to 1px
.
Then the perspective
is changed to 1px
for the .parallax
container which will set the <div>
perspective to the center. Adding overflow-y: auto
allows content to scroll normally, but descendant elements will be rendered to the fixed perspective.
Since this just uses <div>
's and CSS, you should be able to solve your problem without JS. You can easily just place your images within the divs. This is a simple demo that shows just a single <div>
parallax effect. If you look at the source code, you'll see no JavaScript except the part for Google Analytics. Here's a demo with a ton of different sections.
I recommend you read this tutorial, as the code should do everything you want. Plus it works flawlessly on iOS, Safari, Chrome, & FF. I've used it a number of times, and I can't recommend the method enough. Needless to say I borrowed much of my answer from that tutorial, so props to Keith Clark for the great write up.