Make a parallax effect with 10 lines of JavaScript

ibrahima92 profile image Ibrahima Ndaw Updated on ・3 min read

Originally posted on my blog

In this post, we're going to make a nice Parallax effect with HTML, CSS and just 10 lines of JavaScript.

You can check it live here


As you can see, we start by wrapping our elements in the main tag.

        <div class="container">
          <i class="fas fa-5x fa-laugh"></i>
          <p>Scroll to see how cool i am!</p>

        <h3>Cool like you</h3>

Then, we use two tags to make the parallax effect. The first tag, header holds the elements displayed when the page loads, and the second one, section will be fired on scroll to start the effect.


As usual, we start by doing some resets and import the needed font.

@import url("https://fonts.googleapis.com/css?family=Courgette:400,700&display=swap");
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;

body {
  background: linear-gradient(135deg, #0056a7, #165fa3, #477aaa);
  font-family: "Courgette", cursive;

header {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  position: relative;
  height: 100vh;
  color: #eee;
  z-index: -1;
  text-align: center;
  animation: fadeIn 1.5s ease-in-out;

Then, we use position:relative to be able to control the position of the header tag, and when the effect will start the property z-index:-1 will place the header tag behind the section element.

section {
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
  height: 100vh;
  font-size: 5rem;
  background: #fcdb6d;
  color: #0056a7;

Here, we use the opposite for the section selector, by assigning the z-index property to 1 to literally place the section tag above the header when we start scrolling.

.animate-me {
  animation: bounceIn 3s ease-in-out;

@keyframes fadeIn {
  from {
    opacity: 0;
  to {
    opacity: 1;

@keyframes bounceIn {
  0% {
    transform: scale(0.1);
    opacity: 0;
  60% {
    transform: scale(1.2);
    opacity: 1;
  100% {
    transform: scale(1);

And last but not the least, we make some animations for the elements entrance. With the bouncing effect for the section and the fading effect for the header. The class animate-me will be added to the section later through JavaScript.


We'll finally make the magic happen with JavaScript, to be able to make the parallax effect when we scroll.

window.addEventListener("scroll", function() {
  const distance = window.scrollY;
  document.querySelector("header").style.transform = `translateY(${distance *
  ).style.transform = `translateY(${distance * 0.3}px)`;
  setTimeout(() => {
    document.querySelector("section h3").classList.add("animate-me");
  }, 400);

As you can see here, we listen to the scroll event to start the effect.

Then, we assign to the constant distance the amount of scroll through the Y-axis(vertically). And select the needed elements from the DOM and access to the transform property.
With that, we can now use the translateY value to dynamically give value to translateY. The value differs between header and its child element container to just have a smoother effect. Then, we finish up everything, by adding the animate-me class for the section title for the bouncing effect.

That's all folks!

You can check it live here


Posted on by:

ibrahima92 profile

Ibrahima Ndaw


JavaScript enthusiast, Full-stack developer and blogger


markdown guide

As a performance improvement, move the document.querySelector calls outside the scroll event listener, assigned to variables. That way, the browser only has to traverse the DOM once instead of on every scroll event which is what’s happening now. And then, look into throttle to limit the handler calls as scroll fires at a very high rate.


You're absolutely right. I always use selectors in that way. For a real apps, i should control the scroll with a debounce function, but for this quick may be it's not mandatory. So thanks again for your very useful comment.


Just as an FYI for anyone reading. As a reminder, these types of things are basically an anti-pattern for UX and accessibility. They may be fancy and pretty at face value, but suffer issues in different user agents and for screen readers. These tend to suffer even more when transitioning between touch, mouse wheel, mouse drag, scroll bar, arrow keys, and page up/down keys. And that's before even getting into javascriptless browsing.


Nice one!

See also: this trick with perspective and translateZ properties



Thanks for sharing your resource.


If you reduce the height of the window, you can scroll forever 😁


It's not that much responsive, i will soon.


Parallax is absolutely awful and needs to die.